MyGUI  3.2.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  template <> const char* Singleton<InputManager>::mClassTypeName = "InputManager";
25 
27  mWidgetMouseFocus(nullptr),
28  mWidgetKeyFocus(nullptr),
29  mLayerMouseFocus(nullptr),
30  mTimerDoubleClick(INPUT_TIME_DOUBLE_CLICK),
31  mIsShiftPressed(false),
32  mIsControlPressed(false),
33  mHoldKey(KeyCode::None),
34  mHoldChar(0),
35  mFirstPressKey(false),
36  mTimerKey(0.0f),
37  mOldAbsZ(0),
38  mIsInitialise(false)
39  {
41  }
42 
44  {
45  MYGUI_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice");
46  MYGUI_LOG(Info, "* Initialise: " << getClassTypeName());
47 
48  mWidgetMouseFocus = 0;
49  mWidgetKeyFocus = 0;
50  mLayerMouseFocus = 0;
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  if (isFocusMouse())
103  {
104  if (mLayerMouseFocus != nullptr)
105  {
106  IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
107  for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
108  {
109  if (mMouseCapture[i])
110  mWidgetMouseFocus->_riseMouseDrag(point.left, point.top, MouseButton::Enum(i));
111  }
112  }
113  }
114  else
115  {
117  }
118 
119  return true;
120  }
121 
122  Widget* old_mouse_focus = mWidgetMouseFocus;
123 
124  // ищем активное окно
125  Widget* item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);
126 
127  // ничего не изменилось
128  if (mWidgetMouseFocus == item)
129  {
130  bool isFocus = isFocusMouse();
131  if (isFocusMouse())
132  {
133  if (mLayerMouseFocus != nullptr)
134  {
135  IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
136  mWidgetMouseFocus->_riseMouseMove(point.left, point.top);
137  }
138  }
139  return isFocus;
140  }
141 
142  if (item)
143  {
144  // поднимаемся до рута
145  Widget* root = item;
146  while (root->getParent()) root = root->getParent();
147 
148  // проверяем на модальность
149  if (!mVectorModalRootWidget.empty())
150  {
151  if (root != mVectorModalRootWidget.back())
152  {
153  item = nullptr;
154  }
155  }
156 
157  if (item != nullptr)
158  {
159  mLayerMouseFocus = root->getLayer();
160  }
161  }
162 
163  //-------------------------------------------------------------------------------------//
164  // новый вид рутового фокуса мыши
165  Widget* save_widget = nullptr;
166 
167  // спускаемся по новому виджету и устанавливаем рутовый фокус
168  Widget* root_focus = item;
169  while (root_focus != nullptr)
170  {
171  if (root_focus->getRootMouseFocus())
172  {
173  save_widget = root_focus;
174  break;
175  }
176 
177  root_focus->_setRootMouseFocus(true);
178  root_focus->_riseMouseChangeRootFocus(true);
179  root_focus = root_focus->getParent();
180  }
181 
182  // спускаемся по старому виджету и сбрасываем фокус
183  root_focus = mWidgetMouseFocus;
184  while (root_focus != nullptr)
185  {
186  if (root_focus == save_widget)
187  break;
188 
189  root_focus->_setRootMouseFocus(false);
190  root_focus->_riseMouseChangeRootFocus(false);
191  root_focus = root_focus->getParent();
192  }
193  //-------------------------------------------------------------------------------------//
194 
195  // смена фокуса, проверяем на доступность виджета
196  if (isFocusMouse() && mWidgetMouseFocus->getInheritedEnabled())
197  {
198  mWidgetMouseFocus->_riseMouseLostFocus(item);
199  }
200 
201  if ((item != nullptr) && (item->getInheritedEnabled()))
202  {
203  item->_riseMouseMove(_absx, _absy);
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  Widget* old_key_focus = mWidgetKeyFocus;
225 
226  // если мы щелкнули не на гуй
227  if (!isFocusMouse())
228  {
230 
231  if (old_key_focus != mWidgetKeyFocus)
232  eventChangeKeyFocus(mWidgetKeyFocus);
233 
234  return false;
235  }
236 
237  // если активный элемент заблокирован
238  //FIXME
239  if (!mWidgetMouseFocus->getInheritedEnabled())
240  return true;
241 
242  if (MouseButton::None != _id && MouseButton::MAX != _id)
243  {
244  // start capture
245  mMouseCapture[_id.getValue()] = true;
246  // remember last pressed position
247  if (mLayerMouseFocus != nullptr)
248  {
249  IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
250  mLastPressed[_id.getValue()] = point;
251  }
252  }
253 
254  // ищем вверх тот виджет который может принимать фокус
255  Widget* item = mWidgetMouseFocus;
256  while ((item != nullptr) && (!item->getNeedKeyFocus()))
257  item = item->getParent();
258 
259  // устанавливаем перед вызовом т.к. возможно внутри ктонить поменяет фокус под себя
260  setKeyFocusWidget(item);
261 
262  if (isFocusMouse())
263  {
264  mWidgetMouseFocus->_riseMouseButtonPressed(_absx, _absy, _id);
265 
266  // после пресса может сброситься
267  if (mWidgetMouseFocus)
268  {
269  // поднимаем виджет, надо подумать что делать если поменялся фокус клавы
270  LayerManager::getInstance().upLayerItem(mWidgetMouseFocus);
271 
272  // поднимаем пикинг Overlapped окон
273  Widget* pick = mWidgetMouseFocus;
274  do
275  {
276  // если оверлаппед, то поднимаем пикинг
278  {
279  if (pick->getParent()) pick->getParent()->_forcePick(pick);
280  }
281 
282  pick = pick->getParent();
283  }
284  while (pick);
285  }
286  }
287 
288  if (old_key_focus != mWidgetKeyFocus)
289  eventChangeKeyFocus(mWidgetKeyFocus);
290 
291  return true;
292  }
293 
294  bool InputManager::injectMouseRelease(int _absx, int _absy, MouseButton _id)
295  {
296  if (isFocusMouse())
297  {
298  // если активный элемент заблокирован
299  if (!mWidgetMouseFocus->getInheritedEnabled())
300  return true;
301 
302  if (_id != MouseButton::None && _id != MouseButton::MAX)
303  {
304  if (mMouseCapture[_id.getValue()])
305  {
306  // drop capture
307  mMouseCapture[_id.getValue()] = false;
308  }
309  }
310 
311  mWidgetMouseFocus->_riseMouseButtonReleased(_absx, _absy, _id);
312 
313  // после вызова, виджет может быть сброшен
314  if (nullptr != mWidgetMouseFocus)
315  {
316  if (MouseButton::Left == _id)
317  {
318  if (mTimerDoubleClick < INPUT_TIME_DOUBLE_CLICK)
319  {
320  mWidgetMouseFocus->_riseMouseButtonClick();
321  // после вызова, виджет может быть сброшен
322  if (nullptr != mWidgetMouseFocus)
323  mWidgetMouseFocus->_riseMouseButtonDoubleClick();
324  }
325  else
326  {
327  // проверяем над тем ли мы окном сейчас что и были при нажатии
328  Widget* item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);
329  if ( item == mWidgetMouseFocus)
330  {
331  mWidgetMouseFocus->_riseMouseButtonClick();
332  }
333  mTimerDoubleClick = 0;
334  }
335  }
336  }
337 
338  // для корректного отображения
339  injectMouseMove(_absx, _absy, mOldAbsZ);
340 
341  return true;
342  }
343 
344  return false;
345  }
346 
348  {
349  // проверка на переключение языков
350  firstEncoding(_key, true);
351 
352  // запоминаем клавишу
353  storeKey(_key, _text);
354 
355  bool wasFocusKey = isFocusKey();
356 
357  //Pass keystrokes to the current active text widget
358  if (isFocusKey())
359  {
360  mWidgetKeyFocus->_riseKeyButtonPressed(_key, _text);
361  }
362 
363  return wasFocusKey;
364  }
365 
367  {
368  // проверка на переключение языков
369  firstEncoding(_key, false);
370 
371  // сбрасываем клавишу
372  resetKey();
373 
374  bool wasFocusKey = isFocusKey();
375 
376  if (isFocusKey())
377  mWidgetKeyFocus->_riseKeyButtonReleased(_key);
378 
379  return wasFocusKey;
380  }
381 
382  void InputManager::firstEncoding(KeyCode _key, bool bIsKeyPressed)
383  {
384  if ((_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift))
385  mIsShiftPressed = bIsKeyPressed;
386  if ((_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl))
387  mIsControlPressed = bIsKeyPressed;
388  }
389 
391  {
392  if (_widget == mWidgetKeyFocus)
393  return;
394 
395  //-------------------------------------------------------------------------------------//
396  // новый вид рутового фокуса
397  Widget* save_widget = nullptr;
398 
399  // спускаемся по новому виджету и устанавливаем рутовый фокус
400  Widget* root_focus = _widget;
401  while (root_focus != nullptr)
402  {
403  if (root_focus->getRootKeyFocus())
404  {
405  save_widget = root_focus;
406  break;
407  }
408 
409  root_focus->_setRootKeyFocus(true);
410  root_focus->_riseKeyChangeRootFocus(true);
411  root_focus = root_focus->getParent();
412  }
413 
414  // спускаемся по старому виджету и сбрасываем фокус
415  root_focus = mWidgetKeyFocus;
416  while (root_focus != nullptr)
417  {
418  if (root_focus == save_widget)
419  break;
420 
421  root_focus->_setRootKeyFocus(false);
422  root_focus->_riseKeyChangeRootFocus(false);
423  root_focus = root_focus->getParent();
424  }
425  //-------------------------------------------------------------------------------------//
426 
427  // сбрасываем старый
428  if (mWidgetKeyFocus)
429  {
430  mWidgetKeyFocus->_riseKeyLostFocus(_widget);
431  }
432 
433  // устанавливаем новый
434  if (_widget && _widget->getNeedKeyFocus())
435  {
436  _widget->_riseKeySetFocus(mWidgetKeyFocus);
437  }
438 
439  mWidgetKeyFocus = _widget;
440  }
441 
443  {
444  Widget* mouseFocus = mWidgetMouseFocus;
445  mWidgetMouseFocus = nullptr;
446 
447  // спускаемся по старому виджету и сбрасываем фокус
448  Widget* root_focus = mouseFocus;
449  while (root_focus != nullptr)
450  {
451  root_focus->_setRootMouseFocus(false);
452  root_focus->_riseMouseChangeRootFocus(false);
453  root_focus = root_focus->getParent();
454  }
455 
456  for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
457  {
458  if (mMouseCapture[i])
459  {
460  mMouseCapture[i] = false;
461  mouseFocus->_riseMouseButtonReleased(mLastPressed[i].left, mLastPressed[i].top, MouseButton::Enum(i));
462  }
463  }
464 
465  if (nullptr != mouseFocus)
466  {
467  mouseFocus->_riseMouseLostFocus(nullptr);
468  }
469  }
470 
471  // удаляем данный виджет из всех возможных мест
472  void InputManager::_unlinkWidget(Widget* _widget)
473  {
474  if (nullptr == _widget)
475  return;
476 
477  if (mWidgetMouseFocus == _widget)
479 
480  if (_widget == mWidgetKeyFocus)
481  {
482  mWidgetKeyFocus = nullptr;
483  }
484 
485  // ручками сбрасываем, чтобы не менять фокусы
486  for (VectorWidgetPtr::iterator iter = mVectorModalRootWidget.begin(); iter != mVectorModalRootWidget.end(); ++iter)
487  {
488  if (*iter == _widget)
489  {
490  mVectorModalRootWidget.erase(iter);
491  break;
492  }
493  }
494  }
495 
497  {
498  if (nullptr == _widget)
499  return;
500  MYGUI_ASSERT(nullptr == _widget->getParent(), "Modal widget must be root");
501 
503  removeWidgetModal(_widget);
504  mVectorModalRootWidget.push_back(_widget);
505 
506  setKeyFocusWidget(_widget);
508  }
509 
511  {
512  resetKeyFocusWidget(_widget);
514 
515  for (VectorWidgetPtr::iterator iter = mVectorModalRootWidget.begin(); iter != mVectorModalRootWidget.end(); ++iter)
516  {
517  if (*iter == _widget)
518  {
519  mVectorModalRootWidget.erase(iter);
520  break;
521  }
522  }
523  // если еще есть модальные то их фокусируем и поднимаем
524  if (!mVectorModalRootWidget.empty())
525  {
526  setKeyFocusWidget(mVectorModalRootWidget.back());
527  LayerManager::getInstance().upLayerItem(mVectorModalRootWidget.back());
528  }
529  }
530 
531  void InputManager::storeKey(KeyCode _key, Char _text)
532  {
533  mHoldKey = KeyCode::None;
534  mHoldChar = 0;
535 
536  if ( !isFocusKey() ) return;
537  if ( (_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift)
538  || (_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl)
539  || (_key == KeyCode::LeftAlt) || (_key == KeyCode::RightAlt)
540  ) return;
541 
542  mFirstPressKey = true;
543  mHoldKey = _key;
544  mHoldChar = _text;
545  mTimerKey = 0.0f;
546  }
547 
548  void InputManager::resetKey()
549  {
550  mHoldKey = KeyCode::None;
551  mHoldChar = 0;
552  }
553 
554  void InputManager::frameEntered(float _frame)
555  {
556  mTimerDoubleClick += _frame;
557 
558  if ( mHoldKey == KeyCode::None)
559  return;
560 
561  if ( !isFocusKey() )
562  {
563  mHoldKey = KeyCode::None;
564  mHoldChar = 0;
565  return;
566  }
567 
568  mTimerKey += _frame;
569 
570  if (mFirstPressKey)
571  {
572  if (mTimerKey > INPUT_DELAY_FIRST_KEY)
573  {
574  mFirstPressKey = false;
575  mTimerKey = 0.0f;
576  }
577  }
578  else
579  {
580  if (mTimerKey > INPUT_INTERVAL_KEY)
581  {
582  while (mTimerKey > INPUT_INTERVAL_KEY)
583  mTimerKey -= INPUT_INTERVAL_KEY;
584  mWidgetKeyFocus->_riseKeyButtonPressed(mHoldKey, mHoldChar);
585  // focus can be dropped in onKeyButtonPressed
586  if (isFocusKey())
587  mWidgetKeyFocus->_riseKeyButtonReleased(mHoldKey);
588  }
589  }
590 
591  }
592 
594  {
595  if (mWidgetKeyFocus == _widget)
596  setKeyFocusWidget(nullptr);
597  }
598 
600  {
601  if (mLayerMouseFocus != nullptr)
602  return mLayerMouseFocus->getPosition(mMousePosition.left, mMousePosition.top);
603  return mMousePosition;
604  }
605 
607  {
608  return mWidgetMouseFocus != nullptr;
609  }
610 
612  {
613  return mWidgetKeyFocus != nullptr;
614  }
615 
617  {
618  for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
619  {
620  if (mMouseCapture[i])
621  return true;
622  }
623  return false;
624  }
625 
627  {
628  setKeyFocusWidget(nullptr);
629  }
630 
632  {
633  return mWidgetMouseFocus;
634  }
635 
637  {
638  return mWidgetKeyFocus;
639  }
640 
642  {
643  if (_id != MouseButton::None && _id != MouseButton::MAX)
644  {
645  return mLastPressed[_id.getValue()];
646  }
648  }
649 
651  {
652  return mMousePosition;
653  }
654 
656  {
657  return !mVectorModalRootWidget.empty();
658  }
659 
661  {
662  return mIsControlPressed;
663  }
664 
666  {
667  return mIsShiftPressed;
668  }
669 
671  {
672  for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
673  {
674  mMouseCapture[i] = false;
675  }
676  }
677 
679  {
680  _unlinkWidget(_widget);
681  }
682 
683 } // namespace MyGUI