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