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"
8 #include "MyGUI_InputManager.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 
15 namespace 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  // ищем активное окно
122  Widget* item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);
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  // проверяем над тем ли мы окном сейчас что и были при нажатии
330  Widget* item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);
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)
static const char * getClassTypeName()
delegates::CMultiDelegate1< Widget * > eventChangeMouseFocus
Widget * getMouseFocusWidget() const
delegates::CMultiDelegate1< Widget * > eventChangeKeyFocus
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