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