• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

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_Common.h"
00025 #include "MyGUI_InputManager.h"
00026 #include "MyGUI_Widget.h"
00027 #include "MyGUI_WidgetManager.h"
00028 #include "MyGUI_Gui.h"
00029 #include "MyGUI_WidgetManager.h"
00030 
00031 namespace MyGUI
00032 {
00033     const unsigned long INPUT_TIME_DOUBLE_CLICK = 250; //measured in milliseconds
00034     const float INPUT_DELAY_FIRST_KEY = 0.4f;
00035     const float INPUT_INTERVAL_KEY = 0.05f;
00036 
00037     MYGUI_INSTANCE_IMPLEMENT(InputManager);
00038 
00039     void InputManager::initialise()
00040     {
00041         MYGUI_ASSERT(false == mIsInitialise, INSTANCE_TYPE_NAME << " initialised twice");
00042         MYGUI_LOG(Info, "* Initialise: " << INSTANCE_TYPE_NAME);
00043 
00044         mWidgetMouseFocus = 0;
00045         mWidgetKeyFocus = 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 (false == 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) mWidgetMouseFocus->onMouseDrag(_absx, _absy);
00094             else mIsWidgetMouseCapture = false;
00095             return true;
00096         }
00097 
00098         WidgetPtr old_mouse_focus = mWidgetMouseFocus;
00099 
00100         // ищем активное окно
00101         WidgetPtr item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);
00102 
00103         // ничего не изменилось
00104         if (mWidgetMouseFocus == item)
00105         {
00106             bool isFocus = isFocusMouse();
00107             if (mWidgetMouseFocus != nullptr) mWidgetMouseFocus->onMouseMove(_absx, _absy);
00108             return isFocus;
00109         }
00110 
00111         if (item)
00112         {
00113             // поднимаемся до рута
00114             WidgetPtr root = item;
00115             while (root->getParent()) root = root->getParent();
00116 
00117             // проверяем на модальность
00118             if (!mVectorModalRootWidget.empty())
00119             {
00120                 if (root != mVectorModalRootWidget.back())
00121                 {
00122                     item = nullptr;
00123                 }
00124             }
00125         }
00126 
00127         // в методе может пропасть наш виджет
00128         WidgetManager::getInstance().addWidgetToUnlink(item);
00129 
00130 
00131         //-------------------------------------------------------------------------------------//
00132         // новый вид рутового фокуса мыши
00133         WidgetPtr save_widget = nullptr;
00134 
00135         // спускаемся по новому виджету и устанавливаем рутовый фокус
00136         WidgetPtr root_focus = item;
00137         while (root_focus != nullptr)
00138         {
00139             if (root_focus->mRootMouseActive)
00140             {
00141                 save_widget = root_focus;
00142                 break;
00143             }
00144             root_focus->mRootMouseActive = true;
00145 
00146             // в методе может пропасть наш виджет
00147             WidgetManager::getInstance().addWidgetToUnlink(root_focus);
00148             root_focus->onMouseChangeRootFocus(true);
00149             WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
00150 
00151             if (root_focus)
00152                 root_focus = root_focus->getParent();
00153         };
00154 
00155         // спускаемся по старому виджету и сбрасываем фокус
00156         root_focus = mWidgetMouseFocus;
00157         while (root_focus != nullptr)
00158         {
00159             if (root_focus == save_widget)
00160             {
00161                 break;
00162             }
00163             root_focus->mRootMouseActive = false;
00164 
00165             // в методе может пропасть наш виджет
00166             WidgetManager::getInstance().addWidgetToUnlink(root_focus);
00167             root_focus->onMouseChangeRootFocus(false);
00168             WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
00169 
00170             if (root_focus)
00171                 root_focus = root_focus->getParent();
00172         };
00173         //-------------------------------------------------------------------------------------//
00174 
00175         // смена фокуса, проверяем на доступность виджета
00176         if ((mWidgetMouseFocus != nullptr) && (mWidgetMouseFocus->isEnabled()))
00177         {
00178             mWidgetMouseFocus->onMouseLostFocus(item);
00179         }
00180 
00181         WidgetManager::getInstance().removeWidgetFromUnlink(item);
00182 
00183 
00184         if ((item != nullptr) && (item->isEnabled()))
00185         {
00186             item->onMouseMove(_absx, _absy);
00187             item->onMouseSetFocus(mWidgetMouseFocus);
00188         }
00189 
00190         // запоминаем текущее окно
00191         mWidgetMouseFocus = item;
00192 
00193         if (old_mouse_focus != mWidgetMouseFocus)
00194             eventChangeMouseFocus(mWidgetMouseFocus);
00195 
00196         return isFocusMouse();
00197     }
00198 
00199     bool InputManager::injectMousePress(int _absx, int _absy, MouseButton _id)
00200     {
00201         WidgetPtr old_key_focus = mWidgetKeyFocus;
00202 
00203         // если мы щелкнули не на гуй
00204         if (false == isFocusMouse())
00205         {
00206             resetKeyFocusWidget();
00207 
00208             if (old_key_focus != mWidgetKeyFocus)
00209                 eventChangeKeyFocus(mWidgetKeyFocus);
00210 
00211             return false;
00212         }
00213 
00214         // если активный элемент заблокирован
00215         //FIXME
00216         if (false == mWidgetMouseFocus->isEnabled())
00217             return true;
00218 
00219         // захватываем только по левой клавише и только если виджету надо
00220         if (MouseButton::Left == _id)
00221         {
00222             // захват окна
00223             mIsWidgetMouseCapture = true;
00224             // запоминаем место нажатия
00225             mLastLeftPressed.set(_absx, _absy);
00226         }
00227 
00228         // ищем вверх тот виджет который может принимать фокус
00229         WidgetPtr item = mWidgetMouseFocus;
00230         while ((item != nullptr) && (false == item->isNeedKeyFocus()))
00231             item = item->getParent();
00232 
00233         // устанавливаем перед вызовом т.к. возможно внутри ктонить поменяет фокус под себя
00234         setKeyFocusWidget(item);
00235 
00236         if (mWidgetMouseFocus != nullptr)
00237         {
00238             mWidgetMouseFocus->onMouseButtonPressed(_absx, _absy, _id);
00239 
00240             // после пресса может сброситься
00241             if (mWidgetMouseFocus)
00242             {
00243                 // поднимаем виджет, надо подумать что делать если поменялся фокус клавы
00244                 LayerManager::getInstance().upLayerItem(mWidgetMouseFocus);
00245 
00246                 // поднимаем пикинг Overlapped окон
00247                 WidgetPtr pick = mWidgetMouseFocus;
00248                 do
00249                 {
00250                     // если оверлаппед, то поднимаем пикинг
00251                     if (pick->getWidgetStyle() == WidgetStyle::Overlapped)
00252                     {
00253                         if (pick->getParent()) pick->getParent()->_forcePeek(pick);
00254                     }
00255 
00256                     pick = pick->getParent();
00257                 }
00258                 while (pick);
00259             }
00260         }
00261 
00262         if (old_key_focus != mWidgetKeyFocus)
00263             eventChangeKeyFocus(mWidgetKeyFocus);
00264 
00265         return true;
00266     }
00267 
00268     bool InputManager::injectMouseRelease(int _absx, int _absy, MouseButton _id)
00269     {
00270         if (isFocusMouse())
00271         {
00272             // если активный элемент заблокирован
00273             if (false == mWidgetMouseFocus->isEnabled())
00274                 return true;
00275 
00276             mWidgetMouseFocus->onMouseButtonReleased(_absx, _absy, _id);
00277 
00278             if (mIsWidgetMouseCapture)
00279             {
00280                 // сбрасываем захват
00281                 mIsWidgetMouseCapture = false;
00282 
00283                 // после вызова, виджет может быть сброшен
00284                 if (nullptr != mWidgetMouseFocus)
00285                 {
00286                     if ((MouseButton::Left == _id) && mTimer.getMilliseconds() < INPUT_TIME_DOUBLE_CLICK)
00287                     {
00288                         mWidgetMouseFocus->onMouseButtonClick();
00289                         // после вызова, виджет может быть сброшен
00290                         if (nullptr != mWidgetMouseFocus) mWidgetMouseFocus->onMouseButtonDoubleClick();
00291                     }
00292                     else
00293                     {
00294                         // проверяем над тем ли мы окном сейчас что и были при нажатии
00295                         WidgetPtr item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);
00296                         if ( item == mWidgetMouseFocus)
00297                         {
00298                             mWidgetMouseFocus->onMouseButtonClick();
00299                         }
00300                         mTimer.reset();
00301                     }
00302                 }
00303             }
00304 
00305             // для корректного отображения
00306             injectMouseMove(_absx, _absy, mOldAbsZ);
00307 
00308             return true;
00309         }
00310 
00311         return false;
00312     }
00313 
00314     bool InputManager::injectKeyPress(KeyCode _key, Char _text)
00315     {
00316         // проверка на переключение языков
00317         firstEncoding(_key, true);
00318 
00319         // запоминаем клавишу
00320         storeKey(_key, _text);
00321 
00322         bool wasFocusKey = isFocusKey();
00323 
00324         //Pass keystrokes to the current active text widget
00325         if (isFocusKey())
00326         {
00327             mWidgetKeyFocus->onKeyButtonPressed(_key, _text);
00328         }
00329 
00330         return wasFocusKey;
00331     }
00332 
00333     bool InputManager::injectKeyRelease(KeyCode _key)
00334     {
00335         // проверка на переключение языков
00336         firstEncoding(_key, false);
00337 
00338         // сбрасываем клавишу
00339         resetKey();
00340 
00341         bool wasFocusKey = isFocusKey();
00342 
00343         if (isFocusKey()) mWidgetKeyFocus->onKeyButtonReleased(_key);
00344 
00345         return wasFocusKey;
00346     }
00347 
00348     void InputManager::firstEncoding(KeyCode _key, bool bIsKeyPressed)
00349     {
00350         if ((_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift))
00351             mIsShiftPressed = bIsKeyPressed;
00352         if ((_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl))
00353             mIsControlPressed = bIsKeyPressed;
00354     }
00355 
00356     void InputManager::setKeyFocusWidget(WidgetPtr _widget)
00357     {
00358         if (_widget == mWidgetKeyFocus)
00359             return;
00360 
00361         //-------------------------------------------------------------------------------------//
00362         // новый вид рутового фокуса
00363         WidgetPtr save_widget = nullptr;
00364 
00365         // спускаемся по новому виджету и устанавливаем рутовый фокус
00366         WidgetPtr root_focus = _widget;
00367         while (root_focus != nullptr)
00368         {
00369             if (root_focus->mRootKeyActive)
00370             {
00371                 save_widget = root_focus;
00372                 break;
00373             }
00374             root_focus->mRootKeyActive = true;
00375 
00376             // в методе может пропасть наш виджет
00377             WidgetManager::getInstance().addWidgetToUnlink(root_focus);
00378             root_focus->onKeyChangeRootFocus(true);
00379             WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
00380 
00381             if (root_focus)
00382                 root_focus = root_focus->getParent();
00383         };
00384 
00385         // спускаемся по старому виджету и сбрасываем фокус
00386         root_focus = mWidgetKeyFocus;
00387         while (root_focus != nullptr)
00388         {
00389             if (root_focus == save_widget)
00390             {
00391                 break;
00392             }
00393             root_focus->mRootKeyActive = false;
00394 
00395             // в методе может пропасть наш виджет
00396             WidgetManager::getInstance().addWidgetToUnlink(root_focus);
00397             root_focus->onKeyChangeRootFocus(false);
00398             WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
00399 
00400             if (root_focus)
00401                 root_focus = root_focus->getParent();
00402         };
00403         //-------------------------------------------------------------------------------------//
00404 
00405         // сбрасываем старый
00406         if (mWidgetKeyFocus)
00407         {
00408             mWidgetKeyFocus->onKeyLostFocus(_widget);
00409         }
00410 
00411         // устанавливаем новый
00412         if (_widget && _widget->isNeedKeyFocus())
00413         {
00414             _widget->onKeySetFocus(mWidgetKeyFocus);
00415         }
00416 
00417         mWidgetKeyFocus = _widget;
00418     }
00419 
00420     void InputManager::resetMouseFocusWidget()
00421     {
00422         // спускаемся по старому виджету и сбрасываем фокус
00423         WidgetPtr root_focus = mWidgetMouseFocus;
00424         while (root_focus != nullptr)
00425         {
00426             root_focus->mRootMouseActive = false;
00427 
00428             // в методе может пропасть наш виджет
00429             WidgetManager::getInstance().addWidgetToUnlink(root_focus);
00430             root_focus->onMouseChangeRootFocus(false);
00431             WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
00432 
00433             if (root_focus)
00434                 root_focus = root_focus->getParent();
00435         };
00436 
00437         mIsWidgetMouseCapture = false;
00438         if (nullptr != mWidgetMouseFocus)
00439         {
00440             mWidgetMouseFocus->onMouseLostFocus(nullptr);
00441             mWidgetMouseFocus = nullptr;
00442         }
00443 
00444     }
00445 
00446     // удаляем данный виджет из всех возможных мест
00447     void InputManager::_unlinkWidget(WidgetPtr _widget)
00448     {
00449         if (nullptr == _widget) return;
00450         if (_widget == mWidgetMouseFocus)
00451         {
00452             mIsWidgetMouseCapture = false;
00453             mWidgetMouseFocus = nullptr;
00454         }
00455         if (_widget == mWidgetKeyFocus)
00456         {
00457             mWidgetKeyFocus = nullptr;
00458         }
00459 
00460         // ручками сбрасываем, чтобы не менять фокусы
00461         for (VectorWidgetPtr::iterator iter=mVectorModalRootWidget.begin(); iter!=mVectorModalRootWidget.end(); ++iter)
00462         {
00463             if ((*iter == _widget))
00464             {
00465                 mVectorModalRootWidget.erase(iter);
00466                 break;
00467             }
00468         }
00469 
00470     }
00471 
00472     void InputManager::addWidgetModal(WidgetPtr _widget)
00473     {
00474         if (nullptr == _widget) return;
00475         MYGUI_ASSERT(nullptr == _widget->getParent(), "Modal widget must be root");
00476 
00477         resetMouseFocusWidget();
00478         removeWidgetModal(_widget);
00479         mVectorModalRootWidget.push_back(_widget);
00480 
00481         setKeyFocusWidget(_widget);
00482         LayerManager::getInstance().upLayerItem(_widget);
00483     }
00484 
00485     void InputManager::removeWidgetModal(WidgetPtr _widget)
00486     {
00487         resetKeyFocusWidget(_widget);
00488         resetMouseFocusWidget();
00489 
00490         for (VectorWidgetPtr::iterator iter=mVectorModalRootWidget.begin(); iter!=mVectorModalRootWidget.end(); ++iter)
00491         {
00492             if ((*iter == _widget))
00493             {
00494                 mVectorModalRootWidget.erase(iter);
00495                 break;
00496             }
00497         }
00498         // если еще есть модальные то их фокусируем и поднимаем
00499         if (false == mVectorModalRootWidget.empty())
00500         {
00501             setKeyFocusWidget(mVectorModalRootWidget.back());
00502             LayerManager::getInstance().upLayerItem(mVectorModalRootWidget.back());
00503         }
00504     }
00505 
00506     void InputManager::storeKey(KeyCode _key, Char _text)
00507     {
00508         mHoldKey = KeyCode::None;
00509         mHoldChar = 0;
00510 
00511         if ( false == isFocusKey() ) return;
00512         if ( (_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift)
00513             || (_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl)
00514             || (_key == KeyCode::LeftAlt) || (_key == KeyCode::RightAlt)
00515             ) return;
00516 
00517         mFirstPressKey = true;
00518         mHoldKey = _key;
00519         mHoldChar = _text;
00520         mTimerKey = 0.0f;
00521     }
00522 
00523     void InputManager::resetKey()
00524     {
00525         mHoldKey = KeyCode::None;
00526         mHoldChar = 0;
00527     }
00528 
00529     void InputManager::frameEntered(float _frame)
00530     {
00531         if ( mHoldKey == KeyCode::None)
00532             return;
00533 
00534         if ( false == isFocusKey() )
00535         {
00536             mHoldKey = KeyCode::None;
00537             mHoldChar = 0;
00538             return;
00539         }
00540 
00541         mTimerKey += _frame;
00542 
00543         if (mFirstPressKey)
00544         {
00545             if (mTimerKey > INPUT_DELAY_FIRST_KEY)
00546             {
00547                 mFirstPressKey = false;
00548                 mTimerKey = 0.0f;
00549             }
00550         }
00551         else
00552         {
00553             if (mTimerKey > INPUT_INTERVAL_KEY)
00554             {
00555                 while (mTimerKey > INPUT_INTERVAL_KEY) mTimerKey -= INPUT_INTERVAL_KEY;
00556                 mWidgetKeyFocus->onKeyButtonPressed(mHoldKey, mHoldChar);
00557                 // focus can be dropped in onKeyButtonPressed
00558                 if ( isFocusKey() ) mWidgetKeyFocus->onKeyButtonReleased(mHoldKey);
00559             }
00560         }
00561 
00562     }
00563 
00564     void InputManager::resetKeyFocusWidget(WidgetPtr _widget)
00565     {
00566         if (mWidgetKeyFocus == _widget)
00567             setKeyFocusWidget(nullptr);
00568     }
00569 
00570 } // namespace MyGUI

Generated on Sun Jan 30 2011 for MyGUI by  doxygen 1.7.1