The Battle for Wesnoth  1.15.7+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) override;
131 
132  /** Inherited from events::sdl_handler. */
133  void handle_window_event(const SDL_Event& event) override;
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() override;
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_t 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_t button = event.button.button;
383  CVideo& video = CVideo::get_singleton();
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()) {
602  }
603 }
604 
606 {
607  for(auto dispatcher : dispatchers_) {
608  dynamic_cast<widget&>(*dispatcher).set_is_dirty(true);
609  }
610 
611  draw();
612 }
613 
615 {
616  DBG_GUI_E << "Firing: " << SDL_VIDEO_RESIZE << ".\n";
617 
618  for(auto dispatcher : dispatchers_)
619  {
620  dispatcher->fire(SDL_VIDEO_RESIZE, dynamic_cast<widget&>(*dispatcher), new_size);
621  }
622 }
623 
624 void sdl_event_handler::raw_event(const SDL_Event& event) {
625  DBG_GUI_E << "Firing raw event\n";
626 
627  for(auto dispatcher : dispatchers_)
628  {
629  dispatcher->fire(SDL_RAW_EVENT, dynamic_cast<widget&>(*dispatcher), event);
630  }
631 }
632 
633 void sdl_event_handler::mouse(const ui_event event, const point& position)
634 {
635  DBG_GUI_E << "Firing: " << event << ".\n";
636 
637  if(mouse_focus) {
638  mouse_focus->fire(event, dynamic_cast<widget&>(*mouse_focus), position);
639  return;
640  }
641 
644  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher), position);
645  break;
646  }
647 
649  continue;
650  }
651 
652  if(dispatcher->is_at(position)) {
653  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher), position);
654  break;
655  }
656  }
657 }
658 
659 void sdl_event_handler::mouse_button_up(const point& position, const uint8_t button)
660 {
661  switch(button) {
662  case SDL_BUTTON_LEFT:
663  mouse(SDL_LEFT_BUTTON_UP, position);
664  break;
665  case SDL_BUTTON_MIDDLE:
666  mouse(SDL_MIDDLE_BUTTON_UP, position);
667  break;
668  case SDL_BUTTON_RIGHT:
669  mouse(SDL_RIGHT_BUTTON_UP, position);
670  break;
671  default:
672 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
673  WRN_GUI_E << "Unhandled 'mouse button up' event for button "
674  << static_cast<uint32_t>(button) << ".\n";
675 #endif
676  break;
677  }
678 }
679 
680 void sdl_event_handler::mouse_button_down(const point& position, const uint8_t button)
681 {
682  switch(button) {
683  case SDL_BUTTON_LEFT:
684  mouse(SDL_LEFT_BUTTON_DOWN, position);
685  break;
686  case SDL_BUTTON_MIDDLE:
687  mouse(SDL_MIDDLE_BUTTON_DOWN, position);
688  break;
689  case SDL_BUTTON_RIGHT:
690  mouse(SDL_RIGHT_BUTTON_DOWN, position);
691  break;
692  default:
693 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
694  WRN_GUI_E << "Unhandled 'mouse button down' event for button "
695  << static_cast<uint32_t>(button) << ".\n";
696 #endif
697  break;
698  }
699 }
700 
701 void sdl_event_handler::mouse_wheel(const point& position, int x, int y)
702 {
703  if(x > 0) {
704  mouse(SDL_WHEEL_RIGHT, position);
705  } else if(x < 0) {
706  mouse(SDL_WHEEL_LEFT, position);
707  }
708 
709  if(y < 0) {
710  mouse(SDL_WHEEL_DOWN, position);
711  } else if(y > 0) {
712  mouse(SDL_WHEEL_UP, position);
713  }
714 }
715 
717 {
718  if(keyboard_focus_) {
719  return keyboard_focus_;
720  }
721 
724  return dispatcher;
725  }
726  }
727 
728  return nullptr;
729 }
730 
731 void sdl_event_handler::touch_motion(const point& position, const point& distance)
732 {
734  dispatcher->fire(SDL_TOUCH_MOTION , dynamic_cast<widget&>(*dispatcher), position, distance);
735  }
736 }
737 
738 void sdl_event_handler::touch_up(const point& position)
739 {
741  dispatcher->fire(SDL_TOUCH_UP, dynamic_cast<widget&>(*dispatcher), position);
742  }
743 }
744 
746 {
748  dispatcher->fire(SDL_TOUCH_DOWN, dynamic_cast<widget&>(*dispatcher), position);
749  }
750 }
751 
752 void sdl_event_handler::touch_multi_gesture(const point& center, float dTheta, float dDist, uint8_t numFingers)
753 {
755  dispatcher->fire(SDL_TOUCH_MULTI_GESTURE, dynamic_cast<widget&>(*dispatcher), center, dTheta, dDist, numFingers);
756  }
757 }
758 
759 void sdl_event_handler::hat_motion(const SDL_Event& event)
760 {
761  const hotkey::hotkey_ptr& hk = hotkey::get_hotkey(event);
762  bool done = false;
763  if(!hk->null()) {
764  done = hotkey_pressed(hk);
765  }
766  if(!done) {
767  // TODO fendrin think about handling hat motions that are not bound to a
768  // hotkey.
769  }
770 }
771 
772 void sdl_event_handler::button_down(const SDL_Event& event)
773 {
774  const hotkey::hotkey_ptr hk = hotkey::get_hotkey(event);
775  bool done = false;
776  if(!hk->null()) {
777  done = hotkey_pressed(hk);
778  }
779  if(!done) {
780  // TODO fendrin think about handling button down events that are not
781  // bound to a hotkey.
782  }
783 }
784 
785 void sdl_event_handler::key_down(const SDL_Event& event)
786 {
787  const hotkey::hotkey_ptr hk = hotkey::get_hotkey(event);
788  bool done = false;
789  if(!hk->null()) {
790  done = hotkey_pressed(hk);
791  }
792  if(!done) {
793  if(event.type == SDL_TEXTINPUT) {
794  text_input(event.text.text);
795  } else {
796  key_down(event.key.keysym.sym, static_cast<SDL_Keymod>(event.key.keysym.mod), "");
797  }
798  }
799 }
800 
802 {
803  key_down(SDLK_UNKNOWN, static_cast<SDL_Keymod>(0), unicode);
804 
807  dynamic_cast<widget&>(*dispatcher),
808  unicode, -1, -1);
809  }
810 }
811 
812 void sdl_event_handler::text_editing(const std::string& unicode, int32_t start, int32_t len)
813 {
816  dynamic_cast<widget&>(*dispatcher),
817  unicode, start, len);
818  }
819 }
820 
822 {
824  return dispatcher->execute_hotkey(hotkey::get_id(key->get_command()));
825  }
826 
827  return false;
828 }
829 
830 void sdl_event_handler::key_down(const SDL_Keycode key,
831  const SDL_Keymod modifier,
832  const std::string& unicode)
833 {
834  DBG_GUI_E << "Firing: " << SDL_KEY_DOWN << ".\n";
835 
837  dispatcher->fire(SDL_KEY_DOWN,
838  dynamic_cast<widget&>(*dispatcher),
839  key,
840  modifier,
841  unicode);
842  }
843 }
844 
846 {
847  DBG_GUI_E << "Firing: " << event << ".\n";
848 
850  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher));
851  }
852 }
853 
854 void sdl_event_handler::close_window(const unsigned window_id)
855 {
856  DBG_GUI_E << "Firing " << CLOSE_WINDOW << ".\n";
857 
858  window* window = window::window_instance(window_id);
859  if(window) {
860  window->fire(CLOSE_WINDOW, *window);
861  }
862 }
863 
864 /***** manager class. *****/
865 
867 {
868  handler_.reset(new sdl_event_handler());
869 
870 #ifdef MAIN_EVENT_HANDLER
871  draw_interval = 30;
872  SDL_AddTimer(draw_interval, timer_sdl_draw_event, nullptr);
873 
874  event_poll_interval = 10;
875  SDL_AddTimer(event_poll_interval, timer_sdl_poll_events, nullptr);
876 #endif
877 }
878 
880 {
881  handler_.reset(nullptr);
882 
883 #ifdef MAIN_EVENT_HANDLER
884  draw_interval = 0;
885  event_poll_interval = 0;
886 #endif
887 }
888 
889 /***** free functions class. *****/
890 
892 {
893  assert(handler_);
894  assert(dispatcher);
895  handler_->connect(dispatcher);
896 }
897 
899 {
900  assert(handler_);
901  assert(dispatcher);
902  handler_->disconnect(dispatcher);
903 }
904 
905 std::vector<dispatcher*>& get_all_dispatchers()
906 {
907  assert(handler_);
908  return handler_->get_dispatchers();
909 }
910 
912 {
914 
915  SDL_Event event{};
916  event.type = SDL_MOUSEMOTION;
917  event.motion.type = SDL_MOUSEMOTION;
918  event.motion.x = mouse.x;
919  event.motion.y = mouse.y;
920 
921  SDL_PushEvent(&event);
922 }
923 
925 {
926  assert(handler_);
927  assert(dispatcher);
928  handler_->mouse_focus = dispatcher;
929 }
930 
932 {
933  assert(handler_);
934  assert(dispatcher);
935  if(handler_->mouse_focus == dispatcher) {
936  handler_->mouse_focus = nullptr;
937  }
938 }
939 
941 {
942  assert(handler_);
943  assert(dispatcher);
944  assert(dispatcher->get_want_keyboard_input());
945 
946  handler_->keyboard_focus_ = dispatcher;
947 }
948 
949 std::ostream& operator<<(std::ostream& stream, const ui_event event)
950 {
951  switch(event) {
952  case DRAW:
953  stream << "draw";
954  break;
955  case CLOSE_WINDOW:
956  stream << "close window";
957  break;
958  case SDL_VIDEO_RESIZE:
959  stream << "SDL video resize";
960  break;
961  case SDL_MOUSE_MOTION:
962  stream << "SDL mouse motion";
963  break;
964  case MOUSE_ENTER:
965  stream << "mouse enter";
966  break;
967  case MOUSE_LEAVE:
968  stream << "mouse leave";
969  break;
970  case MOUSE_MOTION:
971  stream << "mouse motion";
972  break;
974  stream << "SDL left button down";
975  break;
976  case SDL_LEFT_BUTTON_UP:
977  stream << "SDL left button up";
978  break;
979  case LEFT_BUTTON_DOWN:
980  stream << "left button down";
981  break;
982  case LEFT_BUTTON_UP:
983  stream << "left button up";
984  break;
985  case LEFT_BUTTON_CLICK:
986  stream << "left button click";
987  break;
989  stream << "left button double click";
990  break;
992  stream << "SDL middle button down";
993  break;
995  stream << "SDL middle button up";
996  break;
997  case MIDDLE_BUTTON_DOWN:
998  stream << "middle button down";
999  break;
1000  case MIDDLE_BUTTON_UP:
1001  stream << "middle button up";
1002  break;
1003  case MIDDLE_BUTTON_CLICK:
1004  stream << "middle button click";
1005  break;
1007  stream << "middle button double click";
1008  break;
1009  case SDL_RIGHT_BUTTON_DOWN:
1010  stream << "SDL right button down";
1011  break;
1012  case SDL_RIGHT_BUTTON_UP:
1013  stream << "SDL right button up";
1014  break;
1015  case RIGHT_BUTTON_DOWN:
1016  stream << "right button down";
1017  break;
1018  case RIGHT_BUTTON_UP:
1019  stream << "right button up";
1020  break;
1021  case RIGHT_BUTTON_CLICK:
1022  stream << "right button click";
1023  break;
1025  stream << "right button double click";
1026  break;
1027  case SDL_WHEEL_LEFT:
1028  stream << "SDL wheel left";
1029  break;
1030  case SDL_WHEEL_RIGHT:
1031  stream << "SDL wheel right";
1032  break;
1033  case SDL_WHEEL_UP:
1034  stream << "SDL wheel up";
1035  break;
1036  case SDL_WHEEL_DOWN:
1037  stream << "SDL wheel down";
1038  break;
1039  case SDL_KEY_DOWN:
1040  stream << "SDL key down";
1041  break;
1042  case SDL_TEXT_INPUT:
1043  stream << "SDL text input";
1044  break;
1045  case SDL_TEXT_EDITING:
1046  stream << "SDL text editing";
1047  break;
1048 
1049  case NOTIFY_REMOVAL:
1050  stream << "notify removal";
1051  break;
1052  case NOTIFY_MODIFIED:
1053  stream << "notify modified";
1054  break;
1056  stream << "receive keyboard focus";
1057  break;
1058  case LOSE_KEYBOARD_FOCUS:
1059  stream << "lose keyboard focus";
1060  break;
1061  case SHOW_TOOLTIP:
1062  stream << "show tooltip";
1063  break;
1064  case NOTIFY_REMOVE_TOOLTIP:
1065  stream << "notify remove tooltip";
1066  break;
1067  case SDL_ACTIVATE:
1068  stream << "SDL activate";
1069  break;
1070  case MESSAGE_SHOW_TOOLTIP:
1071  stream << "message show tooltip";
1072  break;
1073  case SHOW_HELPTIP:
1074  stream << "show helptip";
1075  break;
1076  case MESSAGE_SHOW_HELPTIP:
1077  stream << "message show helptip";
1078  break;
1079  case REQUEST_PLACEMENT:
1080  stream << "request placement";
1081  break;
1082  case SDL_TOUCH_MOTION:
1083  stream << "SDL touch motion";
1084  break;
1085  case SDL_TOUCH_UP:
1086  stream << "SDL touch up";
1087  break;
1088  case SDL_TOUCH_DOWN:
1089  stream << "SDL touch down";
1090  break;
1092  stream << "SDL multi-touch gesture";
1093  break;
1094  case SDL_RAW_EVENT:
1095  stream << "SDL raw event";
1096  break;
1097  }
1098 
1099  return stream;
1100 }
1101 
1102 } // namespace event
1103 
1104 std::vector<window*> open_window_stack {};
1105 
1107 {
1108  for(auto iter = open_window_stack.rbegin(); iter != open_window_stack.rend(); ++iter) {
1109  if(*iter == window) {
1110  open_window_stack.erase(std::next(iter).base());
1111  break;
1112  }
1113  }
1114 }
1115 
1117 {
1118  return !open_window_stack.empty();
1119 }
1120 
1121 } // 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:346
Request the widget to show its hover helptip.
Definition: handler.hpp:105
static std::unique_ptr< class sdl_event_handler > handler_
Definition: handler.cpp:62
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:752
Widget loses keyboard focus.
Definition: handler.hpp:100
void video_resize(const point &new_size)
Fires a video resize event.
Definition: handler.cpp:614
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:821
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:585
An SDL left mouse button down event.
Definition: handler.hpp:58
Definition: video.hpp:31
void flip()
Renders the screen.
Definition: video.cpp:329
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
void handle_window_event(const SDL_Event &event) override
Inherited from events::sdl_handler.
Definition: handler.cpp:532
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:812
A mouse leave event for a widget.
Definition: handler.hpp:56
bool is_in_dialog()
Is a dialog open?
Definition: handler.cpp:1116
#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:924
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:772
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:759
void key_down(const SDL_Event &event)
Fires a key down event.
Definition: handler.cpp:785
-file util.hpp
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:731
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:911
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
size_t len
Definition: result_set.cpp:277
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: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:854
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:905
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:1106
void disconnect_dispatcher(dispatcher *dispatcher)
Disconnects a dispatcher to the event handler.
Definition: handler.cpp:898
An SDL middle mouse button down event.
Definition: handler.hpp:65
sdl_handler(sdl_handler &&)=delete
virtual void join()
Definition: events.cpp:299
void connect_dispatcher(dispatcher *dispatcher)
Connects a dispatcher to the event handler.
Definition: handler.cpp:891
std::vector< dispatcher * > & get_dispatchers()
Returns all dispatchers in the Z order.
Definition: handler.cpp:152
void pump()
Definition: events.cpp:475
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:659
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:633
#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:701
#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:680
void text_input(const std::string &unicode)
Fires a text input event.
Definition: handler.cpp:801
#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:550
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:949
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:845
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:624
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:738
std::vector< dispatcher * > dispatchers_
The dispatchers.
Definition: handler.cpp:339
friend void capture_keyboard(dispatcher *)
Captures the keyboard.
Definition: handler.cpp:940
void handle_event(const SDL_Event &event) override
Inherited from events::sdl_handler.
Definition: handler.cpp:375
An SDL text input (commit) event.
Definition: handler.hpp:84
void connect(dispatcher *dispatcher)
Connects a dispatcher.
Definition: handler.cpp:537
void release_mouse(dispatcher *dispatcher)
Releases a captured mouse.
Definition: handler.cpp:931
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
static void reverse(lua_State *L, StkId from, StkId to)
Definition: lapi.cpp:193
virtual void leave()
Definition: events.cpp:344
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:716
SDL_Rect screen_area(bool as_pixels=true) const
Returns the current window renderer area, either in pixels or screen coordinates. ...
Definition: video.cpp:291
void touch_down(const point &position)
Fires a touch "finger down" event.
Definition: handler.cpp:745
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:62
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:155
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:1104
An SDL mouse motion event.
Definition: handler.hpp:53