MyGUI
3.2.0
|
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