MyGUI 3.0.1

MyGUI_InputManager.cpp

Go to the documentation of this file.
00001 
00007 /*
00008     This file is part of MyGUI.
00009 
00010     MyGUI is free software: you can redistribute it and/or modify
00011     it under the terms of the GNU Lesser General Public License as published by
00012     the Free Software Foundation, either version 3 of the License, or
00013     (at your option) any later version.
00014 
00015     MyGUI is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU Lesser General Public License for more details.
00019 
00020     You should have received a copy of the GNU Lesser General Public License
00021     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00022 */
00023 #include "MyGUI_Precompiled.h"
00024 #include "MyGUI_InputManager.h"
00025 #include "MyGUI_Widget.h"
00026 #include "MyGUI_WidgetManager.h"
00027 #include "MyGUI_Gui.h"
00028 #include "MyGUI_WidgetManager.h"
00029 
00030 namespace MyGUI
00031 {
00032     const unsigned long INPUT_TIME_DOUBLE_CLICK = 250; //measured in milliseconds
00033     const float INPUT_DELAY_FIRST_KEY = 0.4f;
00034     const float INPUT_INTERVAL_KEY = 0.05f;
00035 
00036     MYGUI_INSTANCE_IMPLEMENT( InputManager )
00037 
00038     void InputManager::initialise()
00039     {
00040         MYGUI_ASSERT(!mIsInitialise, INSTANCE_TYPE_NAME << " initialised twice");
00041         MYGUI_LOG(Info, "* Initialise: " << INSTANCE_TYPE_NAME);
00042 
00043         mWidgetMouseFocus = 0;
00044         mWidgetKeyFocus = 0;
00045         mLayerMouseFocus = 0;
00046         mIsWidgetMouseCapture = false;
00047         mIsShiftPressed = false;
00048         mIsControlPressed = false;
00049         mHoldKey = KeyCode::None;
00050         mHoldChar = 0;
00051         mFirstPressKey = true;
00052         mTimerKey = 0.0f;
00053         mOldAbsZ = 0;
00054 
00055         WidgetManager::getInstance().registerUnlinker(this);
00056         Gui::getInstance().eventFrameStart += newDelegate(this, &InputManager::frameEntered);
00057 
00058         MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully initialized");
00059         mIsInitialise = true;
00060     }
00061 
00062     void InputManager::shutdown()
00063     {
00064         if (!mIsInitialise) return;
00065         MYGUI_LOG(Info, "* Shutdown: " << INSTANCE_TYPE_NAME);
00066 
00067         Gui::getInstance().eventFrameStart -= newDelegate(this, &InputManager::frameEntered);
00068         WidgetManager::getInstance().unregisterUnlinker(this);
00069 
00070         MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully shutdown");
00071         mIsInitialise = false;
00072     }
00073 
00074     bool InputManager::injectMouseMove(int _absx, int _absy, int _absz)
00075     {
00076         // запоминаем позицию
00077         mMousePosition.set(_absx, _absy);
00078 
00079         // вычисляем прирост по колеса
00080         int relz = _absz - mOldAbsZ;
00081         mOldAbsZ = _absz;
00082 
00083         // проверка на скролл
00084         if (relz != 0)
00085         {
00086             bool isFocus = isFocusMouse();
00087             if (mWidgetMouseFocus != nullptr) mWidgetMouseFocus->onMouseWheel(relz);
00088             return isFocus;
00089         }
00090 
00091         if (mIsWidgetMouseCapture)
00092         {
00093             if (mWidgetMouseFocus != nullptr)
00094             {
00095                 if (mLayerMouseFocus != nullptr)
00096                 {
00097                     IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
00098                     mWidgetMouseFocus->onMouseDrag(point.left, point.top);
00099                 }
00100             }
00101             else
00102                 mIsWidgetMouseCapture = false;
00103             return true;
00104         }
00105 
00106         Widget* old_mouse_focus = mWidgetMouseFocus;
00107 
00108         // ищем активное окно
00109         Widget* item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);
00110 
00111         // ничего не изменилось
00112         if (mWidgetMouseFocus == item)
00113         {
00114             bool isFocus = isFocusMouse();
00115             if (mWidgetMouseFocus != nullptr)
00116             {
00117                 if (mLayerMouseFocus != nullptr)
00118                 {
00119                     IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
00120                     mWidgetMouseFocus->onMouseMove(_absx, _absy);
00121                 }
00122             }
00123             return isFocus;
00124         }
00125 
00126         if (item)
00127         {
00128             // поднимаемся до рута
00129             Widget* root = item;
00130             while (root->getParent()) root = root->getParent();
00131 
00132             // проверяем на модальность
00133             if (!mVectorModalRootWidget.empty())
00134             {
00135                 if (root != mVectorModalRootWidget.back())
00136                 {
00137                     item = nullptr;
00138                 }
00139             }
00140 
00141             if (item != nullptr)
00142             {
00143                 mLayerMouseFocus = root->getLayer();
00144             }
00145         }
00146 
00147         // в методе может пропасть наш виджет
00148         WidgetManager::getInstance().addWidgetToUnlink(item);
00149 
00150 
00151         //-------------------------------------------------------------------------------------//
00152         // новый вид рутового фокуса мыши
00153         Widget* save_widget = nullptr;
00154 
00155         // спускаемся по новому виджету и устанавливаем рутовый фокус
00156         Widget* root_focus = item;
00157         while (root_focus != nullptr)
00158         {
00159             if (root_focus->mRootMouseActive)
00160             {
00161                 save_widget = root_focus;
00162                 break;
00163             }
00164             root_focus->mRootMouseActive = true;
00165 
00166             // в методе может пропасть наш виджет
00167             WidgetManager::getInstance().addWidgetToUnlink(root_focus);
00168             root_focus->onMouseChangeRootFocus(true);
00169             WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
00170 
00171             if (root_focus)
00172                 root_focus = root_focus->getParent();
00173         }
00174 
00175         // спускаемся по старому виджету и сбрасываем фокус
00176         root_focus = mWidgetMouseFocus;
00177         while (root_focus != nullptr)
00178         {
00179             if (root_focus == save_widget)
00180             {
00181                 break;
00182             }
00183             root_focus->mRootMouseActive = false;
00184 
00185             // в методе может пропасть наш виджет
00186             WidgetManager::getInstance().addWidgetToUnlink(root_focus);
00187             root_focus->onMouseChangeRootFocus(false);
00188             WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
00189 
00190             if (root_focus)
00191                 root_focus = root_focus->getParent();
00192         }
00193         //-------------------------------------------------------------------------------------//
00194 
00195         // смена фокуса, проверяем на доступность виджета
00196         if ((mWidgetMouseFocus != nullptr) && (mWidgetMouseFocus->isEnabled()))
00197         {
00198             mWidgetMouseFocus->onMouseLostFocus(item);
00199         }
00200 
00201         WidgetManager::getInstance().removeWidgetFromUnlink(item);
00202 
00203 
00204         if ((item != nullptr) && (item->isEnabled()))
00205         {
00206             item->onMouseMove(_absx, _absy);
00207             item->onMouseSetFocus(mWidgetMouseFocus);
00208         }
00209 
00210         // запоминаем текущее окно
00211         mWidgetMouseFocus = item;
00212 
00213         if (old_mouse_focus != mWidgetMouseFocus)
00214             eventChangeMouseFocus(mWidgetMouseFocus);
00215 
00216         return isFocusMouse();
00217     }
00218 
00219     bool InputManager::injectMousePress(int _absx, int _absy, MouseButton _id)
00220     {
00221         Widget* old_key_focus = mWidgetKeyFocus;
00222 
00223         // если мы щелкнули не на гуй
00224         if (!isFocusMouse())
00225         {
00226             resetKeyFocusWidget();
00227 
00228             if (old_key_focus != mWidgetKeyFocus)
00229                 eventChangeKeyFocus(mWidgetKeyFocus);
00230 
00231             return false;
00232         }
00233 
00234         // если активный элемент заблокирован
00235         //FIXME
00236         if (!mWidgetMouseFocus->isEnabled())
00237             return true;
00238 
00239         // захватываем только по левой клавише и только если виджету надо
00240         if (MouseButton::Left == _id)
00241         {
00242             // захват окна
00243             mIsWidgetMouseCapture = true;
00244             // запоминаем место нажатия
00245             if (mLayerMouseFocus != nullptr)
00246             {
00247                 IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
00248                 mLastLeftPressed = point;
00249             }
00250         }
00251 
00252         // ищем вверх тот виджет который может принимать фокус
00253         Widget* item = mWidgetMouseFocus;
00254         while ((item != nullptr) && (!item->isNeedKeyFocus()))
00255             item = item->getParent();
00256 
00257         // устанавливаем перед вызовом т.к. возможно внутри ктонить поменяет фокус под себя
00258         setKeyFocusWidget(item);
00259 
00260         if (mWidgetMouseFocus != nullptr)
00261         {
00262             mWidgetMouseFocus->onMouseButtonPressed(_absx, _absy, _id);
00263 
00264             // после пресса может сброситься
00265             if (mWidgetMouseFocus)
00266             {
00267                 // поднимаем виджет, надо подумать что делать если поменялся фокус клавы
00268                 LayerManager::getInstance().upLayerItem(mWidgetMouseFocus);
00269 
00270                 // поднимаем пикинг Overlapped окон
00271                 Widget* pick = mWidgetMouseFocus;
00272                 do
00273                 {
00274                     // если оверлаппед, то поднимаем пикинг
00275                     if (pick->getWidgetStyle() == WidgetStyle::Overlapped)
00276                     {
00277                         if (pick->getParent()) pick->getParent()->_forcePeek(pick);
00278                     }
00279 
00280                     pick = pick->getParent();
00281                 }
00282                 while (pick);
00283             }
00284         }
00285 
00286         if (old_key_focus != mWidgetKeyFocus)
00287             eventChangeKeyFocus(mWidgetKeyFocus);
00288 
00289         return true;
00290     }
00291 
00292     bool InputManager::injectMouseRelease(int _absx, int _absy, MouseButton _id)
00293     {
00294         if (isFocusMouse())
00295         {
00296             // если активный элемент заблокирован
00297             if (!mWidgetMouseFocus->isEnabled())
00298                 return true;
00299 
00300             mWidgetMouseFocus->onMouseButtonReleased(_absx, _absy, _id);
00301 
00302             if (mIsWidgetMouseCapture)
00303             {
00304                 // сбрасываем захват
00305                 mIsWidgetMouseCapture = false;
00306 
00307                 // после вызова, виджет может быть сброшен
00308                 if (nullptr != mWidgetMouseFocus)
00309                 {
00310                     if ((MouseButton::Left == _id) && mTimer.getMilliseconds() < INPUT_TIME_DOUBLE_CLICK)
00311                     {
00312                         mWidgetMouseFocus->onMouseButtonClick();
00313                         // после вызова, виджет может быть сброшен
00314                         if (nullptr != mWidgetMouseFocus) mWidgetMouseFocus->onMouseButtonDoubleClick();
00315                     }
00316                     else
00317                     {
00318                         // проверяем над тем ли мы окном сейчас что и были при нажатии
00319                         Widget* item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);
00320                         if ( item == mWidgetMouseFocus)
00321                         {
00322                             mWidgetMouseFocus->onMouseButtonClick();
00323                         }
00324                         mTimer.reset();
00325                     }
00326                 }
00327             }
00328 
00329             // для корректного отображения
00330             injectMouseMove(_absx, _absy, mOldAbsZ);
00331 
00332             return true;
00333         }
00334 
00335         return false;
00336     }
00337 
00338     bool InputManager::injectKeyPress(KeyCode _key, Char _text)
00339     {
00340         // проверка на переключение языков
00341         firstEncoding(_key, true);
00342 
00343         // запоминаем клавишу
00344         storeKey(_key, _text);
00345 
00346         bool wasFocusKey = isFocusKey();
00347 
00348         //Pass keystrokes to the current active text widget
00349         if (isFocusKey())
00350         {
00351             mWidgetKeyFocus->onKeyButtonPressed(_key, _text);
00352         }
00353 
00354         return wasFocusKey;
00355     }
00356 
00357     bool InputManager::injectKeyRelease(KeyCode _key)
00358     {
00359         // проверка на переключение языков
00360         firstEncoding(_key, false);
00361 
00362         // сбрасываем клавишу
00363         resetKey();
00364 
00365         bool wasFocusKey = isFocusKey();
00366 
00367         if (isFocusKey()) mWidgetKeyFocus->onKeyButtonReleased(_key);
00368 
00369         return wasFocusKey;
00370     }
00371 
00372     void InputManager::firstEncoding(KeyCode _key, bool bIsKeyPressed)
00373     {
00374         if ((_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift))
00375             mIsShiftPressed = bIsKeyPressed;
00376         if ((_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl))
00377             mIsControlPressed = bIsKeyPressed;
00378     }
00379 
00380     void InputManager::setKeyFocusWidget(Widget* _widget)
00381     {
00382         if (_widget == mWidgetKeyFocus)
00383             return;
00384 
00385         //-------------------------------------------------------------------------------------//
00386         // новый вид рутового фокуса
00387         Widget* save_widget = nullptr;
00388 
00389         // спускаемся по новому виджету и устанавливаем рутовый фокус
00390         Widget* root_focus = _widget;
00391         while (root_focus != nullptr)
00392         {
00393             if (root_focus->mRootKeyActive)
00394             {
00395                 save_widget = root_focus;
00396                 break;
00397             }
00398             root_focus->mRootKeyActive = true;
00399 
00400             // в методе может пропасть наш виджет
00401             WidgetManager::getInstance().addWidgetToUnlink(root_focus);
00402             root_focus->onKeyChangeRootFocus(true);
00403             WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
00404 
00405             if (root_focus)
00406                 root_focus = root_focus->getParent();
00407         }
00408 
00409         // спускаемся по старому виджету и сбрасываем фокус
00410         root_focus = mWidgetKeyFocus;
00411         while (root_focus != nullptr)
00412         {
00413             if (root_focus == save_widget)
00414             {
00415                 break;
00416             }
00417             root_focus->mRootKeyActive = false;
00418 
00419             // в методе может пропасть наш виджет
00420             WidgetManager::getInstance().addWidgetToUnlink(root_focus);
00421             root_focus->onKeyChangeRootFocus(false);
00422             WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
00423 
00424             if (root_focus)
00425                 root_focus = root_focus->getParent();
00426         }
00427         //-------------------------------------------------------------------------------------//
00428 
00429         // сбрасываем старый
00430         if (mWidgetKeyFocus)
00431         {
00432             mWidgetKeyFocus->onKeyLostFocus(_widget);
00433         }
00434 
00435         // устанавливаем новый
00436         if (_widget && _widget->isNeedKeyFocus())
00437         {
00438             _widget->onKeySetFocus(mWidgetKeyFocus);
00439         }
00440 
00441         mWidgetKeyFocus = _widget;
00442     }
00443 
00444     void InputManager::resetMouseFocusWidget()
00445     {
00446         // спускаемся по старому виджету и сбрасываем фокус
00447         Widget* root_focus = mWidgetMouseFocus;
00448         while (root_focus != nullptr)
00449         {
00450             root_focus->mRootMouseActive = false;
00451 
00452             // в методе может пропасть наш виджет
00453             WidgetManager::getInstance().addWidgetToUnlink(root_focus);
00454             root_focus->onMouseChangeRootFocus(false);
00455             WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
00456 
00457             if (root_focus)
00458                 root_focus = root_focus->getParent();
00459         }
00460 
00461         mIsWidgetMouseCapture = false;
00462         if (nullptr != mWidgetMouseFocus)
00463         {
00464             mWidgetMouseFocus->onMouseLostFocus(nullptr);
00465             mWidgetMouseFocus = nullptr;
00466         }
00467 
00468     }
00469 
00470     // удаляем данный виджет из всех возможных мест
00471     void InputManager::_unlinkWidget(Widget* _widget)
00472     {
00473         if (nullptr == _widget) return;
00474         if (_widget == mWidgetMouseFocus)
00475         {
00476             mIsWidgetMouseCapture = false;
00477             mWidgetMouseFocus = nullptr;
00478         }
00479         if (_widget == mWidgetKeyFocus)
00480         {
00481             mWidgetKeyFocus = nullptr;
00482         }
00483 
00484         // ручками сбрасываем, чтобы не менять фокусы
00485         for (VectorWidgetPtr::iterator iter=mVectorModalRootWidget.begin(); iter!=mVectorModalRootWidget.end(); ++iter)
00486         {
00487             if ((*iter == _widget))
00488             {
00489                 mVectorModalRootWidget.erase(iter);
00490                 break;
00491             }
00492         }
00493 
00494     }
00495 
00496     void InputManager::addWidgetModal(Widget* _widget)
00497     {
00498         if (nullptr == _widget) return;
00499         MYGUI_ASSERT(nullptr == _widget->getParent(), "Modal widget must be root");
00500 
00501         resetMouseFocusWidget();
00502         removeWidgetModal(_widget);
00503         mVectorModalRootWidget.push_back(_widget);
00504 
00505         setKeyFocusWidget(_widget);
00506         LayerManager::getInstance().upLayerItem(_widget);
00507     }
00508 
00509     void InputManager::removeWidgetModal(Widget* _widget)
00510     {
00511         resetKeyFocusWidget(_widget);
00512         resetMouseFocusWidget();
00513 
00514         for (VectorWidgetPtr::iterator iter=mVectorModalRootWidget.begin(); iter!=mVectorModalRootWidget.end(); ++iter)
00515         {
00516             if ((*iter == _widget))
00517             {
00518                 mVectorModalRootWidget.erase(iter);
00519                 break;
00520             }
00521         }
00522         // если еще есть модальные то их фокусируем и поднимаем
00523         if (!mVectorModalRootWidget.empty())
00524         {
00525             setKeyFocusWidget(mVectorModalRootWidget.back());
00526             LayerManager::getInstance().upLayerItem(mVectorModalRootWidget.back());
00527         }
00528     }
00529 
00530     void InputManager::storeKey(KeyCode _key, Char _text)
00531     {
00532         mHoldKey = KeyCode::None;
00533         mHoldChar = 0;
00534 
00535         if ( !isFocusKey() ) return;
00536         if ( (_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift)
00537             || (_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl)
00538             || (_key == KeyCode::LeftAlt) || (_key == KeyCode::RightAlt)
00539             ) return;
00540 
00541         mFirstPressKey = true;
00542         mHoldKey = _key;
00543         mHoldChar = _text;
00544         mTimerKey = 0.0f;
00545     }
00546 
00547     void InputManager::resetKey()
00548     {
00549         mHoldKey = KeyCode::None;
00550         mHoldChar = 0;
00551     }
00552 
00553     void InputManager::frameEntered(float _frame)
00554     {
00555         if ( mHoldKey == KeyCode::None)
00556             return;
00557 
00558         if ( !isFocusKey() )
00559         {
00560             mHoldKey = KeyCode::None;
00561             mHoldChar = 0;
00562             return;
00563         }
00564 
00565         mTimerKey += _frame;
00566 
00567         if (mFirstPressKey)
00568         {
00569             if (mTimerKey > INPUT_DELAY_FIRST_KEY)
00570             {
00571                 mFirstPressKey = false;
00572                 mTimerKey = 0.0f;
00573             }
00574         }
00575         else
00576         {
00577             if (mTimerKey > INPUT_INTERVAL_KEY)
00578             {
00579                 while (mTimerKey > INPUT_INTERVAL_KEY) mTimerKey -= INPUT_INTERVAL_KEY;
00580                 mWidgetKeyFocus->onKeyButtonPressed(mHoldKey, mHoldChar);
00581                 // focus can be dropped in onKeyButtonPressed
00582                 if ( isFocusKey() ) mWidgetKeyFocus->onKeyButtonReleased(mHoldKey);
00583             }
00584         }
00585 
00586     }
00587 
00588     void InputManager::resetKeyFocusWidget(Widget* _widget)
00589     {
00590         if (mWidgetKeyFocus == _widget)
00591             setKeyFocusWidget(nullptr);
00592     }
00593 
00594     IntPoint InputManager::getMousePositionByLayer()
00595     {
00596         if (mLayerMouseFocus != nullptr)
00597             return mLayerMouseFocus->getPosition(mMousePosition.left, mMousePosition.top);
00598         return mMousePosition;
00599     }
00600 
00601 } // namespace MyGUI
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines