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