MyGUI 3.4.1
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 mHoldKey(KeyCode::None),
33 mHoldChar(0),
34 mFirstPressKey(false),
35 mTimerKey(0.0f),
36 mOldAbsZ(0),
37 mIsInitialise(false),
38 mSingletonHolder(this)
39 {
41 }
42
44 {
45 MYGUI_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice");
46 MYGUI_LOG(Info, "* Initialise: " << getClassTypeName());
47
48 mWidgetMouseFocus = nullptr;
49 mWidgetKeyFocus = nullptr;
50 mLayerMouseFocus = nullptr;
51 for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
52 {
53 mMouseCapture[i] = false;
54 }
55 mIsShiftPressed = false;
56 mIsControlPressed = false;
57 mHoldKey = KeyCode::None;
58 mHoldChar = 0;
59 mFirstPressKey = true;
60 mTimerKey = 0.0f;
61 mOldAbsZ = 0;
62
64 Gui::getInstance().eventFrameStart += newDelegate(this, &InputManager::frameEntered);
65
66 MYGUI_LOG(Info, getClassTypeName() << " successfully initialized");
67 mIsInitialise = true;
68 }
69
71 {
72 MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised");
73 MYGUI_LOG(Info, "* Shutdown: " << getClassTypeName());
74
75 Gui::getInstance().eventFrameStart -= newDelegate(this, &InputManager::frameEntered);
77
78 MYGUI_LOG(Info, getClassTypeName() << " successfully shutdown");
79 mIsInitialise = false;
80 }
81
82 bool InputManager::injectMouseMove(int _absx, int _absy, int _absz)
83 {
84 // запоминаем позицию
85 mMousePosition.set(_absx, _absy);
86
87 // вычисляем прирост по колеса
88 int relz = _absz - mOldAbsZ;
89 mOldAbsZ = _absz;
90
91 // проверка на скролл
92 if (relz != 0)
93 {
94 bool isFocus = isFocusMouse();
95 if (isFocusMouse())
96 mWidgetMouseFocus->_riseMouseWheel(relz);
97 return isFocus;
98 }
99
100 if (isCaptureMouse())
101 {
102 bool isFocus = isFocusMouse();
103 if (isFocus)
104 {
105 if (mLayerMouseFocus != nullptr)
106 {
107 IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
108 for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
109 {
110 if (mMouseCapture[i])
111 mWidgetMouseFocus->_riseMouseDrag(point.left, point.top, MouseButton::Enum(i));
112 }
113 }
114 }
115
116 return isFocus;
117 }
118
119 Widget* old_mouse_focus = mWidgetMouseFocus;
120
121 // ищем активное окно
123
124 // ничего не изменилось
125 if (mWidgetMouseFocus == item)
126 {
127 bool isFocus = isFocusMouse();
128 if (isFocusMouse())
129 {
130 if (mLayerMouseFocus != nullptr)
131 {
132 IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
133 mWidgetMouseFocus->_riseMouseMove(point.left, point.top);
134 }
135 }
136 return isFocus;
137 }
138
139 if (item)
140 {
141 // поднимаемся до рута
142 Widget* root = item;
143 while (root->getParent()) root = root->getParent();
144
145 // проверяем на модальность
146 if (!mVectorModalRootWidget.empty())
147 {
148 if (root != mVectorModalRootWidget.back())
149 {
150 item = nullptr;
151 }
152 }
153
154 if (item != nullptr)
155 {
156 mLayerMouseFocus = root->getLayer();
157 }
158 }
159
160 //-------------------------------------------------------------------------------------//
161 // новый вид рутового фокуса мыши
162 Widget* save_widget = nullptr;
163
164 // спускаемся по новому виджету и устанавливаем рутовый фокус
165 Widget* root_focus = item;
166 while (root_focus != nullptr)
167 {
168 if (root_focus->getRootMouseFocus())
169 {
170 save_widget = root_focus;
171 break;
172 }
173
174 root_focus->_setRootMouseFocus(true);
175 root_focus->_riseMouseChangeRootFocus(true);
176 root_focus = root_focus->getParent();
177 }
178
179 // спускаемся по старому виджету и сбрасываем фокус
180 root_focus = mWidgetMouseFocus;
181 while (root_focus != nullptr)
182 {
183 if (root_focus == save_widget)
184 break;
185
186 root_focus->_setRootMouseFocus(false);
187 root_focus->_riseMouseChangeRootFocus(false);
188 root_focus = root_focus->getParent();
189 }
190 //-------------------------------------------------------------------------------------//
191
192 // смена фокуса, проверяем на доступность виджета
193 if (isFocusMouse() && mWidgetMouseFocus->getInheritedEnabled())
194 {
195 mWidgetMouseFocus->_riseMouseLostFocus(item);
196 }
197
198 if ((item != nullptr) && (item->getInheritedEnabled()))
199 {
200 MyGUI::IntPoint point (_absx, _absy);
201 if (mLayerMouseFocus != nullptr)
202 point = mLayerMouseFocus->getPosition(_absx, _absy);
203 item->_riseMouseMove(point.left, point.top);
204 item->_riseMouseSetFocus(mWidgetMouseFocus);
205 }
206
207 // запоминаем текущее окно
208 mWidgetMouseFocus = item;
209
210 if (old_mouse_focus != mWidgetMouseFocus)
211 {
212 // Reset double click timer, double clicks should only work when clicking on the *same* item twice
213 mTimerDoubleClick = INPUT_TIME_DOUBLE_CLICK;
214 eventChangeMouseFocus(mWidgetMouseFocus);
215 }
216
217 return isFocusMouse();
218 }
219
220 bool InputManager::injectMousePress(int _absx, int _absy, MouseButton _id)
221 {
222 injectMouseMove(_absx, _absy, mOldAbsZ);
223
224 if (MouseButton::None != _id && MouseButton::MAX != _id)
225 {
226 // start capture
227 mMouseCapture[_id.getValue()] = true;
228 }
229
230 // если мы щелкнули не на гуй
231 if (!isFocusMouse())
232 {
234
235 return false;
236 }
237
238 // если активный элемент заблокирован
239 //FIXME
240 if (!mWidgetMouseFocus->getInheritedEnabled())
241 return true;
242
243 if (MouseButton::None != _id && MouseButton::MAX != _id)
244 {
245 // remember last pressed position
246 if (mLayerMouseFocus != nullptr)
247 {
248 IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
249 mLastPressed[_id.getValue()] = point;
250 }
251 }
252
253 // ищем вверх тот виджет который может принимать фокус
254 Widget* item = mWidgetMouseFocus;
255 while ((item != nullptr) && (!item->getNeedKeyFocus()))
256 item = item->getParent();
257
258 // устанавливаем перед вызовом т.к. возможно внутри ктонить поменяет фокус под себя
259 setKeyFocusWidget(item);
260
261 if (isFocusMouse())
262 {
263 IntPoint point (_absx, _absy);
264 if (mLayerMouseFocus != nullptr)
265 point = mLayerMouseFocus->getPosition(_absx, _absy);
266 mWidgetMouseFocus->_riseMouseButtonPressed(point.left, point.top, _id);
267
268 // после пресса может сброситься
269 if (mWidgetMouseFocus)
270 {
271 // поднимаем виджет, надо подумать что делать если поменялся фокус клавы
272 LayerManager::getInstance().upLayerItem(mWidgetMouseFocus);
273
274 // поднимаем пикинг Overlapped окон
275 Widget* pick = mWidgetMouseFocus;
276 do
277 {
278 // если оверлаппед, то поднимаем пикинг
280 {
281 if (pick->getParent()) pick->getParent()->_forcePick(pick);
282 }
283
284 pick = pick->getParent();
285 }
286 while (pick);
287 }
288 }
289
290 return true;
291 }
292
293 bool InputManager::injectMouseRelease(int _absx, int _absy, MouseButton _id)
294 {
295 if (_id != MouseButton::None && _id != MouseButton::MAX)
296 {
297 if (mMouseCapture[_id.getValue()])
298 {
299 // drop capture
300 mMouseCapture[_id.getValue()] = false;
301 }
302 }
303
304 if (isFocusMouse())
305 {
306 // если активный элемент заблокирован
307 if (!mWidgetMouseFocus->getInheritedEnabled())
308 return true;
309
310 IntPoint point (_absx, _absy);
311 if (mLayerMouseFocus != nullptr)
312 point = mLayerMouseFocus->getPosition(_absx, _absy);
313 mWidgetMouseFocus->_riseMouseButtonReleased(point.left, point.top, _id);
314
315 // после вызова, виджет может быть сброшен
316 if (nullptr != mWidgetMouseFocus)
317 {
318 if (MouseButton::Left == _id)
319 {
320 if (mTimerDoubleClick < INPUT_TIME_DOUBLE_CLICK)
321 {
322 mWidgetMouseFocus->_riseMouseButtonClick();
323 // после вызова, виджет может быть сброшен
324 if (nullptr != mWidgetMouseFocus)
325 mWidgetMouseFocus->_riseMouseButtonDoubleClick();
326 }
327 else
328 {
329 // проверяем над тем ли мы окном сейчас что и были при нажатии
331 if ( item == mWidgetMouseFocus)
332 {
333 mWidgetMouseFocus->_riseMouseButtonClick();
334 }
335 mTimerDoubleClick = 0;
336 }
337 }
338 }
339
340 // для корректного отображения
341 injectMouseMove(_absx, _absy, mOldAbsZ);
342
343 return true;
344 }
345
346 return false;
347 }
348
350 {
351 // проверка на переключение языков
352 firstEncoding(_key, true);
353
354 // запоминаем клавишу
355 storeKey(_key, _text);
356
357 bool wasFocusKey = isFocusKey();
358
359 //Pass keystrokes to the current active text widget
360 if (isFocusKey())
361 {
362 mWidgetKeyFocus->_riseKeyButtonPressed(_key, _text);
363 }
364
365 return wasFocusKey;
366 }
367
369 {
370 // проверка на переключение языков
371 firstEncoding(_key, false);
372
373 // сбрасываем клавишу
374 resetKey();
375
376 bool wasFocusKey = isFocusKey();
377
378 if (isFocusKey())
379 mWidgetKeyFocus->_riseKeyButtonReleased(_key);
380
381 return wasFocusKey;
382 }
383
384 void InputManager::firstEncoding(KeyCode _key, bool bIsKeyPressed)
385 {
386 if ((_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift))
387 mIsShiftPressed = bIsKeyPressed;
388 if ((_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl))
389 mIsControlPressed = bIsKeyPressed;
390 }
391
393 {
394 if (_widget == mWidgetKeyFocus)
395 return;
396
397 Widget* oldKeyFocus = mWidgetKeyFocus;
398 mWidgetKeyFocus = nullptr;
399
400 Widget* sharedRootFocus = nullptr; // possible shared parent for both old and new widget
401
402 // recursively set root key focus
403 Widget* rootFocus = _widget;
404 while (rootFocus != nullptr)
405 {
406 if (rootFocus->getRootKeyFocus())
407 {
408 sharedRootFocus = rootFocus;
409 break;
410 }
411
412 rootFocus->_setRootKeyFocus(true);
413 rootFocus->_riseKeyChangeRootFocus(true);
414 rootFocus = rootFocus->getParent();
415 }
416
417 // recursively reset root key focus
418 rootFocus = oldKeyFocus;
419 while (rootFocus != nullptr)
420 {
421 if (rootFocus == sharedRootFocus)
422 break;
423
424 rootFocus->_setRootKeyFocus(false);
425 rootFocus->_riseKeyChangeRootFocus(false);
426 rootFocus = rootFocus->getParent();
427 }
428 //-------------------------------------------------------------------------------------//
429
430 mWidgetKeyFocus = _widget;
431
432 if (oldKeyFocus)
433 {
434 oldKeyFocus->_riseKeyLostFocus(_widget);
435 }
436
437 if (_widget)
438 {
439 _widget->_riseKeySetFocus(mWidgetKeyFocus);
440 }
441
442 eventChangeKeyFocus(mWidgetKeyFocus);
443 }
444
446 {
447 Widget* mouseFocus = mWidgetMouseFocus;
448 mWidgetMouseFocus = nullptr;
449
450 // recursively reset old widget focus
451 Widget* root_focus = mouseFocus;
452 while (root_focus != nullptr)
453 {
454 root_focus->_setRootMouseFocus(false);
455 root_focus->_riseMouseChangeRootFocus(false);
456 root_focus = root_focus->getParent();
457 }
458
459 for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
460 {
461 if (mMouseCapture[i])
462 {
463 mMouseCapture[i] = false;
464 if (nullptr != mouseFocus)
465 {
466 mouseFocus->_riseMouseButtonReleased(mLastPressed[i].left, mLastPressed[i].top, MouseButton::Enum(i));
467 }
468 }
469 }
470
471 if (nullptr != mouseFocus)
472 {
473 mouseFocus->_riseMouseLostFocus(nullptr);
474 }
475
476 if (mouseFocus != mWidgetMouseFocus)
477 eventChangeMouseFocus(mWidgetMouseFocus);
478 }
479
480 // удаляем данный виджет из всех возможных мест
481 void InputManager::_unlinkWidget(Widget* _widget)
482 {
483 if (nullptr == _widget)
484 return;
485
486 if (mWidgetMouseFocus == _widget)
488
489 if (_widget == mWidgetKeyFocus)
491
492 // ручками сбрасываем, чтобы не менять фокусы
493 for (VectorWidgetPtr::iterator iter = mVectorModalRootWidget.begin(); iter != mVectorModalRootWidget.end(); ++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(); ++iter)
523 {
524 if (*iter == _widget)
525 {
526 mVectorModalRootWidget.erase(iter);
527 break;
528 }
529 }
530 // если еще есть модальные то их фокусируем и поднимаем
531 if (!mVectorModalRootWidget.empty())
532 {
533 setKeyFocusWidget(mVectorModalRootWidget.back());
534 LayerManager::getInstance().upLayerItem(mVectorModalRootWidget.back());
535 }
536 }
537
538 void InputManager::storeKey(KeyCode _key, Char _text)
539 {
540 mHoldKey = KeyCode::None;
541 mHoldChar = 0;
542
543 if ( !isFocusKey() ) return;
544 if ( (_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift)
545 || (_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl)
546 || (_key == KeyCode::LeftAlt) || (_key == KeyCode::RightAlt)
547 ) return;
548
549 mFirstPressKey = true;
550 mHoldKey = _key;
551 mHoldChar = _text;
552 mTimerKey = 0.0f;
553 }
554
555 void InputManager::resetKey()
556 {
557 mHoldKey = KeyCode::None;
558 mHoldChar = 0;
559 }
560
561 void InputManager::frameEntered(float _frame)
562 {
563 mTimerDoubleClick += _frame;
564
565 if ( mHoldKey == KeyCode::None)
566 return;
567
568 if ( !isFocusKey() )
569 {
570 mHoldKey = KeyCode::None;
571 mHoldChar = 0;
572 return;
573 }
574
575 mTimerKey += _frame;
576
577 if (mFirstPressKey)
578 {
579 if (mTimerKey > INPUT_DELAY_FIRST_KEY)
580 {
581 mFirstPressKey = false;
582 mTimerKey = 0.0f;
583 }
584 }
585 else
586 {
587 if (mTimerKey > INPUT_INTERVAL_KEY)
588 {
589 while (mTimerKey > INPUT_INTERVAL_KEY)
590 mTimerKey -= INPUT_INTERVAL_KEY;
591 mWidgetKeyFocus->_riseKeyButtonPressed(mHoldKey, mHoldChar);
592 // focus can be dropped in onKeyButtonPressed
593 if (isFocusKey())
594 mWidgetKeyFocus->_riseKeyButtonReleased(mHoldKey);
595 }
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 for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
680 {
681 mMouseCapture[i] = false;
682 }
683 }
684
686 {
687 _unlinkWidget(_widget);
688 }
689
690} // namespace MyGUI
#define MYGUI_ASSERT(exp, dest)
#define MYGUI_LOG(level, text)
static const IntPoint & getZeroIntPoint()
static Gui & getInstance()
EventHandle_FrameEventDelegate eventFrameStart
Definition: MyGUI_Gui.h:150
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
ILayer * getLayer() const
void upLayerItem(Widget *_item)
static LayerManager & getInstance()
Widget * getWidgetFromPoint(int _left, int _top) const
widget description should be here.
Definition: MyGUI_Widget.h:37
Widget * getParent() const
bool getInheritedEnabled() const
WidgetStyle getWidgetStyle() const
void _forcePick(Widget *_widget)
void _riseMouseMove(int _left, int _top)
bool getRootKeyFocus() const
void _riseKeyButtonReleased(KeyCode _key)
void _riseKeySetFocus(Widget *_old)
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)
void _riseKeyChangeRootFocus(bool _focus)
bool getNeedKeyFocus() const
void _riseKeyLostFocus(Widget *_new)
void _setRootKeyFocus(bool _value)
void _setRootMouseFocus(bool _value)
void _riseMouseChangeRootFocus(bool _focus)
bool getRootMouseFocus() const
void unregisterUnlinker(IUnlinkWidget *_unlink)
static WidgetManager & getInstance()
void registerUnlinker(IUnlinkWidget *_unlink)
const float INPUT_TIME_DOUBLE_CLICK
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))
MYGUI_SINGLETON_DEFINITION(ClipboardManager)
const float INPUT_INTERVAL_KEY
unsigned int Char
Definition: MyGUI_Types.h:49
const float INPUT_DELAY_FIRST_KEY
void set(T const &_left, T const &_top)
Definition: MyGUI_TPoint.h:95