MyGUI  3.0.1
MyGUI_InputManager.cpp
Go to the documentation of this file.
1 
7 /*
8  This file is part of MyGUI.
9 
10  MyGUI is free software: you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  MyGUI is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
22 */
23 #include "MyGUI_Precompiled.h"
24 #include "MyGUI_InputManager.h"
25 #include "MyGUI_Widget.h"
26 #include "MyGUI_WidgetManager.h"
27 #include "MyGUI_Gui.h"
28 #include "MyGUI_WidgetManager.h"
29 
30 namespace MyGUI
31 {
32  const unsigned long INPUT_TIME_DOUBLE_CLICK = 250; //measured in milliseconds
33  const float INPUT_DELAY_FIRST_KEY = 0.4f;
34  const float INPUT_INTERVAL_KEY = 0.05f;
35 
37 
38  void InputManager::initialise()
39  {
40  MYGUI_ASSERT(!mIsInitialise, INSTANCE_TYPE_NAME << " initialised twice");
41  MYGUI_LOG(Info, "* Initialise: " << INSTANCE_TYPE_NAME);
42 
43  mWidgetMouseFocus = 0;
44  mWidgetKeyFocus = 0;
45  mLayerMouseFocus = 0;
46  mIsWidgetMouseCapture = false;
47  mIsShiftPressed = false;
48  mIsControlPressed = false;
49  mHoldKey = KeyCode::None;
50  mHoldChar = 0;
51  mFirstPressKey = true;
52  mTimerKey = 0.0f;
53  mOldAbsZ = 0;
54 
56  Gui::getInstance().eventFrameStart += newDelegate(this, &InputManager::frameEntered);
57 
58  MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully initialized");
59  mIsInitialise = true;
60  }
61 
63  {
64  if (!mIsInitialise) return;
65  MYGUI_LOG(Info, "* Shutdown: " << INSTANCE_TYPE_NAME);
66 
67  Gui::getInstance().eventFrameStart -= newDelegate(this, &InputManager::frameEntered);
68  WidgetManager::getInstance().unregisterUnlinker(this);
69 
70  MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully shutdown");
71  mIsInitialise = false;
72  }
73 
74  bool InputManager::injectMouseMove(int _absx, int _absy, int _absz)
75  {
76  // запоминаем позицию
77  mMousePosition.set(_absx, _absy);
78 
79  // вычисляем прирост по колеса
80  int relz = _absz - mOldAbsZ;
81  mOldAbsZ = _absz;
82 
83  // проверка на скролл
84  if (relz != 0)
85  {
86  bool isFocus = isFocusMouse();
87  if (mWidgetMouseFocus != nullptr) mWidgetMouseFocus->onMouseWheel(relz);
88  return isFocus;
89  }
90 
91  if (mIsWidgetMouseCapture)
92  {
93  if (mWidgetMouseFocus != nullptr)
94  {
95  if (mLayerMouseFocus != nullptr)
96  {
97  IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
98  mWidgetMouseFocus->onMouseDrag(point.left, point.top);
99  }
100  }
101  else
102  mIsWidgetMouseCapture = false;
103  return true;
104  }
105 
106  Widget* old_mouse_focus = mWidgetMouseFocus;
107 
108  // ищем активное окно
109  Widget* item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);
110 
111  // ничего не изменилось
112  if (mWidgetMouseFocus == item)
113  {
114  bool isFocus = isFocusMouse();
115  if (mWidgetMouseFocus != nullptr)
116  {
117  if (mLayerMouseFocus != nullptr)
118  {
119  IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
120  mWidgetMouseFocus->onMouseMove(_absx, _absy);
121  }
122  }
123  return isFocus;
124  }
125 
126  if (item)
127  {
128  // поднимаемся до рута
129  Widget* root = item;
130  while (root->getParent()) root = root->getParent();
131 
132  // проверяем на модальность
133  if (!mVectorModalRootWidget.empty())
134  {
135  if (root != mVectorModalRootWidget.back())
136  {
137  item = nullptr;
138  }
139  }
140 
141  if (item != nullptr)
142  {
143  mLayerMouseFocus = root->getLayer();
144  }
145  }
146 
147  // в методе может пропасть наш виджет
148  WidgetManager::getInstance().addWidgetToUnlink(item);
149 
150 
151  //-------------------------------------------------------------------------------------//
152  // новый вид рутового фокуса мыши
153  Widget* save_widget = nullptr;
154 
155  // спускаемся по новому виджету и устанавливаем рутовый фокус
156  Widget* root_focus = item;
157  while (root_focus != nullptr)
158  {
159  if (root_focus->mRootMouseActive)
160  {
161  save_widget = root_focus;
162  break;
163  }
164  root_focus->mRootMouseActive = true;
165 
166  // в методе может пропасть наш виджет
167  WidgetManager::getInstance().addWidgetToUnlink(root_focus);
168  root_focus->onMouseChangeRootFocus(true);
169  WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
170 
171  if (root_focus)
172  root_focus = root_focus->getParent();
173  }
174 
175  // спускаемся по старому виджету и сбрасываем фокус
176  root_focus = mWidgetMouseFocus;
177  while (root_focus != nullptr)
178  {
179  if (root_focus == save_widget)
180  {
181  break;
182  }
183  root_focus->mRootMouseActive = false;
184 
185  // в методе может пропасть наш виджет
186  WidgetManager::getInstance().addWidgetToUnlink(root_focus);
187  root_focus->onMouseChangeRootFocus(false);
188  WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
189 
190  if (root_focus)
191  root_focus = root_focus->getParent();
192  }
193  //-------------------------------------------------------------------------------------//
194 
195  // смена фокуса, проверяем на доступность виджета
196  if ((mWidgetMouseFocus != nullptr) && (mWidgetMouseFocus->isEnabled()))
197  {
198  mWidgetMouseFocus->onMouseLostFocus(item);
199  }
200 
201  WidgetManager::getInstance().removeWidgetFromUnlink(item);
202 
203 
204  if ((item != nullptr) && (item->isEnabled()))
205  {
206  item->onMouseMove(_absx, _absy);
207  item->onMouseSetFocus(mWidgetMouseFocus);
208  }
209 
210  // запоминаем текущее окно
211  mWidgetMouseFocus = item;
212 
213  if (old_mouse_focus != mWidgetMouseFocus)
214  eventChangeMouseFocus(mWidgetMouseFocus);
215 
216  return isFocusMouse();
217  }
218 
219  bool InputManager::injectMousePress(int _absx, int _absy, MouseButton _id)
220  {
221  Widget* old_key_focus = mWidgetKeyFocus;
222 
223  // если мы щелкнули не на гуй
224  if (!isFocusMouse())
225  {
227 
228  if (old_key_focus != mWidgetKeyFocus)
229  eventChangeKeyFocus(mWidgetKeyFocus);
230 
231  return false;
232  }
233 
234  // если активный элемент заблокирован
235  //FIXME
236  if (!mWidgetMouseFocus->isEnabled())
237  return true;
238 
239  // захватываем только по левой клавише и только если виджету надо
240  if (MouseButton::Left == _id)
241  {
242  // захват окна
243  mIsWidgetMouseCapture = true;
244  // запоминаем место нажатия
245  if (mLayerMouseFocus != nullptr)
246  {
247  IntPoint point = mLayerMouseFocus->getPosition(_absx, _absy);
248  mLastLeftPressed = point;
249  }
250  }
251 
252  // ищем вверх тот виджет который может принимать фокус
253  Widget* item = mWidgetMouseFocus;
254  while ((item != nullptr) && (!item->isNeedKeyFocus()))
255  item = item->getParent();
256 
257  // устанавливаем перед вызовом т.к. возможно внутри ктонить поменяет фокус под себя
258  setKeyFocusWidget(item);
259 
260  if (mWidgetMouseFocus != nullptr)
261  {
262  mWidgetMouseFocus->onMouseButtonPressed(_absx, _absy, _id);
263 
264  // после пресса может сброситься
265  if (mWidgetMouseFocus)
266  {
267  // поднимаем виджет, надо подумать что делать если поменялся фокус клавы
268  LayerManager::getInstance().upLayerItem(mWidgetMouseFocus);
269 
270  // поднимаем пикинг Overlapped окон
271  Widget* pick = mWidgetMouseFocus;
272  do
273  {
274  // если оверлаппед, то поднимаем пикинг
276  {
277  if (pick->getParent()) pick->getParent()->_forcePeek(pick);
278  }
279 
280  pick = pick->getParent();
281  }
282  while (pick);
283  }
284  }
285 
286  if (old_key_focus != mWidgetKeyFocus)
287  eventChangeKeyFocus(mWidgetKeyFocus);
288 
289  return true;
290  }
291 
292  bool InputManager::injectMouseRelease(int _absx, int _absy, MouseButton _id)
293  {
294  if (isFocusMouse())
295  {
296  // если активный элемент заблокирован
297  if (!mWidgetMouseFocus->isEnabled())
298  return true;
299 
300  mWidgetMouseFocus->onMouseButtonReleased(_absx, _absy, _id);
301 
302  if (mIsWidgetMouseCapture)
303  {
304  // сбрасываем захват
305  mIsWidgetMouseCapture = false;
306 
307  // после вызова, виджет может быть сброшен
308  if (nullptr != mWidgetMouseFocus)
309  {
310  if ((MouseButton::Left == _id) && mTimer.getMilliseconds() < INPUT_TIME_DOUBLE_CLICK)
311  {
312  mWidgetMouseFocus->onMouseButtonClick();
313  // после вызова, виджет может быть сброшен
314  if (nullptr != mWidgetMouseFocus) mWidgetMouseFocus->onMouseButtonDoubleClick();
315  }
316  else
317  {
318  // проверяем над тем ли мы окном сейчас что и были при нажатии
319  Widget* item = LayerManager::getInstance().getWidgetFromPoint(_absx, _absy);
320  if ( item == mWidgetMouseFocus)
321  {
322  mWidgetMouseFocus->onMouseButtonClick();
323  }
324  mTimer.reset();
325  }
326  }
327  }
328 
329  // для корректного отображения
330  injectMouseMove(_absx, _absy, mOldAbsZ);
331 
332  return true;
333  }
334 
335  return false;
336  }
337 
339  {
340  // проверка на переключение языков
341  firstEncoding(_key, true);
342 
343  // запоминаем клавишу
344  storeKey(_key, _text);
345 
346  bool wasFocusKey = isFocusKey();
347 
348  //Pass keystrokes to the current active text widget
349  if (isFocusKey())
350  {
351  mWidgetKeyFocus->onKeyButtonPressed(_key, _text);
352  }
353 
354  return wasFocusKey;
355  }
356 
358  {
359  // проверка на переключение языков
360  firstEncoding(_key, false);
361 
362  // сбрасываем клавишу
363  resetKey();
364 
365  bool wasFocusKey = isFocusKey();
366 
367  if (isFocusKey()) mWidgetKeyFocus->onKeyButtonReleased(_key);
368 
369  return wasFocusKey;
370  }
371 
372  void InputManager::firstEncoding(KeyCode _key, bool bIsKeyPressed)
373  {
374  if ((_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift))
375  mIsShiftPressed = bIsKeyPressed;
376  if ((_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl))
377  mIsControlPressed = bIsKeyPressed;
378  }
379 
381  {
382  if (_widget == mWidgetKeyFocus)
383  return;
384 
385  //-------------------------------------------------------------------------------------//
386  // новый вид рутового фокуса
387  Widget* save_widget = nullptr;
388 
389  // спускаемся по новому виджету и устанавливаем рутовый фокус
390  Widget* root_focus = _widget;
391  while (root_focus != nullptr)
392  {
393  if (root_focus->mRootKeyActive)
394  {
395  save_widget = root_focus;
396  break;
397  }
398  root_focus->mRootKeyActive = true;
399 
400  // в методе может пропасть наш виджет
401  WidgetManager::getInstance().addWidgetToUnlink(root_focus);
402  root_focus->onKeyChangeRootFocus(true);
403  WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
404 
405  if (root_focus)
406  root_focus = root_focus->getParent();
407  }
408 
409  // спускаемся по старому виджету и сбрасываем фокус
410  root_focus = mWidgetKeyFocus;
411  while (root_focus != nullptr)
412  {
413  if (root_focus == save_widget)
414  {
415  break;
416  }
417  root_focus->mRootKeyActive = false;
418 
419  // в методе может пропасть наш виджет
420  WidgetManager::getInstance().addWidgetToUnlink(root_focus);
421  root_focus->onKeyChangeRootFocus(false);
422  WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
423 
424  if (root_focus)
425  root_focus = root_focus->getParent();
426  }
427  //-------------------------------------------------------------------------------------//
428 
429  // сбрасываем старый
430  if (mWidgetKeyFocus)
431  {
432  mWidgetKeyFocus->onKeyLostFocus(_widget);
433  }
434 
435  // устанавливаем новый
436  if (_widget && _widget->isNeedKeyFocus())
437  {
438  _widget->onKeySetFocus(mWidgetKeyFocus);
439  }
440 
441  mWidgetKeyFocus = _widget;
442  }
443 
445  {
446  // спускаемся по старому виджету и сбрасываем фокус
447  Widget* root_focus = mWidgetMouseFocus;
448  while (root_focus != nullptr)
449  {
450  root_focus->mRootMouseActive = false;
451 
452  // в методе может пропасть наш виджет
453  WidgetManager::getInstance().addWidgetToUnlink(root_focus);
454  root_focus->onMouseChangeRootFocus(false);
455  WidgetManager::getInstance().removeWidgetFromUnlink(root_focus);
456 
457  if (root_focus)
458  root_focus = root_focus->getParent();
459  }
460 
461  mIsWidgetMouseCapture = false;
462  if (nullptr != mWidgetMouseFocus)
463  {
464  mWidgetMouseFocus->onMouseLostFocus(nullptr);
465  mWidgetMouseFocus = nullptr;
466  }
467 
468  }
469 
470  // удаляем данный виджет из всех возможных мест
471  void InputManager::_unlinkWidget(Widget* _widget)
472  {
473  if (nullptr == _widget) return;
474  if (_widget == mWidgetMouseFocus)
475  {
476  mIsWidgetMouseCapture = false;
477  mWidgetMouseFocus = nullptr;
478  }
479  if (_widget == mWidgetKeyFocus)
480  {
481  mWidgetKeyFocus = nullptr;
482  }
483 
484  // ручками сбрасываем, чтобы не менять фокусы
485  for (VectorWidgetPtr::iterator iter=mVectorModalRootWidget.begin(); iter!=mVectorModalRootWidget.end(); ++iter)
486  {
487  if ((*iter == _widget))
488  {
489  mVectorModalRootWidget.erase(iter);
490  break;
491  }
492  }
493 
494  }
495 
497  {
498  if (nullptr == _widget) return;
499  MYGUI_ASSERT(nullptr == _widget->getParent(), "Modal widget must be root");
500 
502  removeWidgetModal(_widget);
503  mVectorModalRootWidget.push_back(_widget);
504 
505  setKeyFocusWidget(_widget);
506  LayerManager::getInstance().upLayerItem(_widget);
507  }
508 
510  {
511  resetKeyFocusWidget(_widget);
513 
514  for (VectorWidgetPtr::iterator iter=mVectorModalRootWidget.begin(); iter!=mVectorModalRootWidget.end(); ++iter)
515  {
516  if ((*iter == _widget))
517  {
518  mVectorModalRootWidget.erase(iter);
519  break;
520  }
521  }
522  // если еще есть модальные то их фокусируем и поднимаем
523  if (!mVectorModalRootWidget.empty())
524  {
525  setKeyFocusWidget(mVectorModalRootWidget.back());
526  LayerManager::getInstance().upLayerItem(mVectorModalRootWidget.back());
527  }
528  }
529 
530  void InputManager::storeKey(KeyCode _key, Char _text)
531  {
532  mHoldKey = KeyCode::None;
533  mHoldChar = 0;
534 
535  if ( !isFocusKey() ) return;
536  if ( (_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift)
537  || (_key == KeyCode::LeftControl) || (_key == KeyCode::RightControl)
538  || (_key == KeyCode::LeftAlt) || (_key == KeyCode::RightAlt)
539  ) return;
540 
541  mFirstPressKey = true;
542  mHoldKey = _key;
543  mHoldChar = _text;
544  mTimerKey = 0.0f;
545  }
546 
547  void InputManager::resetKey()
548  {
549  mHoldKey = KeyCode::None;
550  mHoldChar = 0;
551  }
552 
553  void InputManager::frameEntered(float _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) mTimerKey -= INPUT_INTERVAL_KEY;
580  mWidgetKeyFocus->onKeyButtonPressed(mHoldKey, mHoldChar);
581  // focus can be dropped in onKeyButtonPressed
582  if ( isFocusKey() ) mWidgetKeyFocus->onKeyButtonReleased(mHoldKey);
583  }
584  }
585 
586  }
587 
589  {
590  if (mWidgetKeyFocus == _widget)
591  setKeyFocusWidget(nullptr);
592  }
593 
595  {
596  if (mLayerMouseFocus != nullptr)
597  return mLayerMouseFocus->getPosition(mMousePosition.left, mMousePosition.top);
598  return mMousePosition;
599  }
600 
601 } // namespace MyGUI