MyGUI 3.4.3
MyGUI_InputManager.cpp
Go to the documentation of this file.
1/*
2 * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3 * Distributed under the MIT License
4 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5 */
6
7#include "MyGUI_Precompiled.h"
9#include "MyGUI_Widget.h"
10#include "MyGUI_WidgetManager.h"
11#include "MyGUI_Gui.h"
12#include "MyGUI_Constants.h"
13
14namespace MyGUI
15{
16
17 // In seconds
18 const float INPUT_TIME_DOUBLE_CLICK = 0.25f;
19 const float INPUT_DELAY_FIRST_KEY = 0.4f;
20 const float INPUT_INTERVAL_KEY = 0.05f;
21
23
25 mTimerDoubleClick(INPUT_TIME_DOUBLE_CLICK),
26 mSingletonHolder(this)
27 {
29 }
30
32 {
33 MYGUI_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice");
34 MYGUI_LOG(Info, "* Initialise: " << getClassTypeName());
35
36 mWidgetMouseFocus = nullptr;
37 mWidgetKeyFocus = nullptr;
38 mLayerMouseFocus = nullptr;
39 for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
40 {
41 mMouseCapture[i] = false;
42 }
43 mIsShiftPressed = false;
44 mIsControlPressed = false;
45 mIsAltPressed = false;
46 mIsMetaPressed = false;
47
48 mHoldKey = KeyCode::None;
49 mHoldChar = 0;
50 mFirstPressKey = true;
51 mTimerKey = 0.0f;
52 mOldAbsZ = 0;
53
55 Gui::getInstance().eventFrameStart += newDelegate(this, &InputManager::frameEntered);
56
57 MYGUI_LOG(Info, getClassTypeName() << " successfully initialized");
58 mIsInitialise = true;
59 }
60
62 {
63 MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised");
64 MYGUI_LOG(Info, "* Shutdown: " << getClassTypeName());
65
66 Gui::getInstance().eventFrameStart -= newDelegate(this, &InputManager::frameEntered);
68
69 MYGUI_LOG(Info, getClassTypeName() << " successfully shutdown");
70 mIsInitialise = false;
71 }
72
73 bool InputManager::injectMouseMove(int _absx, int _absy, int _absz)
74 {
75 // запоминаем позицию
76 mMousePosition.set(_absx, _absy);
77
78 // вычисляем прирост по колеса
79 int relz = _absz - mOldAbsZ;
80 mOldAbsZ = _absz;
81
82 // проверка на скролл
83 if (relz != 0)
84 {
85 bool isFocus = isFocusMouse();
86 if (isFocusMouse())
87 mWidgetMouseFocus->_riseMouseWheel(relz);
88 return isFocus;
89 }
90
91 if (isCaptureMouse())
92 {
93 bool isFocus = isFocusMouse();
94 if (isFocus)
95 {
96 if (mLayerMouseFocus != nullptr)
97 {
98 IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
99 for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
100 {
101 if (mMouseCapture[i])
102 mWidgetMouseFocus->_riseMouseDrag(point.left, point.top, MouseButton::Enum(i));
103 }
104 }
105 }
106
107 return isFocus;
108 }
109
110 Widget* old_mouse_focus = mWidgetMouseFocus;
111
112 // ищем активное окно
114
115 // ничего не изменилось
116 if (mWidgetMouseFocus == item)
117 {
118 bool isFocus = isFocusMouse();
119 if (isFocusMouse())
120 {
121 if (mLayerMouseFocus != nullptr)
122 {
123 IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
124 mWidgetMouseFocus->_riseMouseMove(point.left, point.top);
125 }
126 }
127 return isFocus;
128 }
129
130 if (item)
131 {
132 // поднимаемся до рута
133 Widget* root = item;
134 while (root->getParent())
135 root = root->getParent();
136
137 // проверяем на модальность
138 if (!mVectorModalRootWidget.empty())
139 {
140 if (root != mVectorModalRootWidget.back())
141 {
142 item = nullptr;
143 }
144 }
145
146 if (item != nullptr)
147 {
148 mLayerMouseFocus = root->getLayer();
149 }
150 }
151
152 //-------------------------------------------------------------------------------------//
153 // новый вид рутового фокуса мыши
154 Widget* save_widget = nullptr;
155
156 // спускаемся по новому виджету и устанавливаем рутовый фокус
157 Widget* root_focus = item;
158 while (root_focus != nullptr)
159 {
160 if (root_focus->getRootMouseFocus())
161 {
162 save_widget = root_focus;
163 break;
164 }
165
166 root_focus->_setRootMouseFocus(true);
167 root_focus->_riseMouseChangeRootFocus(true);
168 root_focus = root_focus->getParent();
169 }
170
171 // спускаемся по старому виджету и сбрасываем фокус
172 root_focus = mWidgetMouseFocus;
173 while (root_focus != nullptr)
174 {
175 if (root_focus == save_widget)
176 break;
177
178 root_focus->_setRootMouseFocus(false);
179 root_focus->_riseMouseChangeRootFocus(false);
180 root_focus = root_focus->getParent();
181 }
182 //-------------------------------------------------------------------------------------//
183
184 // смена фокуса, проверяем на доступность виджета
185 if (isFocusMouse() && mWidgetMouseFocus->getInheritedEnabled())
186 {
187 mWidgetMouseFocus->_riseMouseLostFocus(item);
188 }
189
190 if ((item != nullptr) && (item->getInheritedEnabled()))
191 {
192 MyGUI::IntPoint point(_absx, _absy);
193 if (mLayerMouseFocus != nullptr)
194 point = mLayerMouseFocus->getPosition(_absx, _absy);
195 item->_riseMouseMove(point.left, point.top);
196 item->_riseMouseSetFocus(mWidgetMouseFocus);
197 }
198
199 // запоминаем текущее окно
200 mWidgetMouseFocus = item;
201
202 if (old_mouse_focus != mWidgetMouseFocus)
203 {
204 // Reset double click timer, double clicks should only work when clicking on the *same* item twice
205 mTimerDoubleClick = INPUT_TIME_DOUBLE_CLICK;
206 eventChangeMouseFocus(mWidgetMouseFocus);
207 }
208
209 return isFocusMouse();
210 }
211
212 bool InputManager::injectMousePress(int _absx, int _absy, MouseButton _id)
213 {
214 injectMouseMove(_absx, _absy, mOldAbsZ);
215
216 if (MouseButton::None != _id && MouseButton::MAX != _id)
217 {
218 // start capture
219 mMouseCapture[_id.getValue()] = true;
220 }
221
222 // если мы щелкнули не на гуй
223 if (!isFocusMouse())
224 {
226
227 return false;
228 }
229
230 // если активный элемент заблокирован
231 //FIXME
232 if (!mWidgetMouseFocus->getInheritedEnabled())
233 return true;
234
235 if (MouseButton::None != _id && MouseButton::MAX != _id)
236 {
237 // remember last pressed position
238 if (mLayerMouseFocus != nullptr)
239 {
240 IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
241 mLastPressed[_id.getValue()] = point;
242 }
243 }
244
245 // ищем вверх тот виджет который может принимать фокус
246 Widget* item = mWidgetMouseFocus;
247 while ((item != nullptr) && (!item->getNeedKeyFocus()))
248 item = item->getParent();
249
250 // устанавливаем перед вызовом т.к. возможно внутри ктонить поменяет фокус под себя
251 setKeyFocusWidget(item);
252
253 if (isFocusMouse())
254 {
255 IntPoint point(_absx, _absy);
256 if (mLayerMouseFocus != nullptr)
257 point = mLayerMouseFocus->getPosition(_absx, _absy);
258 mWidgetMouseFocus->_riseMouseButtonPressed(point.left, point.top, _id);
259
260 // после пресса может сброситься
261 if (mWidgetMouseFocus)
262 {
263 // поднимаем виджет, надо подумать что делать если поменялся фокус клавы
264 LayerManager::getInstance().upLayerItem(mWidgetMouseFocus);
265
266 // поднимаем пикинг Overlapped окон
267 Widget* pick = mWidgetMouseFocus;
268 do
269 {
270 // если оверлаппед, то поднимаем пикинг
272 {
273 if (pick->getParent())
274 pick->getParent()->_forcePick(pick);
275 }
276
277 pick = pick->getParent();
278 } while (pick);
279 }
280 }
281
282 return true;
283 }
284
285 bool InputManager::injectMouseRelease(int _absx, int _absy, MouseButton _id)
286 {
287 if (_id != MouseButton::None && _id != MouseButton::MAX)
288 {
289 if (mMouseCapture[_id.getValue()])
290 {
291 // drop capture
292 mMouseCapture[_id.getValue()] = false;
293 }
294 }
295
296 if (isFocusMouse())
297 {
298 // если активный элемент заблокирован
299 if (!mWidgetMouseFocus->getInheritedEnabled())
300 return true;
301
302 IntPoint point(_absx, _absy);
303 if (mLayerMouseFocus != nullptr)
304 point = mLayerMouseFocus->getPosition(_absx, _absy);
305 mWidgetMouseFocus->_riseMouseButtonReleased(point.left, point.top, _id);
306
307 // после вызова, виджет может быть сброшен
308 if (nullptr != mWidgetMouseFocus)
309 {
310 if (MouseButton::Left == _id)
311 {
312 if (mTimerDoubleClick < INPUT_TIME_DOUBLE_CLICK)
313 {
314 mWidgetMouseFocus->_riseMouseButtonClick();
315 // might be reset in the call above, so check again
316 if (nullptr != mWidgetMouseFocus)
317 mWidgetMouseFocus->_riseMouseButtonDoubleClick();
318 }
319 else
320 {
321 // проверяем над тем ли мы окном сейчас что и были при нажатии
323 if (item == mWidgetMouseFocus)
324 {
325 mWidgetMouseFocus->_riseMouseButtonClick();
326 }
327 mTimerDoubleClick = 0;
328 }
329 }
330 }
331
332 // для корректного отображения
333 injectMouseMove(_absx, _absy, mOldAbsZ);
334
335 return true;
336 }
337
338 return false;
339 }
340
342 {
343 // проверка на переключение языков
344 firstEncoding(_key, true);
345
346 // запоминаем клавишу
347 storeKey(_key, _text);
348
349 bool wasFocusKey = isFocusKey();
350
351 //Pass keystrokes to the current active text widget
352 if (isFocusKey())
353 {
354 mWidgetKeyFocus->_riseKeyButtonPressed(_key, _text);
355 }
356
357 return wasFocusKey;
358 }
359
361 {
362 // проверка на переключение языков
363 firstEncoding(_key, false);
364
365 // сбрасываем клавишу
366 resetKey();
367
368 bool wasFocusKey = isFocusKey();
369
370 if (isFocusKey())
371 mWidgetKeyFocus->_riseKeyButtonReleased(_key);
372
373 return wasFocusKey;
374 }
375
376 void InputManager::firstEncoding(KeyCode _key, bool bIsKeyPressed)
377 {
378 if ((_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift))
379 mIsShiftPressed = bIsKeyPressed;
380 if ((_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl))
381 mIsControlPressed = bIsKeyPressed;
382 if ((_key == KeyCode::LeftAlt) || (_key == KeyCode::RightAlt))
383 mIsAltPressed = bIsKeyPressed;
384 if ((_key == KeyCode::LeftWindows) || (_key == KeyCode::RightWindows))
385 mIsMetaPressed = bIsKeyPressed;
386 }
387
389 {
390 if (_widget == mWidgetKeyFocus)
391 return;
392
393 Widget* oldKeyFocus = mWidgetKeyFocus;
394 mWidgetKeyFocus = nullptr;
395
396 Widget* sharedRootFocus = nullptr; // possible shared parent for both old and new widget
397
398 // recursively set root key focus
399 Widget* rootFocus = _widget;
400 while (rootFocus != nullptr)
401 {
402 if (rootFocus->getRootKeyFocus())
403 {
404 sharedRootFocus = rootFocus;
405 break;
406 }
407
408 rootFocus->_setRootKeyFocus(true);
409 rootFocus->_riseKeyChangeRootFocus(true);
410 rootFocus = rootFocus->getParent();
411 }
412
413 // recursively reset root key focus
414 rootFocus = oldKeyFocus;
415 while (rootFocus != nullptr)
416 {
417 if (rootFocus == sharedRootFocus)
418 break;
419
420 rootFocus->_setRootKeyFocus(false);
421 rootFocus->_riseKeyChangeRootFocus(false);
422 rootFocus = rootFocus->getParent();
423 }
424 //-------------------------------------------------------------------------------------//
425
426 mWidgetKeyFocus = _widget;
427
428 if (oldKeyFocus)
429 {
430 oldKeyFocus->_riseKeyLostFocus(_widget);
431 }
432
433 if (_widget)
434 {
435 _widget->_riseKeySetFocus(mWidgetKeyFocus);
436 }
437
438 eventChangeKeyFocus(mWidgetKeyFocus);
439 }
440
442 {
443 Widget* mouseFocus = mWidgetMouseFocus;
444 mWidgetMouseFocus = nullptr;
445
446 // recursively reset old widget focus
447 Widget* root_focus = mouseFocus;
448 while (root_focus != nullptr)
449 {
450 root_focus->_setRootMouseFocus(false);
451 root_focus->_riseMouseChangeRootFocus(false);
452 root_focus = root_focus->getParent();
453 }
454
455 for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
456 {
457 if (mMouseCapture[i])
458 {
459 mMouseCapture[i] = false;
460 if (nullptr != mouseFocus)
461 {
462 mouseFocus->_riseMouseButtonReleased(
463 mLastPressed[i].left,
464 mLastPressed[i].top,
466 }
467 }
468 }
469
470 if (nullptr != mouseFocus)
471 {
472 mouseFocus->_riseMouseLostFocus(nullptr);
473 }
474
475 if (mouseFocus != mWidgetMouseFocus)
476 eventChangeMouseFocus(mWidgetMouseFocus);
477 }
478
479 // удаляем данный виджет из всех возможных мест
480 void InputManager::_unlinkWidget(Widget* _widget)
481 {
482 if (nullptr == _widget)
483 return;
484
485 if (mWidgetMouseFocus == _widget)
487
488 if (_widget == mWidgetKeyFocus)
490
491 // ручками сбрасываем, чтобы не менять фокусы
492 for (VectorWidgetPtr::iterator iter = mVectorModalRootWidget.begin(); iter != mVectorModalRootWidget.end();
493 ++iter)
494 {
495 if (*iter == _widget)
496 {
497 mVectorModalRootWidget.erase(iter);
498 break;
499 }
500 }
501 }
502
504 {
505 if (nullptr == _widget)
506 return;
507 MYGUI_ASSERT(nullptr == _widget->getParent(), "Modal widget must be root");
508
510 removeWidgetModal(_widget);
511 mVectorModalRootWidget.push_back(_widget);
512
513 setKeyFocusWidget(_widget);
515 }
516
518 {
519 resetKeyFocusWidget(_widget);
521
522 for (VectorWidgetPtr::iterator iter = mVectorModalRootWidget.begin(); iter != mVectorModalRootWidget.end();
523 ++iter)
524 {
525 if (*iter == _widget)
526 {
527 mVectorModalRootWidget.erase(iter);
528 break;
529 }
530 }
531 // если еще есть модальные то их фокусируем и поднимаем
532 if (!mVectorModalRootWidget.empty())
533 {
534 setKeyFocusWidget(mVectorModalRootWidget.back());
535 LayerManager::getInstance().upLayerItem(mVectorModalRootWidget.back());
536 }
537 }
538
539 void InputManager::storeKey(KeyCode _key, Char _text)
540 {
541 mHoldKey = KeyCode::None;
542 mHoldChar = 0;
543
544 if (!isFocusKey())
545 return;
546 if ((_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift) || (_key == KeyCode::LeftControl) ||
547 (_key == KeyCode::RightControl) || (_key == KeyCode::LeftAlt) || (_key == KeyCode::RightAlt))
548 return;
549
550 mFirstPressKey = true;
551 mHoldKey = _key;
552 mHoldChar = _text;
553 mTimerKey = 0.0f;
554 }
555
556 void InputManager::resetKey()
557 {
558 mHoldKey = KeyCode::None;
559 mHoldChar = 0;
560 }
561
562 void InputManager::frameEntered(float _frame)
563 {
564 mTimerDoubleClick += _frame;
565
566 if (mHoldKey == KeyCode::None)
567 return;
568
569 if (!isFocusKey())
570 {
571 mHoldKey = KeyCode::None;
572 mHoldChar = 0;
573 return;
574 }
575
576 mTimerKey += _frame;
577
578 if (mFirstPressKey)
579 {
580 if (mTimerKey > INPUT_DELAY_FIRST_KEY)
581 {
582 mFirstPressKey = false;
583 mTimerKey = 0.0f;
584 }
585 }
586 else
587 {
588 if (mTimerKey > INPUT_INTERVAL_KEY)
589 {
590 while (mTimerKey > INPUT_INTERVAL_KEY)
591 mTimerKey -= INPUT_INTERVAL_KEY;
592 mWidgetKeyFocus->_riseKeyButtonPressed(mHoldKey, mHoldChar);
593 // focus can be dropped in onKeyButtonPressed
594 if (isFocusKey())
595 mWidgetKeyFocus->_riseKeyButtonReleased(mHoldKey);
596 }
597 }
598 }
599
601 {
602 if (mWidgetKeyFocus == _widget)
603 setKeyFocusWidget(nullptr);
604 }
605
607 {
608 if (mLayerMouseFocus != nullptr)
609 return mLayerMouseFocus->getPosition(mMousePosition.left, mMousePosition.top);
610 return mMousePosition;
611 }
612
614 {
615 return mWidgetMouseFocus != nullptr;
616 }
617
619 {
620 return mWidgetKeyFocus != nullptr;
621 }
622
624 {
625 for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
626 {
627 if (mMouseCapture[i])
628 return true;
629 }
630 return false;
631 }
632
634 {
635 setKeyFocusWidget(nullptr);
636 }
637
639 {
640 return mWidgetMouseFocus;
641 }
642
644 {
645 return mWidgetKeyFocus;
646 }
647
649 {
650 if (_id != MouseButton::None && _id != MouseButton::MAX)
651 {
652 return mLastPressed[_id.getValue()];
653 }
655 }
656
658 {
659 return mMousePosition;
660 }
661
663 {
664 return !mVectorModalRootWidget.empty();
665 }
666
668 {
669 return mIsControlPressed;
670 }
671
673 {
674 return mIsShiftPressed;
675 }
676
678 {
679 return mIsAltPressed;
680 }
681
683 {
684 return mIsMetaPressed;
685 }
686
688 {
689 for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
690 {
691 mMouseCapture[i] = false;
692 }
693 }
694
696 {
697 _unlinkWidget(_widget);
698 }
699
700} // namespace MyGUI
#define MYGUI_ASSERT(exp, dest)
#define MYGUI_LOG(level, text)
#define MYGUI_SINGLETON_DEFINITION(ClassName)
static const IntPoint & getZeroIntPoint()
static Gui & getInstance()
Definition MyGUI_Gui.cpp:34
EventHandle_FrameEventDelegate eventFrameStart
Definition MyGUI_Gui.h:215
const IntPoint & getLastPressedPosition(MouseButton _id) const
void unlinkWidget(Widget *_widget)
bool injectMousePress(int _absx, int _absy, MouseButton _id)
bool injectMouseMove(int _absx, int _absy, int _absz)
const IntPoint & getMousePosition() const
Widget * getKeyFocusWidget() const
void setKeyFocusWidget(Widget *_widget)
delegates::MultiDelegate< Widget * > eventChangeMouseFocus
Widget * getMouseFocusWidget() const
delegates::MultiDelegate< Widget * > eventChangeKeyFocus
bool injectMouseRelease(int _absx, int _absy, MouseButton _id)
static std::string_view getClassTypeName()
bool injectKeyPress(KeyCode _key, Char _text=0)
bool injectKeyRelease(KeyCode _key)
void addWidgetModal(Widget *_widget)
void removeWidgetModal(Widget *_widget)
IntPoint getMousePositionByLayer() const
ILayer * getLayer() const
void upLayerItem(Widget *_item)
static LayerManager & getInstance()
Widget * getWidgetFromPoint(int _left, int _top) const
widget description should be here.
Widget * getParent() const
bool getInheritedEnabled() const
WidgetStyle getWidgetStyle() const
void _forcePick(Widget *_widget)
void _riseMouseMove(int _left, int _top)
void _riseKeySetFocus(Widget *_old)
void _riseMouseButtonReleased(int _left, int _top, MouseButton _id)
void _riseMouseSetFocus(Widget *_old)
void _riseMouseLostFocus(Widget *_new)
void _riseKeyChangeRootFocus(bool _focus)
void _riseKeyLostFocus(Widget *_new)
void _setRootKeyFocus(bool _value)
void _setRootMouseFocus(bool _value)
void _riseMouseChangeRootFocus(bool _focus)
void unregisterUnlinker(IUnlinkWidget *_unlink)
static WidgetManager & getInstance()
void registerUnlinker(IUnlinkWidget *_unlink)
const float INPUT_TIME_DOUBLE_CLICK
types::TPoint< int > IntPoint
Definition MyGUI_Types.h:27
unsigned int Char
Definition MyGUI_Types.h:50
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))
const float INPUT_INTERVAL_KEY
const float INPUT_DELAY_FIRST_KEY