The Battle for Wesnoth  1.17.6+dev
handler.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2022
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  */
149  void disconnect(dispatcher* dispatcher);
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. */
157  dispatcher* 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  */
221  dispatcher* keyboard_dispatcher();
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  */
343  dispatcher* keyboard_focus_;
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  case SDL_WINDOWEVENT_RESIZED:
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 = new 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  delete event_context;
571  event_context = nullptr;
572  }
573 }
574 
576 {
577  for(auto dispatcher : dispatchers_)
578  {
579  dispatcher->fire(SDL_ACTIVATE, dynamic_cast<widget&>(*dispatcher), nullptr);
580  }
581 }
582 
584 {
585  DBG_GUI_E << "Firing: " << SDL_VIDEO_RESIZE << ".";
586 
587  for(auto dispatcher : dispatchers_)
588  {
589  dispatcher->fire(SDL_VIDEO_RESIZE, dynamic_cast<widget&>(*dispatcher), new_size);
590  }
591 }
592 
593 void sdl_event_handler::raw_event(const SDL_Event& event) {
594  DBG_GUI_E << "Firing raw event";
595 
596  for(auto dispatcher : dispatchers_)
597  {
598  dispatcher->fire(SDL_RAW_EVENT, dynamic_cast<widget&>(*dispatcher), event);
599  }
600 }
601 
602 void sdl_event_handler::mouse(const ui_event event, const point& position)
603 {
604  DBG_GUI_E << "Firing: " << event << ".";
605 
606  if(mouse_focus) {
607  mouse_focus->fire(event, dynamic_cast<widget&>(*mouse_focus), position);
608  return;
609  }
610 
613  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher), position);
614  break;
615  }
616 
618  continue;
619  }
620 
621  if(dispatcher->is_at(position)) {
622  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher), position);
623  break;
624  }
625  }
626 }
627 
628 void sdl_event_handler::mouse_button_up(const point& position, const uint8_t button)
629 {
630  switch(button) {
631  case SDL_BUTTON_LEFT:
632  mouse(SDL_LEFT_BUTTON_UP, position);
633  break;
634  case SDL_BUTTON_MIDDLE:
635  mouse(SDL_MIDDLE_BUTTON_UP, position);
636  break;
637  case SDL_BUTTON_RIGHT:
638  mouse(SDL_RIGHT_BUTTON_UP, position);
639  break;
640  default:
641 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
642  WRN_GUI_E << "Unhandled 'mouse button up' event for button "
643  << static_cast<uint32_t>(button) << ".";
644 #endif
645  break;
646  }
647 }
648 
649 void sdl_event_handler::mouse_button_down(const point& position, const uint8_t button)
650 {
651  switch(button) {
652  case SDL_BUTTON_LEFT:
653  mouse(SDL_LEFT_BUTTON_DOWN, position);
654  break;
655  case SDL_BUTTON_MIDDLE:
656  mouse(SDL_MIDDLE_BUTTON_DOWN, position);
657  break;
658  case SDL_BUTTON_RIGHT:
659  mouse(SDL_RIGHT_BUTTON_DOWN, position);
660  break;
661  default:
662 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
663  WRN_GUI_E << "Unhandled 'mouse button down' event for button "
664  << static_cast<uint32_t>(button) << ".";
665 #endif
666  break;
667  }
668 }
669 
670 void sdl_event_handler::mouse_wheel(const point& position, int x, int y)
671 {
672  if(x > 0) {
673  mouse(SDL_WHEEL_RIGHT, position);
674  } else if(x < 0) {
675  mouse(SDL_WHEEL_LEFT, position);
676  }
677 
678  if(y < 0) {
679  mouse(SDL_WHEEL_DOWN, position);
680  } else if(y > 0) {
681  mouse(SDL_WHEEL_UP, position);
682  }
683 }
684 
686 {
687  if(keyboard_focus_) {
688  return keyboard_focus_;
689  }
690 
693  return dispatcher;
694  }
695  }
696 
697  return nullptr;
698 }
699 
700 void sdl_event_handler::touch_motion(const point& position, const point& distance)
701 {
703  dispatcher->fire(SDL_TOUCH_MOTION , dynamic_cast<widget&>(*dispatcher), position, distance);
704  }
705 }
706 
707 void sdl_event_handler::touch_up(const point& position)
708 {
710  dispatcher->fire(SDL_TOUCH_UP, dynamic_cast<widget&>(*dispatcher), position);
711  }
712 }
713 
715 {
717  dispatcher->fire(SDL_TOUCH_DOWN, dynamic_cast<widget&>(*dispatcher), position);
718  }
719 }
720 
721 void sdl_event_handler::touch_multi_gesture(const point& center, float dTheta, float dDist, uint8_t numFingers)
722 {
724  dispatcher->fire(SDL_TOUCH_MULTI_GESTURE, dynamic_cast<widget&>(*dispatcher), center, dTheta, dDist, numFingers);
725  }
726 }
727 
728 void sdl_event_handler::hat_motion(const SDL_Event& event)
729 {
730  const hotkey::hotkey_ptr& hk = hotkey::get_hotkey(event);
731  bool done = false;
732  if(!hk->null()) {
733  done = hotkey_pressed(hk);
734  }
735  if(!done) {
736  // TODO fendrin think about handling hat motions that are not bound to a
737  // hotkey.
738  }
739 }
740 
741 void sdl_event_handler::button_down(const SDL_Event& event)
742 {
743  const hotkey::hotkey_ptr hk = hotkey::get_hotkey(event);
744  bool done = false;
745  if(!hk->null()) {
746  done = hotkey_pressed(hk);
747  }
748  if(!done) {
749  // TODO fendrin think about handling button down events that are not
750  // bound to a hotkey.
751  }
752 }
753 
754 void sdl_event_handler::key_down(const SDL_Event& event)
755 {
756  const hotkey::hotkey_ptr hk = hotkey::get_hotkey(event);
757  bool done = false;
758  if(!hk->null()) {
759  done = hotkey_pressed(hk);
760  }
761  if(!done) {
762  if(event.type == SDL_TEXTINPUT) {
763  text_input(event.text.text);
764  } else {
765  key_down(event.key.keysym.sym, static_cast<SDL_Keymod>(event.key.keysym.mod), "");
766  }
767  }
768 }
769 
770 void sdl_event_handler::text_input(const std::string& unicode)
771 {
772  key_down(SDLK_UNKNOWN, static_cast<SDL_Keymod>(0), unicode);
773 
776  dynamic_cast<widget&>(*dispatcher),
777  unicode, -1, -1);
778  }
779 }
780 
781 void sdl_event_handler::text_editing(const std::string& unicode, int32_t start, int32_t len)
782 {
785  dynamic_cast<widget&>(*dispatcher),
786  unicode, start, len);
787  }
788 }
789 
791 {
793  return dispatcher->execute_hotkey(hotkey::get_hotkey_command(key->get_command()).command);
794  }
795 
796  return false;
797 }
798 
799 void sdl_event_handler::key_down(const SDL_Keycode key,
800  const SDL_Keymod modifier,
801  const std::string& unicode)
802 {
803  DBG_GUI_E << "Firing: " << SDL_KEY_DOWN << ".";
804 
806  dispatcher->fire(SDL_KEY_DOWN,
807  dynamic_cast<widget&>(*dispatcher),
808  key,
809  modifier,
810  unicode);
811  }
812 }
813 
815 {
816  DBG_GUI_E << "Firing: " << event << ".";
817 
819  dispatcher->fire(event, dynamic_cast<widget&>(*dispatcher));
820  }
821 }
822 
823 void sdl_event_handler::close_window(const unsigned window_id)
824 {
825  DBG_GUI_E << "Firing " << CLOSE_WINDOW << ".";
826 
827  window* window = window::window_instance(window_id);
828  if(window) {
829  window->fire(CLOSE_WINDOW, *window);
830  }
831 }
832 
833 /***** manager class. *****/
834 
836 {
837  handler_.reset(new sdl_event_handler());
838 
839 #ifdef MAIN_EVENT_HANDLER
840  draw_interval = 30;
841  SDL_AddTimer(draw_interval, timer_sdl_draw_event, nullptr);
842 
843  event_poll_interval = 10;
844  SDL_AddTimer(event_poll_interval, timer_sdl_poll_events, nullptr);
845 #endif
846 }
847 
849 {
850  handler_.reset(nullptr);
851 
852 #ifdef MAIN_EVENT_HANDLER
853  draw_interval = 0;
854  event_poll_interval = 0;
855 #endif
856 }
857 
858 /***** free functions class. *****/
859 
861 {
862  assert(handler_);
863  assert(dispatcher);
864  handler_->connect(dispatcher);
865 }
866 
868 {
869  assert(handler_);
870  assert(dispatcher);
871  handler_->disconnect(dispatcher);
872 }
873 
874 std::vector<dispatcher*>& get_all_dispatchers()
875 {
876  assert(handler_);
877  return handler_->get_dispatchers();
878 }
879 
881 {
883 
884  SDL_Event event{};
885  event.type = SDL_MOUSEMOTION;
886  event.motion.type = SDL_MOUSEMOTION;
887  event.motion.x = mouse.x;
888  event.motion.y = mouse.y;
889 
890  SDL_PushEvent(&event);
891 }
892 
894 {
895  assert(handler_);
896  assert(dispatcher);
897  handler_->mouse_focus = dispatcher;
898 }
899 
901 {
902  assert(handler_);
903  assert(dispatcher);
904  if(handler_->mouse_focus == dispatcher) {
905  handler_->mouse_focus = nullptr;
906  }
907 }
908 
910 {
911  assert(handler_);
912  assert(dispatcher);
913  assert(dispatcher->get_want_keyboard_input());
914 
915  handler_->keyboard_focus_ = dispatcher;
916 }
917 
918 std::ostream& operator<<(std::ostream& stream, const ui_event event)
919 {
920  switch(event) {
921  case DRAW:
922  stream << "draw";
923  break;
924  case CLOSE_WINDOW:
925  stream << "close window";
926  break;
927  case SDL_VIDEO_RESIZE:
928  stream << "SDL video resize";
929  break;
930  case SDL_MOUSE_MOTION:
931  stream << "SDL mouse motion";
932  break;
933  case MOUSE_ENTER:
934  stream << "mouse enter";
935  break;
936  case MOUSE_LEAVE:
937  stream << "mouse leave";
938  break;
939  case MOUSE_MOTION:
940  stream << "mouse motion";
941  break;
943  stream << "SDL left button down";
944  break;
945  case SDL_LEFT_BUTTON_UP:
946  stream << "SDL left button up";
947  break;
948  case LEFT_BUTTON_DOWN:
949  stream << "left button down";
950  break;
951  case LEFT_BUTTON_UP:
952  stream << "left button up";
953  break;
954  case LEFT_BUTTON_CLICK:
955  stream << "left button click";
956  break;
958  stream << "left button double click";
959  break;
961  stream << "SDL middle button down";
962  break;
964  stream << "SDL middle button up";
965  break;
966  case MIDDLE_BUTTON_DOWN:
967  stream << "middle button down";
968  break;
969  case MIDDLE_BUTTON_UP:
970  stream << "middle button up";
971  break;
972  case MIDDLE_BUTTON_CLICK:
973  stream << "middle button click";
974  break;
976  stream << "middle button double click";
977  break;
979  stream << "SDL right button down";
980  break;
981  case SDL_RIGHT_BUTTON_UP:
982  stream << "SDL right button up";
983  break;
984  case RIGHT_BUTTON_DOWN:
985  stream << "right button down";
986  break;
987  case RIGHT_BUTTON_UP:
988  stream << "right button up";
989  break;
990  case RIGHT_BUTTON_CLICK:
991  stream << "right button click";
992  break;
994  stream << "right button double click";
995  break;
996  case SDL_WHEEL_LEFT:
997  stream << "SDL wheel left";
998  break;
999  case SDL_WHEEL_RIGHT:
1000  stream << "SDL wheel right";
1001  break;
1002  case SDL_WHEEL_UP:
1003  stream << "SDL wheel up";
1004  break;
1005  case SDL_WHEEL_DOWN:
1006  stream << "SDL wheel down";
1007  break;
1008  case SDL_KEY_DOWN:
1009  stream << "SDL key down";
1010  break;
1011  case SDL_TEXT_INPUT:
1012  stream << "SDL text input";
1013  break;
1014  case SDL_TEXT_EDITING:
1015  stream << "SDL text editing";
1016  break;
1017 
1018  case NOTIFY_REMOVAL:
1019  stream << "notify removal";
1020  break;
1021  case NOTIFY_MODIFIED:
1022  stream << "notify modified";
1023  break;
1025  stream << "receive keyboard focus";
1026  break;
1027  case LOSE_KEYBOARD_FOCUS:
1028  stream << "lose keyboard focus";
1029  break;
1030  case SHOW_TOOLTIP:
1031  stream << "show tooltip";
1032  break;
1033  case NOTIFY_REMOVE_TOOLTIP:
1034  stream << "notify remove tooltip";
1035  break;
1036  case SDL_ACTIVATE:
1037  stream << "SDL activate";
1038  break;
1039  case MESSAGE_SHOW_TOOLTIP:
1040  stream << "message show tooltip";
1041  break;
1042  case SHOW_HELPTIP:
1043  stream << "show helptip";
1044  break;
1045  case MESSAGE_SHOW_HELPTIP:
1046  stream << "message show helptip";
1047  break;
1048  case REQUEST_PLACEMENT:
1049  stream << "request placement";
1050  break;
1051  case SDL_TOUCH_MOTION:
1052  stream << "SDL touch motion";
1053  break;
1054  case SDL_TOUCH_UP:
1055  stream << "SDL touch up";
1056  break;
1057  case SDL_TOUCH_DOWN:
1058  stream << "SDL touch down";
1059  break;
1061  stream << "SDL multi-touch gesture";
1062  break;
1063  case SDL_RAW_EVENT:
1064  stream << "SDL raw event";
1065  break;
1066  }
1067 
1068  return stream;
1069 }
1070 
1071 } // namespace event
1072 
1073 std::vector<window*> open_window_stack {};
1074 
1076 {
1077  for(auto iter = open_window_stack.rbegin(); iter != open_window_stack.rend(); ++iter) {
1078  if(*iter == window) {
1079  open_window_stack.erase(std::next(iter).base());
1080  break;
1081  }
1082  }
1083 }
1084 
1086 {
1087  return !open_window_stack.empty();
1088 }
1089 
1090 } // namespace gui2
mouse_behavior get_mouse_behavior() const
Definition: dispatcher.hpp:419
Define the common log macros for the gui toolkit.
dispatcher * keyboard_focus_
Needed to determine which dispatcher gets the keyboard events.
Definition: handler.cpp:343
static std::unique_ptr< class sdl_event_handler > handler_
Definition: handler.cpp:64
void touch_multi_gesture(const point &center, float dTheta, float dDist, uint8_t numFingers)
Fires a touch gesture event.
Definition: handler.cpp:721
ui_event
The event sent to the dispatcher.
Definition: handler.hpp:115
void video_resize(const point &new_size)
Fires a video resize event.
Definition: handler.cpp:583
#define LOG_GUI_E
Definition: log.hpp:36
bool hotkey_pressed(const hotkey::hotkey_ptr key)
Handles the pressing of a hotkey.
Definition: handler.cpp:790
Base class for event handling.
Definition: dispatcher.hpp:151
void activate()
Reinitializes the state of all dispatchers.
Definition: handler.cpp:575
This file contains the window object, this object is a top level container which has the event manage...
auto reversed_view(T &container)
Definition: ranges.hpp:28
void handle_window_event(const SDL_Event &event) override
Inherited from events::sdl_handler.
Definition: handler.cpp:521
void text_editing(const std::string &unicode, int32_t start, int32_t len)
Fires a text editing event.
Definition: handler.cpp:781
An SDL text input (commit) event.
Definition: handler.hpp:153
bool is_in_dialog()
Is a dialog open?
Definition: handler.cpp:1085
std::string_view data
Definition: picture.cpp:208
#define TIMER_EVENT
Definition: events.hpp:25
#define DRAW_EVENT
Definition: events.hpp:27
void capture_mouse(dispatcher *dispatcher)
Captures the mouse.
Definition: handler.cpp:893
button(const implementation::builder_button &builder)
Definition: button.cpp:44
void button_down(const SDL_Event &event)
Handles a joystick button down event.
Definition: handler.cpp:741
void hat_motion(const SDL_Event &event)
Handles a hat motion event.
Definition: handler.cpp:728
void key_down(const SDL_Event &event)
Fires a key down event.
Definition: handler.cpp:754
void touch_motion(const point &position, const point &distance)
Fires a touch-moved event.
Definition: handler.cpp:700
void init_mouse_location()
Initializes the location of the mouse.
Definition: handler.cpp:880
Generic file dialog.
#define CLOSE_WINDOW_EVENT
Definition: events.hpp:28
bool get_want_keyboard_input() const
Definition: dispatcher.hpp:429
An SDL text editing (IME) event.
Definition: handler.hpp:154
static events::event_context * event_context
Definition: handler.cpp:65
EXIT_STATUS start(const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Definition: editor_main.cpp:30
const hotkey_ptr get_hotkey(const SDL_Event &event)
Iterate through the list of hotkeys and return a hotkey that matches the SDL_Event and the current ke...
virtual bool is_at(const point &coordinate) const =0
Determines whether the location is inside an active widget.
This singleton class handles all events.
Definition: handler.cpp:122
void close_window(const unsigned window_id)
Fires a CLOSE_WINDOW event for the window with the given ID.
Definition: handler.cpp:823
std::shared_ptr< class hotkey_base > hotkey_ptr
Definition: hotkey_item.hpp:27
std::vector< dispatcher * > & get_all_dispatchers()
Gets all event dispatchers in the Z order.
Definition: handler.cpp:874
friend void capture_keyboard(dispatcher *dispatcher)
Captures the keyboard.
Definition: handler.cpp:909
bool execute_hotkey(const hotkey::HOTKEY_COMMAND id)
Executes a hotkey.
Definition: dispatcher.cpp:154
void remove_from_window_stack(window *window)
Removes a entry from the open_window_stack list.
Definition: handler.cpp:1075
void disconnect_dispatcher(dispatcher *dispatcher)
Disconnects a dispatcher to the event handler.
Definition: handler.cpp:867
sdl_handler(sdl_handler &&)=delete
virtual void join()
Definition: events.cpp:304
void connect_dispatcher(dispatcher *dispatcher)
Connects a dispatcher to the event handler.
Definition: handler.cpp:860
std::vector< dispatcher * > & get_dispatchers()
Returns all dispatchers in the Z order.
Definition: handler.cpp:154
void pump()
Process all events currently in the queue.
Definition: events.cpp:475
void mouse_button_up(const point &position, const uint8_t button)
Fires a mouse button up event.
Definition: handler.cpp:628
static window * window_instance(const unsigned handle)
Returns the instance of a window.
Definition: window.cpp:409
void mouse(const ui_event event, const point &position)
Fires a generic mouse event.
Definition: handler.cpp:602
void mouse_wheel(const point &position, int scrollx, int scrolly)
Fires a mouse wheel event.
Definition: handler.cpp:670
#define DOUBLE_CLICK_EVENT
Definition: events.hpp:24
void mouse_button_down(const point &position, const uint8_t button)
Fires a mouse button down event.
Definition: handler.cpp:649
void text_input(const std::string &unicode)
Fires a text input event.
Definition: handler.cpp:770
#define DBG_GUI_E
Definition: log.hpp:35
#define SHOW_HELPTIP_EVENT
Definition: events.hpp:29
#define WRN_GUI_E
Definition: log.hpp:37
point game_canvas_size()
The size of the game canvas, in drawing coordinates / game pixels.
Definition: video.cpp:386
void disconnect(dispatcher *dispatcher)
Disconnects a dispatcher.
Definition: handler.cpp:542
std::ostream & operator<<(std::ostream &stream, const ui_event event)
Definition: handler.cpp:918
Contains the gui2 timer routines.
Holds a 2D point.
Definition: point.hpp:24
#define HOVER_REMOVE_POPUP_EVENT
Definition: events.hpp:26
void keyboard(const ui_event event)
Fires a keyboard event which has no parameters.
Definition: handler.cpp:814
Type that can be thrown as an exception to quit to desktop.
Definition: video.hpp:303
void raw_event(const SDL_Event &event)
Fires a raw SDL event.
Definition: handler.cpp:593
Handling of system events.
Definition: manager.hpp:43
point get_mouse_position()
Returns the current mouse position.
Definition: helper.cpp:114
void touch_up(const point &position)
Fires a touch "finger up" event.
Definition: handler.cpp:707
std::vector< dispatcher * > dispatchers_
The dispatchers.
Definition: handler.cpp:336
void handle_event(const SDL_Event &event) override
Inherited from events::sdl_handler.
Definition: handler.cpp:372
void connect(dispatcher *dispatcher)
Connects a dispatcher.
Definition: handler.cpp:526
void release_mouse(dispatcher *dispatcher)
Releases a captured mouse.
Definition: handler.cpp:900
Simple push button.
Definition: button.hpp:36
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:76
void point(int x, int y)
Draw a single point.
Definition: draw.cpp:193
virtual void leave()
Definition: events.cpp:349
dispatcher * keyboard_dispatcher()
Gets the dispatcher that wants to receive the keyboard input.
Definition: handler.cpp:685
mock_char c
const hotkey_command & get_hotkey_command(const std::string &command)
returns the hotkey_command with the given name
void touch_down(const point &position)
Fires a touch "finger down" event.
Definition: handler.cpp:714
base class of top level items, the only item which needs to store the final canvases to draw on...
Definition: window.hpp:66
dispatcher * mouse_focus
The dispatcher that captured the mouse focus.
Definition: handler.cpp:157
bool execute_timer(const std::size_t id)
Executes a timer.
Definition: timer.cpp:201
std::vector< window * > open_window_stack
Keeps track of any open windows of any type (modal, non-modal, or tooltip) in the order in which they...
Definition: handler.cpp:1073