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