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