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