MyGUI  3.2.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"
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  // если мы щелкнули не на гуй
225  if (!isFocusMouse())
226  {
228 
229  return false;
230  }
231 
232  // если активный элемент заблокирован
233  //FIXME
234  if (!mWidgetMouseFocus->getInheritedEnabled())
235  return true;
236 
237  if (MouseButton::None != _id && MouseButton::MAX != _id)
238  {
239  // start capture
240  mMouseCapture[_id.getValue()] = true;
241  // remember last pressed position
242  if (mLayerMouseFocus != nullptr)
243  {
244  IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
245  mLastPressed[_id.getValue()] = point;
246  }
247  }
248 
249  // ищем вверх тот виджет который может принимать фокус
250  Widget* item = mWidgetMouseFocus;
251  while ((item != nullptr) && (!item->getNeedKeyFocus()))
252  item = item->getParent();
253 
254  // устанавливаем перед вызовом т.к. возможно внутри ктонить поменяет фокус под себя
255  setKeyFocusWidget(item);
256 
257  if (isFocusMouse())
258  {
259  mWidgetMouseFocus->_riseMouseButtonPressed(_absx, _absy, _id);
260 
261  // после пресса может сброситься
262  if (mWidgetMouseFocus)
263  {
264  // поднимаем виджет, надо подумать что делать если поменялся фокус клавы
265  LayerManager::getInstance().upLayerItem(mWidgetMouseFocus);
266 
267  // поднимаем пикинг Overlapped окон
268  Widget* pick = mWidgetMouseFocus;
269  do
270  {
271  // если оверлаппед, то поднимаем пикинг
273  {
274  if (pick->getParent()) pick->getParent()->_forcePick(pick);
275  }
276 
277  pick = pick->getParent();
278  }
279  while (pick);
280  }
281  }
282 
283  return true;
284  }
285 
286  bool InputManager::injectMouseRelease(int _absx, int _absy, MouseButton _id)
287  {
288  if (isFocusMouse())
289  {
290  // если активный элемент заблокирован
291  if (!mWidgetMouseFocus->getInheritedEnabled())
292  return true;
293 
294  if (_id != MouseButton::None && _id != MouseButton::MAX)
295  {
296  if (mMouseCapture[_id.getValue()])
297  {
298  // drop capture
299  mMouseCapture[_id.getValue()] = false;
300  }
301  }
302 
303  mWidgetMouseFocus->_riseMouseButtonReleased(_absx, _absy, _id);
304 
305  // после вызова, виджет может быть сброшен
306  if (nullptr != mWidgetMouseFocus)
307  {
308  if (MouseButton::Left == _id)
309  {
310  if (mTimerDoubleClick < INPUT_TIME_DOUBLE_CLICK)
311  {
312  mWidgetMouseFocus->_riseMouseButtonClick();
313  // после вызова, виджет может быть сброшен
314  if (nullptr != mWidgetMouseFocus)
315  mWidgetMouseFocus->_riseMouseButtonDoubleClick();
316  }
317  else
318  {
319  // проверяем над тем ли мы окном сейчас что и были при нажатии
320  Widget* item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);
321  if ( item == mWidgetMouseFocus)
322  {
323  mWidgetMouseFocus->_riseMouseButtonClick();
324  }
325  mTimerDoubleClick = 0;
326  }
327  }
328  }
329 
330  // для корректного отображения
331  injectMouseMove(_absx, _absy, mOldAbsZ);
332 
333  return true;
334  }
335 
336  return false;
337  }
338 
340  {
341  // проверка на переключение языков
342  firstEncoding(_key, true);
343 
344  // запоминаем клавишу
345  storeKey(_key, _text);
346 
347  bool wasFocusKey = isFocusKey();
348 
349  //Pass keystrokes to the current active text widget
350  if (isFocusKey())
351  {
352  mWidgetKeyFocus->_riseKeyButtonPressed(_key, _text);
353  }
354 
355  return wasFocusKey;
356  }
357 
359  {
360  // проверка на переключение языков
361  firstEncoding(_key, false);
362 
363  // сбрасываем клавишу
364  resetKey();
365 
366  bool wasFocusKey = isFocusKey();
367 
368  if (isFocusKey())
369  mWidgetKeyFocus->_riseKeyButtonReleased(_key);
370 
371  return wasFocusKey;
372  }
373 
374  void InputManager::firstEncoding(KeyCode _key, bool bIsKeyPressed)
375  {
376  if ((_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift))
377  mIsShiftPressed = bIsKeyPressed;
378  if ((_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl))
379  mIsControlPressed = bIsKeyPressed;
380  }
381 
383  {
384  if (_widget == mWidgetKeyFocus)
385  return;
386 
387  //-------------------------------------------------------------------------------------//
388  // новый вид рутового фокуса
389  Widget* save_widget = nullptr;
390 
391  // спускаемся по новому виджету и устанавливаем рутовый фокус
392  Widget* root_focus = _widget;
393  while (root_focus != nullptr)
394  {
395  if (root_focus->getRootKeyFocus())
396  {
397  save_widget = root_focus;
398  break;
399  }
400 
401  root_focus->_setRootKeyFocus(true);
402  root_focus->_riseKeyChangeRootFocus(true);
403  root_focus = root_focus->getParent();
404  }
405 
406  // спускаемся по старому виджету и сбрасываем фокус
407  root_focus = mWidgetKeyFocus;
408  while (root_focus != nullptr)
409  {
410  if (root_focus == save_widget)
411  break;
412 
413  root_focus->_setRootKeyFocus(false);
414  root_focus->_riseKeyChangeRootFocus(false);
415  root_focus = root_focus->getParent();
416  }
417  //-------------------------------------------------------------------------------------//
418 
419  // сбрасываем старый
420  if (mWidgetKeyFocus)
421  {
422  mWidgetKeyFocus->_riseKeyLostFocus(_widget);
423  }
424 
425  // устанавливаем новый
426  if (_widget && _widget->getNeedKeyFocus())
427  {
428  _widget->_riseKeySetFocus(mWidgetKeyFocus);
429  }
430 
431  mWidgetKeyFocus = _widget;
432 
433  eventChangeKeyFocus(mWidgetKeyFocus);
434  }
435 
437  {
438  Widget* mouseFocus = mWidgetMouseFocus;
439  mWidgetMouseFocus = nullptr;
440 
441  // спускаемся по старому виджету и сбрасываем фокус
442  Widget* root_focus = mouseFocus;
443  while (root_focus != nullptr)
444  {
445  root_focus->_setRootMouseFocus(false);
446  root_focus->_riseMouseChangeRootFocus(false);
447  root_focus = root_focus->getParent();
448  }
449 
450  for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
451  {
452  if (mMouseCapture[i])
453  {
454  mMouseCapture[i] = false;
455  mouseFocus->_riseMouseButtonReleased(mLastPressed[i].left, mLastPressed[i].top, MouseButton::Enum(i));
456  }
457  }
458 
459  if (nullptr != mouseFocus)
460  {
461  mouseFocus->_riseMouseLostFocus(nullptr);
462  }
463 
464  if (mouseFocus != mWidgetMouseFocus)
465  eventChangeMouseFocus(mWidgetMouseFocus);
466  }
467 
468  // удаляем данный виджет из всех возможных мест
469  void InputManager::_unlinkWidget(Widget* _widget)
470  {
471  if (nullptr == _widget)
472  return;
473 
474  if (mWidgetMouseFocus == _widget)
476 
477  if (_widget == mWidgetKeyFocus)
478  {
479  mWidgetKeyFocus = nullptr;
480  }
481 
482  // ручками сбрасываем, чтобы не менять фокусы
483  for (VectorWidgetPtr::iterator iter = mVectorModalRootWidget.begin(); iter != mVectorModalRootWidget.end(); ++iter)
484  {
485  if (*iter == _widget)
486  {
487  mVectorModalRootWidget.erase(iter);
488  break;
489  }
490  }
491  }
492 
494  {
495  if (nullptr == _widget)
496  return;
497  MYGUI_ASSERT(nullptr == _widget->getParent(), "Modal widget must be root");
498 
500  removeWidgetModal(_widget);
501  mVectorModalRootWidget.push_back(_widget);
502 
503  setKeyFocusWidget(_widget);
505  }
506 
508  {
509  resetKeyFocusWidget(_widget);
511 
512  for (VectorWidgetPtr::iterator iter = mVectorModalRootWidget.begin(); iter != mVectorModalRootWidget.end(); ++iter)
513  {
514  if (*iter == _widget)
515  {
516  mVectorModalRootWidget.erase(iter);
517  break;
518  }
519  }
520  // если еще есть модальные то их фокусируем и поднимаем
521  if (!mVectorModalRootWidget.empty())
522  {
523  setKeyFocusWidget(mVectorModalRootWidget.back());
524  LayerManager::getInstance().upLayerItem(mVectorModalRootWidget.back());
525  }
526  }
527 
528  void InputManager::storeKey(KeyCode _key, Char _text)
529  {
530  mHoldKey = KeyCode::None;
531  mHoldChar = 0;
532 
533  if ( !isFocusKey() ) return;
534  if ( (_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift)
535  || (_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl)
536  || (_key == KeyCode::LeftAlt) || (_key == KeyCode::RightAlt)
537  ) return;
538 
539  mFirstPressKey = true;
540  mHoldKey = _key;
541  mHoldChar = _text;
542  mTimerKey = 0.0f;
543  }
544 
545  void InputManager::resetKey()
546  {
547  mHoldKey = KeyCode::None;
548  mHoldChar = 0;
549  }
550 
551  void InputManager::frameEntered(float _frame)
552  {
553  mTimerDoubleClick += _frame;
554 
555  if ( mHoldKey == KeyCode::None)
556  return;
557 
558  if ( !isFocusKey() )
559  {
560  mHoldKey = KeyCode::None;
561  mHoldChar = 0;
562  return;
563  }
564 
565  mTimerKey += _frame;
566 
567  if (mFirstPressKey)
568  {
569  if (mTimerKey > INPUT_DELAY_FIRST_KEY)
570  {
571  mFirstPressKey = false;
572  mTimerKey = 0.0f;
573  }
574  }
575  else
576  {
577  if (mTimerKey > INPUT_INTERVAL_KEY)
578  {
579  while (mTimerKey > INPUT_INTERVAL_KEY)
580  mTimerKey -= INPUT_INTERVAL_KEY;
581  mWidgetKeyFocus->_riseKeyButtonPressed(mHoldKey, mHoldChar);
582  // focus can be dropped in onKeyButtonPressed
583  if (isFocusKey())
584  mWidgetKeyFocus->_riseKeyButtonReleased(mHoldKey);
585  }
586  }
587 
588  }
589 
591  {
592  if (mWidgetKeyFocus == _widget)
593  setKeyFocusWidget(nullptr);
594  }
595 
597  {
598  if (mLayerMouseFocus != nullptr)
599  return mLayerMouseFocus->getPosition(mMousePosition.left, mMousePosition.top);
600  return mMousePosition;
601  }
602 
604  {
605  return mWidgetMouseFocus != nullptr;
606  }
607 
609  {
610  return mWidgetKeyFocus != nullptr;
611  }
612 
614  {
615  for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
616  {
617  if (mMouseCapture[i])
618  return true;
619  }
620  return false;
621  }
622 
624  {
625  setKeyFocusWidget(nullptr);
626  }
627 
629  {
630  return mWidgetMouseFocus;
631  }
632 
634  {
635  return mWidgetKeyFocus;
636  }
637 
639  {
640  if (_id != MouseButton::None && _id != MouseButton::MAX)
641  {
642  return mLastPressed[_id.getValue()];
643  }
645  }
646 
648  {
649  return mMousePosition;
650  }
651 
653  {
654  return !mVectorModalRootWidget.empty();
655  }
656 
658  {
659  return mIsControlPressed;
660  }
661 
663  {
664  return mIsShiftPressed;
665  }
666 
668  {
669  for (int i = MouseButton::Button0; i < MouseButton::MAX; ++i)
670  {
671  mMouseCapture[i] = false;
672  }
673  }
674 
676  {
677  _unlinkWidget(_widget);
678  }
679 
680 } // namespace MyGUI
Widget properties. Widget_skin_childs Skin childs. Widget widget description should be here...
Definition: MyGUI_Widget.h:29
void _forcePick(Widget *_widget)
void removeWidgetModal(Widget *_widget)
const float INPUT_INTERVAL_KEY
EventHandle_FrameEventDelegate eventFrameStart
Definition: MyGUI_Gui.h:150
void _riseKeySetFocus(Widget *_old)
const IntPoint & getLastPressedPosition(MouseButton _id) const
void _riseMouseSetFocus(Widget *_old)
delegates::IDelegate0 * newDelegate(void(*_func)())
static WidgetManager & getInstance()
virtual IntPoint getPosition(int _left, int _top) const =0
bool getRootKeyFocus() const
void _riseMouseDrag(int _left, int _top, MouseButton _id)
static const IntPoint & getZeroIntPoint()
bool injectMouseMove(int _absx, int _absy, int _absz)
void _riseKeyChangeRootFocus(bool _focus)
bool injectMousePress(int _absx, int _absy, MouseButton _id)
bool getRootMouseFocus() const
static const char * getClassTypeName()
#define nullptr
void _riseMouseLostFocus(Widget *_new)
void _setRootKeyFocus(bool _value)
const float INPUT_TIME_DOUBLE_CLICK
#define MYGUI_LOG(level, text)
const float INPUT_DELAY_FIRST_KEY
void _riseMouseWheel(int _rel)
bool getNeedKeyFocus() const
bool injectKeyRelease(KeyCode _key)
void setKeyFocusWidget(Widget *_widget)
void _riseKeyButtonReleased(KeyCode _key)
void _riseMouseButtonReleased(int _left, int _top, MouseButton _id)
#define MYGUI_ASSERT(exp, dest)
unsigned int Char
Definition: MyGUI_Types.h:51
void _riseKeyButtonPressed(KeyCode _key, Char _char)
void _riseMouseMove(int _left, int _top)
void _riseMouseButtonPressed(int _left, int _top, MouseButton _id)
void registerUnlinker(IUnlinkWidget *_unlink)
void addWidgetModal(Widget *_widget)
Widget * getWidgetFromPoint(int _left, int _top)
WidgetStyle getWidgetStyle() const
Widget * getMouseFocusWidget() const
bool getInheritedEnabled() const
Widget * getParent() const
void unlinkWidget(Widget *_widget)
Widget * getKeyFocusWidget() const
bool injectMouseRelease(int _absx, int _absy, MouseButton _id)
ILayer * getLayer() const
void _setRootMouseFocus(bool _value)
const IntPoint & getMousePosition() const
delegates::CMultiDelegate1< Widget * > eventChangeKeyFocus
bool injectKeyPress(KeyCode _key, Char _text=0)
void _riseMouseChangeRootFocus(bool _focus)
void unregisterUnlinker(IUnlinkWidget *_unlink)
void set(T const &_left, T const &_top)
Definition: MyGUI_TPoint.h:95
void _riseKeyLostFocus(Widget *_new)
delegates::CMultiDelegate1< Widget * > eventChangeMouseFocus
void upLayerItem(Widget *_item)
bool isControlPressed() const