The Battle for Wesnoth  1.19.5+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;
62 static std::unique_ptr<events::event_context> event_context = 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";
535  event_context = std::make_unique<events::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  event_context = nullptr;
571  }
572 }
573 
575 {
576  for(auto dispatcher : dispatchers_)
577  {
578  dispatcher->fire(SDL_ACTIVATE, dynamic_cast<widget&>(*dispatcher), nullptr);
579  }
580 }
581 
583 {
584  DBG_GUI_E << "Firing: " << SDL_VIDEO_RESIZE << ".";
585 
586  for(auto dispatcher : dispatchers_)
587  {
588  dispatcher->fire(SDL_VIDEO_RESIZE, dynamic_cast<widget&>(*dispatcher), new_size);
589  }
590 }
591 
592 void sdl_event_handler::raw_event(const SDL_Event& event) {
593  DBG_GUI_E << "Firing raw event";
594 
595  for(auto dispatcher : dispatchers_)
596  {
597  dispatcher->fire(SDL_RAW_EVENT, dynamic_cast<widget&>(*dispatcher), event);
598  }
599 }
600 
601 void sdl_event_handler::mouse(const ui_event event, const point& position)
602 {
603  DBG_GUI_E << "Firing: " << event << ".";
604 
605  if(mouse_focus) {
606  mouse_focus->fire(event, dynamic_cast<widget&>(*mouse_focus), position);
607  return;
608  }
609 
612  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher), position);
613  break;
614  }
615 
617  continue;
618  }
619 
620  if(dispatcher->is_at(position)) {
621  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher), position);
622  break;
623  }
624  }
625 }
626 
627 void sdl_event_handler::mouse_button_up(const point& position, const uint8_t button)
628 {
629  switch(button) {
630  case SDL_BUTTON_LEFT:
631  mouse(SDL_LEFT_BUTTON_UP, position);
632  break;
633  case SDL_BUTTON_MIDDLE:
634  mouse(SDL_MIDDLE_BUTTON_UP, position);
635  break;
636  case SDL_BUTTON_RIGHT:
637  mouse(SDL_RIGHT_BUTTON_UP, position);
638  break;
639  default:
640 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
641  WRN_GUI_E << "Unhandled 'mouse button up' event for button "
642  << static_cast<uint32_t>(button) << ".";
643 #endif
644  break;
645  }
646 }
647 
648 void sdl_event_handler::mouse_button_down(const point& position, const uint8_t button)
649 {
650  switch(button) {
651  case SDL_BUTTON_LEFT:
652  mouse(SDL_LEFT_BUTTON_DOWN, position);
653  break;
654  case SDL_BUTTON_MIDDLE:
655  mouse(SDL_MIDDLE_BUTTON_DOWN, position);
656  break;
657  case SDL_BUTTON_RIGHT:
658  mouse(SDL_RIGHT_BUTTON_DOWN, position);
659  break;
660  default:
661 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
662  WRN_GUI_E << "Unhandled 'mouse button down' event for button "
663  << static_cast<uint32_t>(button) << ".";
664 #endif
665  break;
666  }
667 }
668 
669 void sdl_event_handler::mouse_wheel(const point& position, int x, int y)
670 {
671  if(x > 0) {
672  mouse(SDL_WHEEL_RIGHT, position);
673  } else if(x < 0) {
674  mouse(SDL_WHEEL_LEFT, position);
675  }
676 
677  if(y < 0) {
678  mouse(SDL_WHEEL_DOWN, position);
679  } else if(y > 0) {
680  mouse(SDL_WHEEL_UP, position);
681  }
682 }
683 
685 {
686  if(keyboard_focus_) {
687  return keyboard_focus_;
688  }
689 
692  return dispatcher;
693  }
694  }
695 
696  return nullptr;
697 }
698 
699 void sdl_event_handler::touch_motion(const point& position, const point& distance)
700 {
702  dispatcher->fire(SDL_TOUCH_MOTION , dynamic_cast<widget&>(*dispatcher), position, distance);
703  }
704 }
705 
706 void sdl_event_handler::touch_up(const point& position)
707 {
709  dispatcher->fire(SDL_TOUCH_UP, dynamic_cast<widget&>(*dispatcher), position);
710  }
711 }
712 
714 {
716  dispatcher->fire(SDL_TOUCH_DOWN, dynamic_cast<widget&>(*dispatcher), position);
717  }
718 }
719 
720 void sdl_event_handler::touch_multi_gesture(const point& center, float dTheta, float dDist, uint8_t numFingers)
721 {
723  dispatcher->fire(SDL_TOUCH_MULTI_GESTURE, dynamic_cast<widget&>(*dispatcher), center, dTheta, dDist, numFingers);
724  }
725 }
726 
727 void sdl_event_handler::hat_motion(const SDL_Event& event)
728 {
729  const hotkey::hotkey_ptr& hk = hotkey::get_hotkey(event);
730  bool done = false;
731  if(!hk->null()) {
732  done = hotkey_pressed(hk);
733  }
734  if(!done) {
735  // TODO fendrin think about handling hat motions that are not bound to a
736  // hotkey.
737  }
738 }
739 
740 void sdl_event_handler::button_down(const SDL_Event& event)
741 {
742  const hotkey::hotkey_ptr hk = hotkey::get_hotkey(event);
743  bool done = false;
744  if(!hk->null()) {
745  done = hotkey_pressed(hk);
746  }
747  if(!done) {
748  // TODO fendrin think about handling button down events that are not
749  // bound to a hotkey.
750  }
751 }
752 
753 void sdl_event_handler::key_down(const SDL_Event& event)
754 {
755  const hotkey::hotkey_ptr hk = hotkey::get_hotkey(event);
756  bool done = false;
757  if(!hk->null()) {
758  done = hotkey_pressed(hk);
759  }
760  if(!done) {
761  if(event.type == SDL_TEXTINPUT) {
762  text_input(event.text.text);
763  } else {
764  key_down(event.key.keysym.sym, static_cast<SDL_Keymod>(event.key.keysym.mod), "");
765  }
766  }
767 }
768 
769 void sdl_event_handler::text_input(const std::string& unicode)
770 {
771  key_down(SDLK_UNKNOWN, static_cast<SDL_Keymod>(0), unicode);
772 
775  dynamic_cast<widget&>(*dispatcher),
776  unicode, -1, -1);
777  }
778 }
779 
780 void sdl_event_handler::text_editing(const std::string& unicode, int32_t start, int32_t len)
781 {
784  dynamic_cast<widget&>(*dispatcher),
785  unicode, start, len);
786  }
787 }
788 
790 {
792  return dispatcher->execute_hotkey(hotkey::get_hotkey_command(key->get_command()).command);
793  }
794 
795  return false;
796 }
797 
798 void sdl_event_handler::key_down(const SDL_Keycode key,
799  const SDL_Keymod modifier,
800  const std::string& unicode)
801 {
802  DBG_GUI_E << "Firing: " << SDL_KEY_DOWN << ".";
803 
806  dynamic_cast<widget&>(*dispatcher),
807  key,
808  modifier,
809  unicode);
810  }
811 }
812 
814 {
815  DBG_GUI_E << "Firing: " << event << ".";
816 
818  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher));
819  }
820 }
821 
822 void sdl_event_handler::close_window(const unsigned window_id)
823 {
824  DBG_GUI_E << "Firing " << CLOSE_WINDOW << ".";
825 
826  window* window = window::window_instance(window_id);
827  if(window) {
829  }
830 }
831 
832 /***** manager class. *****/
833 
835 {
836  handler_.reset(new sdl_event_handler());
837 
838 #ifdef MAIN_EVENT_HANDLER
839  draw_interval = 30;
840  SDL_AddTimer(draw_interval, timer_sdl_draw_event, nullptr);
841 
842  event_poll_interval = 10;
843  SDL_AddTimer(event_poll_interval, timer_sdl_poll_events, nullptr);
844 #endif
845 }
846 
848 {
849  handler_.reset(nullptr);
850 
851 #ifdef MAIN_EVENT_HANDLER
852  draw_interval = 0;
853  event_poll_interval = 0;
854 #endif
855 }
856 
857 /***** free functions class. *****/
858 
860 {
861  assert(handler_);
862  assert(dispatcher);
863  handler_->connect(dispatcher);
864 }
865 
867 {
868  assert(handler_);
869  assert(dispatcher);
870  handler_->disconnect(dispatcher);
871 }
872 
873 std::vector<dispatcher*>& get_all_dispatchers()
874 {
875  assert(handler_);
876  return handler_->get_dispatchers();
877 }
878 
880 {
882 
883  SDL_Event event{};
884  event.type = SDL_MOUSEMOTION;
885  event.motion.type = SDL_MOUSEMOTION;
886  event.motion.x = mouse.x;
887  event.motion.y = mouse.y;
888 
889  SDL_PushEvent(&event);
890 }
891 
893 {
894  assert(handler_);
895  assert(dispatcher);
896  handler_->mouse_focus = dispatcher;
897 }
898 
900 {
901  assert(handler_);
902  assert(dispatcher);
903  if(handler_->mouse_focus == dispatcher) {
904  handler_->mouse_focus = nullptr;
905  }
906 }
907 
909 {
910  assert(handler_);
911  assert(dispatcher);
913 
914  handler_->keyboard_focus_ = dispatcher;
915 }
916 
917 std::ostream& operator<<(std::ostream& stream, const ui_event event)
918 {
919  switch(event) {
920  case DRAW:
921  stream << "draw";
922  break;
923  case CLOSE_WINDOW:
924  stream << "close window";
925  break;
926  case SDL_VIDEO_RESIZE:
927  stream << "SDL video resize";
928  break;
929  case SDL_MOUSE_MOTION:
930  stream << "SDL mouse motion";
931  break;
932  case MOUSE_ENTER:
933  stream << "mouse enter";
934  break;
935  case MOUSE_LEAVE:
936  stream << "mouse leave";
937  break;
938  case MOUSE_MOTION:
939  stream << "mouse motion";
940  break;
942  stream << "SDL left button down";
943  break;
944  case SDL_LEFT_BUTTON_UP:
945  stream << "SDL left button up";
946  break;
947  case LEFT_BUTTON_DOWN:
948  stream << "left button down";
949  break;
950  case LEFT_BUTTON_UP:
951  stream << "left button up";
952  break;
953  case LEFT_BUTTON_CLICK:
954  stream << "left button click";
955  break;
957  stream << "left button double click";
958  break;
960  stream << "SDL middle button down";
961  break;
963  stream << "SDL middle button up";
964  break;
965  case MIDDLE_BUTTON_DOWN:
966  stream << "middle button down";
967  break;
968  case MIDDLE_BUTTON_UP:
969  stream << "middle button up";
970  break;
971  case MIDDLE_BUTTON_CLICK:
972  stream << "middle button click";
973  break;
975  stream << "middle button double click";
976  break;
978  stream << "SDL right button down";
979  break;
980  case SDL_RIGHT_BUTTON_UP:
981  stream << "SDL right button up";
982  break;
983  case RIGHT_BUTTON_DOWN:
984  stream << "right button down";
985  break;
986  case RIGHT_BUTTON_UP:
987  stream << "right button up";
988  break;
989  case RIGHT_BUTTON_CLICK:
990  stream << "right button click";
991  break;
993  stream << "right button double click";
994  break;
995  case SDL_WHEEL_LEFT:
996  stream << "SDL wheel left";
997  break;
998  case SDL_WHEEL_RIGHT:
999  stream << "SDL wheel right";
1000  break;
1001  case SDL_WHEEL_UP:
1002  stream << "SDL wheel up";
1003  break;
1004  case SDL_WHEEL_DOWN:
1005  stream << "SDL wheel down";
1006  break;
1007  case SDL_KEY_DOWN:
1008  stream << "SDL key down";
1009  break;
1010  case SDL_TEXT_INPUT:
1011  stream << "SDL text input";
1012  break;
1013  case SDL_TEXT_EDITING:
1014  stream << "SDL text editing";
1015  break;
1016 
1017  case NOTIFY_REMOVAL:
1018  stream << "notify removal";
1019  break;
1020  case NOTIFY_MODIFIED:
1021  stream << "notify modified";
1022  break;
1024  stream << "receive keyboard focus";
1025  break;
1026  case LOSE_KEYBOARD_FOCUS:
1027  stream << "lose keyboard focus";
1028  break;
1029  case SHOW_TOOLTIP:
1030  stream << "show tooltip";
1031  break;
1032  case NOTIFY_REMOVE_TOOLTIP:
1033  stream << "notify remove tooltip";
1034  break;
1035  case SDL_ACTIVATE:
1036  stream << "SDL activate";
1037  break;
1038  case MESSAGE_SHOW_TOOLTIP:
1039  stream << "message show tooltip";
1040  break;
1041  case SHOW_HELPTIP:
1042  stream << "show helptip";
1043  break;
1044  case MESSAGE_SHOW_HELPTIP:
1045  stream << "message show helptip";
1046  break;
1047  case REQUEST_PLACEMENT:
1048  stream << "request placement";
1049  break;
1050  case SDL_TOUCH_MOTION:
1051  stream << "SDL touch motion";
1052  break;
1053  case SDL_TOUCH_UP:
1054  stream << "SDL touch up";
1055  break;
1056  case SDL_TOUCH_DOWN:
1057  stream << "SDL touch down";
1058  break;
1060  stream << "SDL multi-touch gesture";
1061  break;
1062  case SDL_RAW_EVENT:
1063  stream << "SDL raw event";
1064  break;
1065  }
1066 
1067  return stream;
1068 }
1069 
1070 } // namespace event
1071 
1072 std::vector<window*> open_window_stack {};
1073 
1075 {
1076  for(auto iter = open_window_stack.rbegin(); iter != open_window_stack.rend(); ++iter) {
1077  if(*iter == window) {
1078  open_window_stack.erase(std::next(iter).base());
1079  break;
1080  }
1081  }
1082 }
1083 
1085 {
1086  return !open_window_stack.empty();
1087 }
1088 
1089 } // namespace gui2
virtual void join()
Definition: events.cpp:308
virtual void leave()
Definition: events.cpp:353
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:713
void keyboard(const ui_event event)
Fires a keyboard event which has no parameters.
Definition: handler.cpp:813
void activate()
Reinitializes the state of all dispatchers.
Definition: handler.cpp:574
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:627
void close_window(const unsigned window_id)
Fires a CLOSE_WINDOW event for the window with the given ID.
Definition: handler.cpp:822
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:582
void text_editing(const std::string &unicode, int32_t start, int32_t len)
Fires a text editing event.
Definition: handler.cpp:780
void touch_up(const point &position)
Fires a touch "finger up" event.
Definition: handler.cpp:706
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:684
friend void capture_keyboard(dispatcher *dispatcher)
Captures the keyboard.
Definition: handler.cpp:908
void text_input(const std::string &unicode)
Fires a text input event.
Definition: handler.cpp:769
void touch_motion(const point &position, const point &distance)
Fires a touch-moved event.
Definition: handler.cpp:699
void mouse_button_down(const point &position, const uint8_t button)
Fires a mouse button down event.
Definition: handler.cpp:648
void hat_motion(const SDL_Event &event)
Handles a hat motion event.
Definition: handler.cpp:727
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:753
void mouse(const ui_event event, const point &position)
Fires a generic mouse event.
Definition: handler.cpp:601
void touch_multi_gesture(const point &center, float dTheta, float dDist, uint8_t numFingers)
Fires a touch gesture event.
Definition: handler.cpp:720
bool hotkey_pressed(const hotkey::hotkey_ptr key)
Handles the pressing of a hotkey.
Definition: handler.cpp:789
void mouse_wheel(const point &position, int scrollx, int scrolly)
Fires a mouse wheel event.
Definition: handler.cpp:669
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:740
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:592
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:55
base class of top level items, the only item which needs to store the final canvases to draw on.
Definition: window.hpp:61
static window * window_instance(const unsigned handle)
Returns the instance of a window.
Definition: window.cpp:414
Type that can be thrown as an exception to quit to desktop.
Definition: video.hpp:320
#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:479
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
void capture_mouse(dispatcher *dispatcher)
Captures the mouse.
Definition: handler.cpp:892
void release_mouse(dispatcher *dispatcher)
Releases a captured mouse.
Definition: handler.cpp:899
void disconnect_dispatcher(dispatcher *dispatcher)
Disconnects a dispatcher to the event handler.
Definition: handler.cpp:866
static std::unique_ptr< class sdl_event_handler > handler_
Definition: handler.cpp:61
void capture_keyboard(dispatcher *dispatcher)
Captures the keyboard.
Definition: handler.cpp:908
@ mouse
Callbacks with a coordinate as extra parameter.
void connect_dispatcher(dispatcher *dispatcher)
Connects a dispatcher to the event handler.
Definition: handler.cpp:859
std::vector< dispatcher * > & get_all_dispatchers()
Gets all event dispatchers in the Z order.
Definition: handler.cpp:873
std::ostream & operator<<(std::ostream &stream, const ui_event event)
Definition: handler.cpp:917
static std::unique_ptr< events::event_context > event_context
Definition: handler.cpp:62
void init_mouse_location()
Initializes the location of the mouse.
Definition: handler.cpp:879
Generic file dialog.
bool is_in_dialog()
Is a dialog open?
Definition: handler.cpp:1084
void remove_from_window_stack(window *window)
Removes a entry from the open_window_stack list.
Definition: handler.cpp:1074
point get_mouse_position()
Returns the current mouse position.
Definition: helper.cpp:143
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:1072
bool execute_timer(const std::size_t id)
Executes a timer.
Definition: timer.cpp:197
const hotkey_command & get_hotkey_command(const std::string &command)
returns the hotkey_command with the given name
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...
auto reversed_view(T &container)
Definition: ranges.hpp:26
point game_canvas_size()
The size of the game canvas, in drawing coordinates / game pixels.
Definition: video.cpp:432
std::string_view data
Definition: picture.cpp:178
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.