The Battle for Wesnoth  1.15.13+dev
handler.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2018 by Mark de Wever <koraq@xs4all.nl>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
18 
20 #include "gui/core/timer.hpp"
21 #include "gui/core/log.hpp"
22 #include "gui/widgets/helper.hpp"
23 #include "gui/widgets/widget.hpp"
24 #include "gui/widgets/window.hpp"
25 #include "hotkey/hotkey_item.hpp"
26 #include "video.hpp"
28 #include "sdl/userevent.hpp"
29 #include "utils/ranges.hpp"
30 
31 #include <cassert>
32 
33 /**
34  * @todo The items below are not implemented yet.
35  *
36  * - Tooltips have a fixed short time until showing up.
37  * - Tooltips are shown until the widget is exited.
38  * - Help messages aren't shown yet.
39  *
40  * @note it might be that tooltips will be shown independent of a window and in
41  * their own window, therefore the code will be cleaned up after that has been
42  * determined.
43  */
44 
45 /*
46  * At some point in the future this event handler should become the main event
47  * handler. This switch controls the experimental switch for that change.
48  */
49 //#define MAIN_EVENT_HANDLER
50 
51 /* Since this code is still very experimental it's not enabled yet. */
52 //#define ENABLE
53 
54 namespace gui2
55 {
56 
57 namespace event
58 {
59 
60 /***** Static data. *****/
61 static std::unique_ptr<class sdl_event_handler> handler_ = nullptr;
63 
64 #ifdef MAIN_EVENT_HANDLER
65 static unsigned draw_interval = 0;
66 static unsigned event_poll_interval = 0;
67 
68 /***** Static functions. *****/
69 
70 /**
71  * SDL_AddTimer() callback for the draw event.
72  *
73  * When this callback is called it pushes a new draw event in the event queue.
74  *
75  * @returns The new timer interval, 0 to stop.
76  */
77 static uint32_t timer_sdl_draw_event(uint32_t, void*)
78 {
79  // DBG_GUI_E << "Pushing draw event in queue.\n";
80 
81  SDL_Event event;
83 
84  event.type = DRAW_EVENT;
85  event.user = data;
86 
87  SDL_PushEvent(&event);
88  return draw_interval;
89 }
90 
91 /**
92  * SDL_AddTimer() callback for the poll event.
93  *
94  * When this callback is called it will run the events in the SDL event queue.
95  *
96  * @returns The new timer interval, 0 to stop.
97  */
98 static uint32_t timer_sdl_poll_events(uint32_t, void*)
99 {
100  try
101  {
102  events::pump();
103  }
104  catch(CVideo::quit&)
105  {
106  return 0;
107  }
108  return event_poll_interval;
109 }
110 #endif
111 
112 /***** handler class. *****/
113 
114 /**
115  * This singleton class handles all events.
116  *
117  * It's a new experimental class.
118  */
120 {
121  friend bool gui2::is_in_dialog();
122 
123 public:
125 
127 
128  /** Inherited from events::sdl_handler. */
129  void handle_event(const SDL_Event& event) override;
130 
131  /** Inherited from events::sdl_handler. */
132  void handle_window_event(const SDL_Event& event) override;
133 
134  /**
135  * Connects a dispatcher.
136  *
137  * @param dispatcher The dispatcher to connect.
138  */
140 
141  /**
142  * Disconnects a dispatcher.
143  *
144  * @param dispatcher The dispatcher to disconnect.
145  */
146  void disconnect(dispatcher* dispatcher);
147 
148  /**
149  * Returns all dispatchers in the Z order.
150  */
151  std::vector<dispatcher*>& get_dispatchers() { return dispatchers_; }
152 
153  /** The dispatcher that captured the mouse focus. */
154  dispatcher* mouse_focus;
155 
156 private:
157  /**
158  * Reinitializes the state of all dispatchers.
159  *
160  * This is needed when the application gets activated, to make sure the
161  * state of mainly the mouse is set properly.
162  */
163  void activate();
164 
165  /***** Handlers *****/
166 
167  /** Fires a raw SDL event. */
168  void raw_event(const SDL_Event &event);
169 
170  /** Fires a draw event. */
172  void draw() override;
173  void draw_everything();
174 
175  /**
176  * Fires a video resize event.
177  *
178  * @param new_size The new size of the window.
179  */
180  void video_resize(const point& new_size);
181 
182  /**
183  * Fires a generic mouse event.
184  *
185  * @param event The event to fire.
186  * @param position The position of the mouse.
187  */
188  void mouse(const ui_event event, const point& position);
189 
190  /**
191  * Fires a mouse button up event.
192  *
193  * @param position The position of the mouse.
194  * @param button The SDL id of the button that caused the
195  * event.
196  */
197  void mouse_button_up(const point& position, const uint8_t button);
198 
199  /**
200  * Fires a mouse button down event.
201  *
202  * @param position The position of the mouse.
203  * @param button The SDL id of the button that caused the
204  * event.
205  */
206  void mouse_button_down(const point& position, const uint8_t button);
207 
208  /**
209  * Fires a mouse wheel event.
210  *
211  * @param position The position of the mouse.
212  * @param scrollx The amount of horizontal scrolling.
213  * @param scrolly The amount of vertical scrolling.
214  */
215  void mouse_wheel(const point& position, int scrollx, int scrolly);
216 
217  /**
218  * Gets the dispatcher that wants to receive the keyboard input.
219  *
220  * @returns The dispatcher.
221  * @retval nullptr No dispatcher found.
222  */
223  dispatcher* keyboard_dispatcher();
224 
225  /**
226  * Fires a touch-moved event.
227  *
228  * @param position The position touched.
229  * @param distance The distance moved.
230  */
231  void touch_motion(const point& position, const point& distance);
232 
233  /**
234  * Fires a touch "finger down" event.
235  *
236  * @param position The position touched.
237  */
238  void touch_down(const point& position);
239 
240  /**
241  * Fires a touch "finger up" event.
242  *
243  * @param position The position touched.
244  */
245  void touch_up(const point& position);
246 
247  /**
248  * Fires a touch gesture event.
249  * @param center the center of gesture
250  * @param dTheta the amount that the fingers rotated during this motion
251  * @param dDist the amount that the fingers pinched during this motion
252  * @param numFingers the number of fingers used in the gesture
253  */
254  void touch_multi_gesture(const point& center, float dTheta, float dDist, uint8_t numFingers);
255 
256  /**
257  * Handles a hat motion event.
258  *
259  * @param event The SDL joystick hat event triggered.
260  */
261  void hat_motion(const SDL_Event& event);
262 
263  /**
264  * Handles a joystick button down event.
265  *
266  * @param event The SDL joystick button event triggered.
267  */
268  void button_down(const SDL_Event& event);
269 
270  /**
271  * Fires a key down event.
272  *
273  * @param event The SDL keyboard event triggered.
274  */
275  void key_down(const SDL_Event& event);
276 
277  /**
278  * Handles the pressing of a hotkey.
279  *
280  * @param key The hotkey item pressed.
281  *
282  * @returns True if there was a valid dispatcher with
283  * which to execute the hotkey callback, false
284  * otherwise.
285  */
286  bool hotkey_pressed(const hotkey::hotkey_ptr key);
287 
288  /**
289  * Fires a key down event.
290  *
291  * @param key The SDL key code of the key pressed.
292  * @param modifier The SDL key modifiers used.
293  * @param unicode The unicode value for the key pressed.
294  */
295  void key_down(const SDL_Keycode key,
296  const SDL_Keymod modifier,
297  const std::string& unicode);
298 
299  /**
300  * Fires a text input event.
301  *
302  * @param unicode The unicode value for the text entered.
303  */
304  void text_input(const std::string& unicode);
305 
306  /**
307  * Fires a text editing event.
308  *
309  * @param unicode The unicode value for the text being edited.
310  * @param start The start position for the text being edited.
311  * @param len The selection length for the text being edited.
312  */
313  void text_editing(const std::string& unicode, int32_t start, int32_t len);
314 
315  /**
316  * Fires a keyboard event which has no parameters.
317  *
318  * This can happen for example when the mouse wheel is used.
319  *
320  * @param event The event to fire.
321  */
322  void keyboard(const ui_event event);
323 
324  /**
325  * Fires a CLOSE_WINDOW event for the window with the given ID.
326  *
327  * @param window_id The ID of the window to close.
328  */
329  void close_window(const unsigned window_id);
330 
331  /**
332  * The dispatchers.
333  *
334  * The order of the items in the list is also the z-order the front item
335  * being the one completely in the background and the back item the one
336  * completely in the foreground.
337  */
338  std::vector<dispatcher*> dispatchers_;
339 
340  /**
341  * Needed to determine which dispatcher gets the keyboard events.
342  *
343  * NOTE the keyboard events aren't really wired in yet so doesn't do much.
344  */
345  dispatcher* keyboard_focus_;
346  friend void capture_keyboard(dispatcher* dispatcher);
347 };
348 
350  : events::sdl_handler(false)
351  , mouse_focus(nullptr)
352  , dispatchers_()
353  , keyboard_focus_(nullptr)
354 {
355  if(SDL_WasInit(SDL_INIT_TIMER) == 0) {
356  if(SDL_InitSubSystem(SDL_INIT_TIMER) == -1) {
357  assert(false);
358  }
359  }
360 
361 // The event context is created now we join it.
362 #ifdef ENABLE
363  join();
364 #endif
365 }
366 
368 {
369 #ifdef ENABLE
370  leave();
371 #endif
372 }
373 
374 void sdl_event_handler::handle_event(const SDL_Event& event)
375 {
376  /** No dispatchers drop the event. */
377  if(dispatchers_.empty()) {
378  return;
379  }
380 
381  uint8_t button = event.button.button;
382  CVideo& video = CVideo::get_singleton();
383 
384  switch(event.type) {
385  case SDL_MOUSEMOTION:
386 #ifdef MOUSE_TOUCH_EMULATION
387  // There's no finger motion when it's not down.
388  if (event.motion.state != 0)
389 #endif
390  {
391  mouse(SDL_MOUSE_MOTION, {event.motion.x, event.motion.y});
392  }
393  break;
394 
395  case SDL_MOUSEBUTTONDOWN:
396  {
397  mouse_button_down({event.button.x, event.button.y}, button);
398  }
399  break;
400 
401  case SDL_MOUSEBUTTONUP:
402  {
403  mouse_button_up({event.button.x, event.button.y}, button);
404  }
405  break;
406 
407  case SDL_MOUSEWHEEL:
408  mouse_wheel(get_mouse_position(), event.wheel.x, event.wheel.y);
409  break;
410 
411  case SHOW_HELPTIP_EVENT:
413  break;
414 
416  // remove_popup();
417  break;
418 
419  case DRAW_EVENT:
420  draw();
421  break;
422 
423  case DRAW_ALL_EVENT:
424  draw_everything();
425  break;
426 
427  case TIMER_EVENT:
428  execute_timer(reinterpret_cast<std::size_t>(event.user.data1));
429  break;
430 
431  case CLOSE_WINDOW_EVENT:
432  close_window(event.user.code);
433  break;
434 
435  case SDL_JOYBUTTONDOWN:
436  button_down(event);
437  break;
438 
439  case SDL_JOYBUTTONUP:
440  break;
441 
442  case SDL_JOYAXISMOTION:
443  break;
444 
445  case SDL_JOYHATMOTION:
446  hat_motion(event);
447  break;
448 
449  case SDL_KEYDOWN:
450  key_down(event);
451  break;
452 
453  case SDL_WINDOWEVENT:
454  switch(event.window.event) {
455  case SDL_WINDOWEVENT_EXPOSED:
456  draw();
457  break;
458 
459  case SDL_WINDOWEVENT_RESIZED:
460  video_resize({event.window.data1, event.window.data2});
461  break;
462 
463  case SDL_WINDOWEVENT_ENTER:
464  case SDL_WINDOWEVENT_FOCUS_GAINED:
465  activate();
466  break;
467  }
468 
469  break;
470 
471  case SDL_TEXTINPUT:
472  key_down(event);
473  break;
474 
475  case SDL_TEXTEDITING:
476  text_editing(event.edit.text, event.edit.start, event.edit.length);
477  break;
478 
479  case SDL_FINGERMOTION:
480  {
481  SDL_Rect r = video.screen_area();
482  touch_motion(point(event.tfinger.x * r.w, event.tfinger.y * r.h),
483  point(event.tfinger.dx * r.w, event.tfinger.dy * r.h));
484  }
485  break;
486 
487  case SDL_FINGERUP:
488  {
489  SDL_Rect r = video.screen_area();
490  touch_up(point(event.tfinger.x * r.w, event.tfinger.y * r.h));
491  }
492  break;
493 
494  case SDL_FINGERDOWN:
495  {
496  SDL_Rect r = video.screen_area();
497  touch_down(point(event.tfinger.x * r.w, event.tfinger.y * r.h));
498  }
499  break;
500 
501  case SDL_MULTIGESTURE:
502  {
503  SDL_Rect r = video.screen_area();
504  touch_multi_gesture(point(event.mgesture.x * r.w, event.mgesture.y * r.h),
505  event.mgesture.dTheta, event.mgesture.dDist, event.mgesture.numFingers);
506  }
507  break;
508 
509 #if(defined(_X11) && !defined(__APPLE__)) || defined(_WIN32)
510  case SDL_SYSWMEVENT:
511  /* DO NOTHING */
512  break;
513 #endif
514 
515  // Silently ignored events.
516  case SDL_KEYUP:
517  case DOUBLE_CLICK_EVENT:
518  break;
519 
520  default:
521 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
522  WRN_GUI_E << "Unhandled event " << static_cast<uint32_t>(event.type)
523  << ".\n";
524 #endif
525  break;
526  }
527 
528  raw_event(event);
529 }
530 
531 void sdl_event_handler::handle_window_event(const SDL_Event& event)
532 {
533  handle_event(event);
534 }
535 
537 {
538  assert(std::find(dispatchers_.begin(), dispatchers_.end(), dispatcher)
539  == dispatchers_.end());
540 
541  if(dispatchers_.empty()) {
542  event_context = new events::event_context();
543  join();
544  }
545 
546  dispatchers_.push_back(dispatcher);
547 }
548 
550 {
551  /***** Validate pre conditions. *****/
552  auto itor = std::find(dispatchers_.begin(), dispatchers_.end(), disp);
553  assert(itor != dispatchers_.end());
554 
555  /***** Remove dispatcher. *****/
556  dispatchers_.erase(itor);
557 
558  if(disp == mouse_focus) {
559  mouse_focus = nullptr;
560  }
561  if(disp == keyboard_focus_) {
562  keyboard_focus_ = nullptr;
563  }
564 
565  /***** Set proper state for the other dispatchers. *****/
566  for(auto d : dispatchers_)
567  {
568  dynamic_cast<widget&>(*d).set_is_dirty(true);
569  }
570 
571  activate();
572 
573  /***** Validate post conditions. *****/
574  assert(std::find(dispatchers_.begin(), dispatchers_.end(), disp)
575  == dispatchers_.end());
576 
577  if(dispatchers_.empty()) {
578  leave();
579  delete event_context;
580  event_context = nullptr;
581  }
582 }
583 
585 {
586  for(auto dispatcher : dispatchers_)
587  {
588  dispatcher->fire(SDL_ACTIVATE, dynamic_cast<widget&>(*dispatcher), nullptr);
589  }
590 }
591 
593 {
594  for(auto dispatcher : dispatchers_)
595  {
596  dispatcher->fire(DRAW, dynamic_cast<widget&>(*dispatcher));
597  }
598 
599  if(!dispatchers_.empty()) {
601  }
602 }
603 
605 {
606  for(auto dispatcher : dispatchers_) {
607  dynamic_cast<widget&>(*dispatcher).set_is_dirty(true);
608  }
609 
610  draw();
611 }
612 
614 {
615  DBG_GUI_E << "Firing: " << SDL_VIDEO_RESIZE << ".\n";
616 
617  for(auto dispatcher : dispatchers_)
618  {
619  dispatcher->fire(SDL_VIDEO_RESIZE, dynamic_cast<widget&>(*dispatcher), new_size);
620  }
621 }
622 
623 void sdl_event_handler::raw_event(const SDL_Event& event) {
624  DBG_GUI_E << "Firing raw event\n";
625 
626  for(auto dispatcher : dispatchers_)
627  {
628  dispatcher->fire(SDL_RAW_EVENT, dynamic_cast<widget&>(*dispatcher), event);
629  }
630 }
631 
632 void sdl_event_handler::mouse(const ui_event event, const point& position)
633 {
634  DBG_GUI_E << "Firing: " << event << ".\n";
635 
636  if(mouse_focus) {
637  mouse_focus->fire(event, dynamic_cast<widget&>(*mouse_focus), position);
638  return;
639  }
640 
643  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher), position);
644  break;
645  }
646 
648  continue;
649  }
650 
651  if(dispatcher->is_at(position)) {
652  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher), position);
653  break;
654  }
655  }
656 }
657 
658 void sdl_event_handler::mouse_button_up(const point& position, const uint8_t button)
659 {
660  switch(button) {
661  case SDL_BUTTON_LEFT:
662  mouse(SDL_LEFT_BUTTON_UP, position);
663  break;
664  case SDL_BUTTON_MIDDLE:
665  mouse(SDL_MIDDLE_BUTTON_UP, position);
666  break;
667  case SDL_BUTTON_RIGHT:
668  mouse(SDL_RIGHT_BUTTON_UP, position);
669  break;
670  default:
671 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
672  WRN_GUI_E << "Unhandled 'mouse button up' event for button "
673  << static_cast<uint32_t>(button) << ".\n";
674 #endif
675  break;
676  }
677 }
678 
679 void sdl_event_handler::mouse_button_down(const point& position, const uint8_t button)
680 {
681  switch(button) {
682  case SDL_BUTTON_LEFT:
683  mouse(SDL_LEFT_BUTTON_DOWN, position);
684  break;
685  case SDL_BUTTON_MIDDLE:
686  mouse(SDL_MIDDLE_BUTTON_DOWN, position);
687  break;
688  case SDL_BUTTON_RIGHT:
689  mouse(SDL_RIGHT_BUTTON_DOWN, position);
690  break;
691  default:
692 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
693  WRN_GUI_E << "Unhandled 'mouse button down' event for button "
694  << static_cast<uint32_t>(button) << ".\n";
695 #endif
696  break;
697  }
698 }
699 
700 void sdl_event_handler::mouse_wheel(const point& position, int x, int y)
701 {
702  if(x > 0) {
703  mouse(SDL_WHEEL_RIGHT, position);
704  } else if(x < 0) {
705  mouse(SDL_WHEEL_LEFT, position);
706  }
707 
708  if(y < 0) {
709  mouse(SDL_WHEEL_DOWN, position);
710  } else if(y > 0) {
711  mouse(SDL_WHEEL_UP, position);
712  }
713 }
714 
716 {
717  if(keyboard_focus_) {
718  return keyboard_focus_;
719  }
720 
723  return dispatcher;
724  }
725  }
726 
727  return nullptr;
728 }
729 
730 void sdl_event_handler::touch_motion(const point& position, const point& distance)
731 {
733  dispatcher->fire(SDL_TOUCH_MOTION , dynamic_cast<widget&>(*dispatcher), position, distance);
734  }
735 }
736 
737 void sdl_event_handler::touch_up(const point& position)
738 {
740  dispatcher->fire(SDL_TOUCH_UP, dynamic_cast<widget&>(*dispatcher), position);
741  }
742 }
743 
745 {
747  dispatcher->fire(SDL_TOUCH_DOWN, dynamic_cast<widget&>(*dispatcher), position);
748  }
749 }
750 
751 void sdl_event_handler::touch_multi_gesture(const point& center, float dTheta, float dDist, uint8_t numFingers)
752 {
754  dispatcher->fire(SDL_TOUCH_MULTI_GESTURE, dynamic_cast<widget&>(*dispatcher), center, dTheta, dDist, numFingers);
755  }
756 }
757 
758 void sdl_event_handler::hat_motion(const SDL_Event& event)
759 {
760  const hotkey::hotkey_ptr& hk = hotkey::get_hotkey(event);
761  bool done = false;
762  if(!hk->null()) {
763  done = hotkey_pressed(hk);
764  }
765  if(!done) {
766  // TODO fendrin think about handling hat motions that are not bound to a
767  // hotkey.
768  }
769 }
770 
771 void sdl_event_handler::button_down(const SDL_Event& event)
772 {
773  const hotkey::hotkey_ptr hk = hotkey::get_hotkey(event);
774  bool done = false;
775  if(!hk->null()) {
776  done = hotkey_pressed(hk);
777  }
778  if(!done) {
779  // TODO fendrin think about handling button down events that are not
780  // bound to a hotkey.
781  }
782 }
783 
784 void sdl_event_handler::key_down(const SDL_Event& event)
785 {
786  const hotkey::hotkey_ptr hk = hotkey::get_hotkey(event);
787  bool done = false;
788  if(!hk->null()) {
789  done = hotkey_pressed(hk);
790  }
791  if(!done) {
792  if(event.type == SDL_TEXTINPUT) {
793  text_input(event.text.text);
794  } else {
795  key_down(event.key.keysym.sym, static_cast<SDL_Keymod>(event.key.keysym.mod), "");
796  }
797  }
798 }
799 
800 void sdl_event_handler::text_input(const std::string& unicode)
801 {
802  key_down(SDLK_UNKNOWN, static_cast<SDL_Keymod>(0), unicode);
803 
806  dynamic_cast<widget&>(*dispatcher),
807  unicode, -1, -1);
808  }
809 }
810 
811 void sdl_event_handler::text_editing(const std::string& unicode, int32_t start, int32_t len)
812 {
815  dynamic_cast<widget&>(*dispatcher),
816  unicode, start, len);
817  }
818 }
819 
821 {
823  return dispatcher->execute_hotkey(hotkey::get_id(key->get_command()));
824  }
825 
826  return false;
827 }
828 
829 void sdl_event_handler::key_down(const SDL_Keycode key,
830  const SDL_Keymod modifier,
831  const std::string& unicode)
832 {
833  DBG_GUI_E << "Firing: " << SDL_KEY_DOWN << ".\n";
834 
836  dispatcher->fire(SDL_KEY_DOWN,
837  dynamic_cast<widget&>(*dispatcher),
838  key,
839  modifier,
840  unicode);
841  }
842 }
843 
845 {
846  DBG_GUI_E << "Firing: " << event << ".\n";
847 
849  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher));
850  }
851 }
852 
853 void sdl_event_handler::close_window(const unsigned window_id)
854 {
855  DBG_GUI_E << "Firing " << CLOSE_WINDOW << ".\n";
856 
857  window* window = window::window_instance(window_id);
858  if(window) {
859  window->fire(CLOSE_WINDOW, *window);
860  }
861 }
862 
863 /***** manager class. *****/
864 
866 {
867  handler_.reset(new sdl_event_handler());
868 
869 #ifdef MAIN_EVENT_HANDLER
870  draw_interval = 30;
871  SDL_AddTimer(draw_interval, timer_sdl_draw_event, nullptr);
872 
873  event_poll_interval = 10;
874  SDL_AddTimer(event_poll_interval, timer_sdl_poll_events, nullptr);
875 #endif
876 }
877 
879 {
880  handler_.reset(nullptr);
881 
882 #ifdef MAIN_EVENT_HANDLER
883  draw_interval = 0;
884  event_poll_interval = 0;
885 #endif
886 }
887 
888 /***** free functions class. *****/
889 
891 {
892  assert(handler_);
893  assert(dispatcher);
894  handler_->connect(dispatcher);
895 }
896 
898 {
899  assert(handler_);
900  assert(dispatcher);
901  handler_->disconnect(dispatcher);
902 }
903 
904 std::vector<dispatcher*>& get_all_dispatchers()
905 {
906  assert(handler_);
907  return handler_->get_dispatchers();
908 }
909 
911 {
913 
914  SDL_Event event{};
915  event.type = SDL_MOUSEMOTION;
916  event.motion.type = SDL_MOUSEMOTION;
917  event.motion.x = mouse.x;
918  event.motion.y = mouse.y;
919 
920  SDL_PushEvent(&event);
921 }
922 
924 {
925  assert(handler_);
926  assert(dispatcher);
927  handler_->mouse_focus = dispatcher;
928 }
929 
931 {
932  assert(handler_);
933  assert(dispatcher);
934  if(handler_->mouse_focus == dispatcher) {
935  handler_->mouse_focus = nullptr;
936  }
937 }
938 
940 {
941  assert(handler_);
942  assert(dispatcher);
943  assert(dispatcher->get_want_keyboard_input());
944 
945  handler_->keyboard_focus_ = dispatcher;
946 }
947 
948 std::ostream& operator<<(std::ostream& stream, const ui_event event)
949 {
950  switch(event) {
951  case DRAW:
952  stream << "draw";
953  break;
954  case CLOSE_WINDOW:
955  stream << "close window";
956  break;
957  case SDL_VIDEO_RESIZE:
958  stream << "SDL video resize";
959  break;
960  case SDL_MOUSE_MOTION:
961  stream << "SDL mouse motion";
962  break;
963  case MOUSE_ENTER:
964  stream << "mouse enter";
965  break;
966  case MOUSE_LEAVE:
967  stream << "mouse leave";
968  break;
969  case MOUSE_MOTION:
970  stream << "mouse motion";
971  break;
973  stream << "SDL left button down";
974  break;
975  case SDL_LEFT_BUTTON_UP:
976  stream << "SDL left button up";
977  break;
978  case LEFT_BUTTON_DOWN:
979  stream << "left button down";
980  break;
981  case LEFT_BUTTON_UP:
982  stream << "left button up";
983  break;
984  case LEFT_BUTTON_CLICK:
985  stream << "left button click";
986  break;
988  stream << "left button double click";
989  break;
991  stream << "SDL middle button down";
992  break;
994  stream << "SDL middle button up";
995  break;
996  case MIDDLE_BUTTON_DOWN:
997  stream << "middle button down";
998  break;
999  case MIDDLE_BUTTON_UP:
1000  stream << "middle button up";
1001  break;
1002  case MIDDLE_BUTTON_CLICK:
1003  stream << "middle button click";
1004  break;
1006  stream << "middle button double click";
1007  break;
1008  case SDL_RIGHT_BUTTON_DOWN:
1009  stream << "SDL right button down";
1010  break;
1011  case SDL_RIGHT_BUTTON_UP:
1012  stream << "SDL right button up";
1013  break;
1014  case RIGHT_BUTTON_DOWN:
1015  stream << "right button down";
1016  break;
1017  case RIGHT_BUTTON_UP:
1018  stream << "right button up";
1019  break;
1020  case RIGHT_BUTTON_CLICK:
1021  stream << "right button click";
1022  break;
1024  stream << "right button double click";
1025  break;
1026  case SDL_WHEEL_LEFT:
1027  stream << "SDL wheel left";
1028  break;
1029  case SDL_WHEEL_RIGHT:
1030  stream << "SDL wheel right";
1031  break;
1032  case SDL_WHEEL_UP:
1033  stream << "SDL wheel up";
1034  break;
1035  case SDL_WHEEL_DOWN:
1036  stream << "SDL wheel down";
1037  break;
1038  case SDL_KEY_DOWN:
1039  stream << "SDL key down";
1040  break;
1041  case SDL_TEXT_INPUT:
1042  stream << "SDL text input";
1043  break;
1044  case SDL_TEXT_EDITING:
1045  stream << "SDL text editing";
1046  break;
1047 
1048  case NOTIFY_REMOVAL:
1049  stream << "notify removal";
1050  break;
1051  case NOTIFY_MODIFIED:
1052  stream << "notify modified";
1053  break;
1055  stream << "receive keyboard focus";
1056  break;
1057  case LOSE_KEYBOARD_FOCUS:
1058  stream << "lose keyboard focus";
1059  break;
1060  case SHOW_TOOLTIP:
1061  stream << "show tooltip";
1062  break;
1063  case NOTIFY_REMOVE_TOOLTIP:
1064  stream << "notify remove tooltip";
1065  break;
1066  case SDL_ACTIVATE:
1067  stream << "SDL activate";
1068  break;
1069  case MESSAGE_SHOW_TOOLTIP:
1070  stream << "message show tooltip";
1071  break;
1072  case SHOW_HELPTIP:
1073  stream << "show helptip";
1074  break;
1075  case MESSAGE_SHOW_HELPTIP:
1076  stream << "message show helptip";
1077  break;
1078  case REQUEST_PLACEMENT:
1079  stream << "request placement";
1080  break;
1081  case SDL_TOUCH_MOTION:
1082  stream << "SDL touch motion";
1083  break;
1084  case SDL_TOUCH_UP:
1085  stream << "SDL touch up";
1086  break;
1087  case SDL_TOUCH_DOWN:
1088  stream << "SDL touch down";
1089  break;
1091  stream << "SDL multi-touch gesture";
1092  break;
1093  case SDL_RAW_EVENT:
1094  stream << "SDL raw event";
1095  break;
1096  }
1097 
1098  return stream;
1099 }
1100 
1101 } // namespace event
1102 
1103 std::vector<window*> open_window_stack {};
1104 
1106 {
1107  for(auto iter = open_window_stack.rbegin(); iter != open_window_stack.rend(); ++iter) {
1108  if(*iter == window) {
1109  open_window_stack.erase(std::next(iter).base());
1110  break;
1111  }
1112  }
1113 }
1114 
1116 {
1117  return !open_window_stack.empty();
1118 }
1119 
1120 } // namespace gui2
mouse_behavior get_mouse_behavior() const
Definition: dispatcher.hpp:833
Define the common log macros for the gui toolkit.
dispatcher * keyboard_focus_
Needed to determine which dispatcher gets the keyboard events.
Definition: handler.cpp:345
Request the widget to show its hover helptip.
Definition: handler.hpp:105
static std::unique_ptr< class sdl_event_handler > handler_
Definition: handler.cpp:61
An SDL text editing (IME) event.
Definition: handler.hpp:85
A left mouse button down event for a widget.
Definition: handler.hpp:60
void touch_multi_gesture(const point &center, float dTheta, float dDist, uint8_t numFingers)
Fires a touch gesture event.
Definition: handler.cpp:751
Widget loses keyboard focus.
Definition: handler.hpp:100
void video_resize(const point &new_size)
Fires a video resize event.
Definition: handler.cpp:613
An SDL wheel right event.
Definition: handler.hpp:80
bool hotkey_pressed(const hotkey::hotkey_ptr key)
Handles the pressing of a hotkey.
Definition: handler.cpp:820
Base class for event handling.
Definition: dispatcher.hpp:306
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:76
void activate()
Reinitializes the state of all dispatchers.
Definition: handler.cpp:584
An SDL left mouse button down event.
Definition: handler.hpp:58
Definition: video.hpp:31
void flip()
Renders the screen.
Definition: video.cpp:307
An SDL resize request, coordinate is the new window size.
Definition: handler.hpp:51
This file contains the window object, this object is a top level container which has the event manage...
An SDL key down event.
Definition: handler.hpp:83
auto reversed_view(T &container)
Definition: ranges.hpp:27
void handle_window_event(const SDL_Event &event) override
Inherited from events::sdl_handler.
Definition: handler.cpp:531
Base class for all widgets.
Definition: widget.hpp:49
void text_editing(const std::string &unicode, int32_t start, int32_t len)
Fires a text editing event.
Definition: handler.cpp:811
A mouse leave event for a widget.
Definition: handler.hpp:56
bool is_in_dialog()
Is a dialog open?
Definition: handler.cpp:1115
#define TIMER_EVENT
Definition: events.hpp:24
#define DRAW_EVENT
Definition: events.hpp:26
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:77
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:69
Type that can be thrown as an exception to quit to desktop.
Definition: video.hpp:245
void capture_mouse(dispatcher *dispatcher)
Captures the mouse.
Definition: handler.cpp:923
button(const implementation::builder_button &builder)
Definition: button.cpp:43
An SDL right mouse button down event.
Definition: handler.hpp:72
static CVideo & get_singleton()
Definition: video.hpp:48
virtual void draw()
Definition: events.hpp:80
See LEFT_BUTTON_DOWN.
Definition: handler.hpp:67
#define d
void button_down(const SDL_Event &event)
Handles a joystick button down event.
Definition: handler.cpp:771
Request to show a helptip based on the data sent.
Definition: handler.hpp:106
void hat_motion(const SDL_Event &event)
Handles a hat motion event.
Definition: handler.cpp:758
void key_down(const SDL_Event &event)
Fires a key down event.
Definition: handler.cpp:784
An SDL wheel down event.
Definition: handler.hpp:82
See LEFT_BUTTON_UP.
Definition: handler.hpp:75
Widget gains keyboard focus.
Definition: handler.hpp:99
void touch_motion(const point &position, const point &distance)
Fires a touch-moved event.
Definition: handler.cpp:730
Request the widget to show its hover tooltip.
Definition: handler.hpp:102
int x
x coordinate.
Definition: point.hpp:44
void init_mouse_location()
Initializes the location of the mouse.
Definition: handler.cpp:910
Generic file dialog.
Definition: field-fwd.hpp:22
Sent by a widget to notify others its contents or state are modified.
Definition: handler.hpp:88
#define CLOSE_WINDOW_EVENT
Definition: events.hpp:27
Request the widget to remove its hover tooltip.
Definition: handler.hpp:103
bool get_want_keyboard_input() const
Definition: dispatcher.hpp:843
Request to place the widget.
Definition: handler.hpp:94
static events::event_context * event_context
Definition: handler.cpp:62
const hotkey_ptr get_hotkey(const SDL_Event &event)
Iterate through the list of hotkeys and return a hotkey that matches the SDL_Event and the current ke...
virtual bool is_at(const point &coordinate) const =0
Determines whether the location is inside an active widget.
This singleton class handles all events.
Definition: handler.cpp:119
void close_window(const unsigned window_id)
Fires a CLOSE_WINDOW event for the window with the given ID.
Definition: handler.cpp:853
A left mouse button up event for a widget.
Definition: handler.hpp:61
void set_is_dirty(const bool is_dirty)
Definition: widget.cpp:465
Periodic redraw request.
Definition: handler.hpp:49
Sent by a widget to notify others it&#39;s being destroyed.
Definition: handler.hpp:87
std::vector< dispatcher * > & get_all_dispatchers()
Gets all event dispatchers in the Z order.
Definition: handler.cpp:904
friend void capture_keyboard(dispatcher *dispatcher)
Captures the keyboard.
Definition: handler.cpp:939
bool execute_hotkey(const hotkey::HOTKEY_COMMAND id)
Executes a hotkey.
Definition: dispatcher.cpp:146
void remove_from_window_stack(window *window)
Removes a entry from the open_window_stack list.
Definition: handler.cpp:1105
void disconnect_dispatcher(dispatcher *dispatcher)
Disconnects a dispatcher to the event handler.
Definition: handler.cpp:897
An SDL middle mouse button down event.
Definition: handler.hpp:65
sdl_handler(sdl_handler &&)=delete
virtual void join()
Definition: events.cpp:296
void connect_dispatcher(dispatcher *dispatcher)
Connects a dispatcher to the event handler.
Definition: handler.cpp:890
std::vector< dispatcher * > & get_dispatchers()
Returns all dispatchers in the Z order.
Definition: handler.cpp:151
void pump()
Definition: events.cpp:472
An SDL wheel up event.
Definition: handler.hpp:81
void mouse_button_up(const point &position, const uint8_t button)
Fires a mouse button up event.
Definition: handler.cpp:658
static window * window_instance(const unsigned handle)
Returns the instance of a window.
Definition: window.cpp:426
void mouse(const ui_event event, const point &position)
Fires a generic mouse event.
Definition: handler.cpp:632
#define DRAW_ALL_EVENT
Definition: events.hpp:29
An SDL middle mouse button up event.
Definition: handler.hpp:66
void mouse_wheel(const point &position, int scrollx, int scrolly)
Fires a mouse wheel event.
Definition: handler.cpp:700
#define DOUBLE_CLICK_EVENT
Definition: events.hpp:23
void mouse_button_down(const point &position, const uint8_t button)
Fires a mouse button down event.
Definition: handler.cpp:679
void text_input(const std::string &unicode)
Fires a text input event.
Definition: handler.cpp:800
#define DBG_GUI_E
Definition: log.hpp:34
An SDL wheel left event.
Definition: handler.hpp:79
#define SHOW_HELPTIP_EVENT
Definition: events.hpp:28
A mouse motion event for a widget.
Definition: handler.hpp:55
#define WRN_GUI_E
Definition: log.hpp:36
void disconnect(dispatcher *dispatcher)
Disconnects a dispatcher.
Definition: handler.cpp:549
A left mouse button double click event for a widget.
Definition: handler.hpp:63
A mouse enter event for a widget.
Definition: handler.hpp:54
std::ostream & operator<<(std::ostream &stream, const ui_event event)
Definition: handler.cpp:948
Contains the gui2 timer routines.
Holds a 2D point.
Definition: point.hpp:23
Request to show a tooltip based on the data sent.
Definition: handler.hpp:104
#define HOVER_REMOVE_POPUP_EVENT
Definition: events.hpp:25
void keyboard(const ui_event event)
Fires a keyboard event which has no parameters.
Definition: handler.cpp:844
std::shared_ptr< hotkey_base > hotkey_ptr
Definition: hotkey_item.hpp:31
The main application window is activated.
Definition: handler.hpp:48
void raw_event(const SDL_Event &event)
Fires a raw SDL event.
Definition: handler.cpp:623
Handling of system events.
Definition: manager.hpp:42
#define next(ls)
Definition: llex.cpp:32
An SDL left mouse button up event.
Definition: handler.hpp:59
point get_mouse_position()
Returns the current mouse position.
Definition: helper.cpp:117
void touch_up(const point &position)
Fires a touch "finger up" event.
Definition: handler.cpp:737
std::vector< dispatcher * > dispatchers_
The dispatchers.
Definition: handler.cpp:338
void handle_event(const SDL_Event &event) override
Inherited from events::sdl_handler.
Definition: handler.cpp:374
An SDL text input (commit) event.
Definition: handler.hpp:84
void connect(dispatcher *dispatcher)
Connects a dispatcher.
Definition: handler.cpp:536
void release_mouse(dispatcher *dispatcher)
Releases a captured mouse.
Definition: handler.cpp:930
Simple push button.
Definition: button.hpp:35
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:68
EXIT_STATUS start(const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Definition: editor_main.cpp:28
See LEFT_BUTTON_DOWN.
Definition: handler.hpp:74
virtual void leave()
Definition: events.cpp:341
A request to close the current window.
Definition: handler.hpp:50
dispatcher * keyboard_dispatcher()
Gets the dispatcher that wants to receive the keyboard input.
Definition: handler.cpp:715
SDL_Rect screen_area(bool as_pixels=true) const
Returns the current window renderer area, either in pixels or screen coordinates. ...
Definition: video.cpp:270
void touch_down(const point &position)
Fires a touch "finger down" event.
Definition: handler.cpp:744
An SDL right mouse button up event.
Definition: handler.hpp:73
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:70
int y
y coordinate.
Definition: point.hpp:47
base class of top level items, the only item which needs to store the final canvases to draw on...
Definition: window.hpp:64
A left mouse button click event for a widget.
Definition: handler.hpp:62
dispatcher * mouse_focus
The dispatcher that captured the mouse focus.
Definition: handler.cpp:154
See LEFT_BUTTON_UP.
Definition: handler.hpp:68
HOTKEY_COMMAND get_id(const std::string &command)
returns get_hotkey_command(command).id
bool execute_timer(const std::size_t id)
Executes a timer.
Definition: timer.cpp:200
ui_event
The event send to the dispatcher.
Definition: handler.hpp:47
std::vector< window * > open_window_stack
Keeps track of any open windows of any type (modal, non-modal, or tooltip) in the order in which they...
Definition: handler.cpp:1103
An SDL mouse motion event.
Definition: handler.hpp:53