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