The Battle for Wesnoth  1.15.7+dev
distributor.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2018 by Mark de Wever <koraq@xs4all.nl>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
18 
19 #include "events.hpp"
20 #include "gui/core/log.hpp"
21 #include "gui/core/timer.hpp"
22 #include "gui/widgets/settings.hpp"
23 #include "gui/widgets/widget.hpp"
24 #include "gui/widgets/window.hpp"
26 #include "sdl/userevent.hpp"
27 
28 #include "utils/functional.hpp"
29 
30 namespace gui2
31 {
32 
33 namespace event
34 {
35 
36 /**
37  * Small helper to keep a resource (boolean) locked.
38  *
39  * Some of the event handling routines can't be called recursively, this due to
40  * the fact that they are attached to the pre queue and when the forward an
41  * event the pre queue event gets triggered recursively causing infinite
42  * recursion.
43  *
44  * To prevent that those functions check the lock and exit when the lock is
45  * held otherwise grab the lock here.
46  */
48 {
49 public:
50  resource_locker(bool& locked) : locked_(locked)
51  {
52  assert(!locked_);
53  locked_ = true;
54  }
55 
57  {
58  assert(locked_);
59  locked_ = false;
60  }
61 
62 private:
63  bool& locked_;
64 };
65 
66 
67 /***** ***** ***** ***** mouse_motion ***** ***** ***** ***** *****/
68 
69 #define LOG_HEADER "distributor mouse motion [" << owner_.id() << "]: "
70 
72  const dispatcher::queue_position queue_position)
73  : mouse_focus_(nullptr)
74  , mouse_captured_(false)
75  , owner_(owner)
76  , hover_timer_(0)
77  , hover_widget_(nullptr)
78  , hover_position_(0, 0)
79  , hover_shown_(true)
80  , signal_handler_sdl_mouse_motion_entered_(false)
81 {
84  this,
85  _2,
86  _3,
87  _5),
88  queue_position);
89 
92  this,
93  _2,
94  _3,
95  _5,
96  _6),
97  queue_position);
98 
100  &mouse_motion::signal_handler_sdl_wheel, this, _2, _3, _5));
102  &mouse_motion::signal_handler_sdl_wheel, this, _2, _3, _5));
104  &mouse_motion::signal_handler_sdl_wheel, this, _2, _3, _5));
106  &mouse_motion::signal_handler_sdl_wheel, this, _2, _3, _5));
107 
110  this,
111  _2,
112  _3,
113  _5),
114  queue_position);
115 }
116 
118 {
120 }
121 
122 void mouse_motion::capture_mouse(const bool capture)
123 {
124  assert(mouse_focus_);
125  mouse_captured_ = capture;
126 }
127 
129  bool& handled,
130  const point& coordinate)
131 {
133  return;
134  }
136 
137  DBG_GUI_E << LOG_HEADER << event << ".\n";
138 
139  if(mouse_captured_) {
140  assert(mouse_focus_);
141  if(!owner_.fire(event, *mouse_focus_, coordinate)) {
142  mouse_hover(mouse_focus_, coordinate);
143  }
144  } else {
145  widget* mouse_over = owner_.find_at(coordinate, true);
146  while(mouse_over && !mouse_over->can_mouse_focus() && mouse_over->parent()) {
147  mouse_over = mouse_over->parent();
148  }
149  if(mouse_over) {
150  DBG_GUI_E << LOG_HEADER << "Firing: " << event << ".\n";
151  if(owner_.fire(event, *mouse_over, coordinate)) {
152  return;
153  }
154  }
155 
156  if(!mouse_focus_ && mouse_over) {
157  mouse_enter(mouse_over);
158  } else if(mouse_focus_ && !mouse_over) {
159  mouse_leave();
160  } else if(mouse_focus_ && mouse_focus_ == mouse_over) {
161  mouse_hover(mouse_over, coordinate);
162  } else if(mouse_focus_ && mouse_over) {
163  // moved from one widget to the next
164  mouse_leave();
165  mouse_enter(mouse_over);
166  } else {
167  assert(!mouse_focus_ && !mouse_over);
168  }
169  }
170  handled = true;
171 }
172 
174  bool& handled,
175  const point& coordinate,
176  const point& distance)
177 {
178  DBG_GUI_E << LOG_HEADER << event << ".\n";
179 
180  if(mouse_captured_) {
181  assert(mouse_focus_);
182  owner_.fire(event, *mouse_focus_, coordinate, distance);
183  } else {
184  widget* mouse_over = owner_.find_at(coordinate, true);
185  if(mouse_over) {
186  owner_.fire(event, *mouse_over, coordinate, distance);
187  }
188  }
189  handled = true;
190 }
191 
193  bool& handled,
194  const point& coordinate)
195 {
196  DBG_GUI_E << LOG_HEADER << event << ".\n";
197 
198  if(mouse_captured_) {
199  assert(mouse_focus_);
200  owner_.fire(event, *mouse_focus_, coordinate);
201  } else {
202  widget* mouse_over = owner_.find_at(coordinate, true);
203  if(mouse_over) {
204  owner_.fire(event, *mouse_over, coordinate);
205  }
206  }
207  handled = true;
208 }
209 
211  bool& handled,
212  const point& coordinate)
213 {
214  DBG_GUI_E << LOG_HEADER << event << ".\n";
215 
216  if(mouse_captured_) {
217  assert(mouse_focus_);
218  if(owner_.fire(event, *mouse_focus_, coordinate)) {
220  }
221  } else {
222  widget* mouse_over = owner_.find_at(coordinate, true);
223  if(mouse_over) {
224  DBG_GUI_E << LOG_HEADER << "Firing: " << event << ".\n";
225  if(owner_.fire(event, *mouse_over, coordinate)) {
227  }
228  }
229  }
230 
231  handled = true;
232 }
233 
235 {
236  DBG_GUI_E << LOG_HEADER << "Firing: " << event::MOUSE_ENTER << ".\n";
237 
238  assert(mouse_over);
239 
240  mouse_focus_ = mouse_over;
241  owner_.fire(event::MOUSE_ENTER, *mouse_over);
242 
243  hover_shown_ = false;
244  start_hover_timer(mouse_over, get_mouse_position());
245 }
246 
248 {
249  DBG_GUI_E << LOG_HEADER << "Firing: " << event::MOUSE_MOTION << ".\n";
250 
251  assert(mouse_over);
252 
253  owner_.fire(event::MOUSE_MOTION, *mouse_over, coordinate);
254 
255  if(hover_timer_) {
256  if((std::abs(hover_position_.x - coordinate.x) > 5)
257  || (std::abs(hover_position_.y - coordinate.y) > 5)) {
258 
260  start_hover_timer(mouse_over, coordinate);
261  }
262  }
263 }
264 
266 {
267  DBG_GUI_E << LOG_HEADER << "Firing: " << event::SHOW_TOOLTIP << ".\n";
268 
269  if(!hover_widget_) {
270  // See mouse_motion::stop_hover_timer.
271  ERR_GUI_E << LOG_HEADER << event::SHOW_TOOLTIP
272  << " bailing out, no hover widget.\n";
273  return;
274  }
275 
276  /*
277  * Ignore the result of the event, always mark the tooltip as shown. If
278  * there was no handler, there is no reason to assume there will be one
279  * next time.
280  */
282 
283  hover_shown_ = true;
284 
285  hover_timer_ = 0;
286  hover_widget_ = nullptr;
288 }
289 
291 {
292  DBG_GUI_E << LOG_HEADER << "Firing: " << event::MOUSE_LEAVE << ".\n";
293 
294  styled_widget* control = dynamic_cast<styled_widget*>(mouse_focus_);
295  if(!control || control->get_active()) {
296  owner_.fire(event::MOUSE_LEAVE, *mouse_focus_);
297  }
298 
300 
301  mouse_focus_ = nullptr;
302 
304 }
305 
307 {
308  assert(widget);
309 
310 #ifdef __IPHONEOS__
311  // Guessing a crash location in a nasty stack in gui2::execute_timer.
312  // Either this or a long-touch menu.
313  // Remove this when the crash in gui2::execute_timer() and gui2::timer_callback() is gone and try again.
314  return;
315 #endif
316 
318 
319  if(hover_shown_ || !widget->wants_mouse_hover()) {
320  return;
321  }
322 
323  DBG_GUI_E << LOG_HEADER << "Start hover timer for widget '" << widget->id()
324  << "' at address " << widget << ".\n";
325 
327  = add_timer(50, std::bind(&mouse_motion::show_tooltip, this));
328 
329  if(hover_timer_) {
330  hover_widget_ = widget;
332  } else {
333  ERR_GUI_E << LOG_HEADER << "Failed to add hover timer." << std::endl;
334  }
335 }
336 
338 {
339  if(hover_timer_) {
340  assert(hover_widget_);
341  DBG_GUI_E << LOG_HEADER << "Stop hover timer for widget '"
342  << hover_widget_->id() << "' at address " << hover_widget_
343  << ".\n";
344 
345  if(!remove_timer(hover_timer_)) {
346  ERR_GUI_E << LOG_HEADER << "Failed to remove hover timer."
347  << std::endl;
348  }
349 
350  hover_timer_ = 0;
351  hover_widget_ = nullptr;
353  }
354 }
355 
356 /***** ***** ***** ***** mouse_button ***** ***** ***** ***** *****/
357 
358 #undef LOG_HEADER
359 #define LOG_HEADER \
360  "distributor mouse button " << events_.name << " [" << owner_.id() << "]: "
361 
363  const dispatcher::queue_position queue_position)
364  : mouse_motion(owner, queue_position)
365  , last_click_stamp_(0)
366  , last_clicked_widget_(nullptr)
367  , focus_(nullptr)
368  , events_(events)
369  , is_down_(false)
370  , signal_handler_sdl_button_down_entered_(false)
371  , signal_handler_sdl_button_up_entered_(false)
372 {
373  // The connect_signal framework is currently using SFINAE checking to ensure that we only
374  // register mouse button signal handlers for mouse buttons. That causes us to need this
375  // hardcoded (either directly or by making mouse_button a templated class), the manual handling
376  // of the three cases here is the current progress on refactoring.
381  this,
382  _2,
383  _3,
384  _5),
385  queue_position);
388  this,
389  _2,
390  _3,
391  _5),
392  queue_position);
393  break;
394  }
398  this,
399  _2,
400  _3,
401  _5),
402  queue_position);
405  this,
406  _2,
407  _3,
408  _5),
409  queue_position);
410  break;
411  }
415  this,
416  _2,
417  _3,
418  _5),
419  queue_position);
422  this,
423  _2,
424  _3,
425  _5),
426  queue_position);
427  break;
428  }
429  default: {
430  // There's exactly three instances of this class per instance of distributor, so this assert
431  // will be caught during the build-time-tests.
432  assert(!"Hardcoded assumption about button being LEFT / MIDDLE / RIGHT failed");
433  }
434  }
435 }
436 
437 void mouse_button::initialize_state(int32_t button_state)
438 {
439  last_click_stamp_ = 0;
440  last_clicked_widget_ = nullptr;
441  focus_ = 0;
442  is_down_ = button_state & events_.mask;
443 }
444 
446  const point& coordinate)
447 {
449  return;
450  }
452 
453  DBG_GUI_E << LOG_HEADER << event << ".\n";
454 
455  if(is_down_) {
456 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
457  WRN_GUI_E << LOG_HEADER << event
458  << ". The mouse button is already down, "
459  << "we missed an event.\n";
460 #endif
461  return;
462  }
463  is_down_ = true;
464 
465  if(mouse_captured_) {
466  assert(mouse_focus_);
468  DBG_GUI_E << LOG_HEADER << "Firing: " << events_.sdl_button_down_event << ".\n";
469  if(!owner_.fire(events_.sdl_button_down_event, *focus_, coordinate)) {
470  DBG_GUI_E << LOG_HEADER << "Firing: " << events_.button_down_event << ".\n";
472  }
473  } else {
474  widget* mouse_over = owner_.find_at(coordinate, true);
475  if(!mouse_over) {
476  return;
477  }
478 
479  if(mouse_over != mouse_focus_) {
480 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
481  WRN_GUI_E << LOG_HEADER << ". Mouse down on non focused widget "
482  << "and mouse not captured, we missed events.\n";
483 #endif
484  mouse_focus_ = mouse_over;
485  }
486 
487  focus_ = mouse_over;
488  DBG_GUI_E << LOG_HEADER << "Firing: " << events_.sdl_button_down_event << ".\n";
489  if(!owner_.fire(events_.sdl_button_down_event, *focus_, coordinate)) {
490  DBG_GUI_E << LOG_HEADER << "Firing: " << events_.button_down_event << ".\n";
492  }
493  }
494  handled = true;
495 }
496 
498  const point& coordinate)
499 {
501  return;
502  }
504 
505  DBG_GUI_E << LOG_HEADER << event << ".\n";
506 
507  if(!is_down_) {
508 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
509  WRN_GUI_E << LOG_HEADER << event
510  << ". The mouse button is already up, we missed an event.\n";
511 #endif
512  return;
513  }
514  is_down_ = false;
515 
516  if(focus_) {
517  DBG_GUI_E << LOG_HEADER << "Firing: " << events_.sdl_button_up_event << ".\n";
518  if(!owner_.fire(events_.sdl_button_up_event, *focus_, coordinate)) {
519  DBG_GUI_E << LOG_HEADER << "Firing: " << events_.button_up_event << ".\n";
521  }
522  }
523 
524  // FIXME: The block below is strange diamond inheritance - it's code that could be in
525  // mouse_motion which applies to all three buttons, but it will be run in one of the
526  // three mouse_button<T> subclasses, and then the other two mouse_button<T> subclasses
527  // will reach here with mouse_captured_ == false.
528  widget* mouse_over = owner_.find_at(coordinate, true);
529  if(mouse_captured_) {
530  const unsigned mask = SDL_BUTTON_LMASK | SDL_BUTTON_MMASK
531  | SDL_BUTTON_RMASK;
532 
533  if((SDL_GetMouseState(nullptr, nullptr) & mask) == 0) {
534  mouse_captured_ = false;
535  }
536 
537  if(mouse_focus_ == mouse_over) {
539  } else if(!mouse_captured_) {
540  mouse_leave();
541 
542  if(mouse_over) {
543  mouse_enter(mouse_over);
544  }
545  }
546  } else if(focus_ && focus_ == mouse_over) {
548  }
549 
550  focus_ = nullptr;
551  handled = true;
552 }
553 
555 {
556  uint32_t stamp = SDL_GetTicks();
558  && last_clicked_widget_ == widget) {
559 
560  DBG_GUI_E << LOG_HEADER << "Firing: " << events_.button_double_click_event << ".\n";
561 
563  last_click_stamp_ = 0;
564  last_clicked_widget_ = nullptr;
565 
566  } else {
567 
568  DBG_GUI_E << LOG_HEADER << "Firing: " << events_.button_click_event << ".\n";
570  last_click_stamp_ = stamp;
571  last_clicked_widget_ = widget;
572  }
573 }
574 
575 /***** ***** ***** ***** distributor ***** ***** ***** ***** *****/
576 
577 #undef LOG_HEADER
578 #define LOG_HEADER "distributor mouse motion [" << owner_.id() << "]: "
579 
580 namespace
581 {
582 
583 const auto mouse_button_left_events = mouse_button_event_types {
590  SDL_BUTTON_LMASK,
591  "left"};
592 
593 const auto mouse_button_middle_events = mouse_button_event_types {
600  SDL_BUTTON_MMASK,
601  "middle"};
602 
603 const auto mouse_button_right_events = mouse_button_event_types {
610  SDL_BUTTON_RMASK,
611  "right"};
612 } // anonymous namespace
613 
614 /**
615  * @todo Test whether the state is properly tracked when an input blocker is
616  * used.
617  */
619  const dispatcher::queue_position queue_position)
620  : mouse_motion(owner, queue_position)
621  , mouse_button_left(mouse_button_left_events, owner, queue_position)
622  , mouse_button_middle(mouse_button_middle_events, owner, queue_position)
623  , mouse_button_right(mouse_button_right_events, owner, queue_position)
624  , keyboard_focus_(nullptr)
625  , keyboard_focus_chain_()
626 {
627  if(SDL_WasInit(SDL_INIT_TIMER) == 0) {
628  if(SDL_InitSubSystem(SDL_INIT_TIMER) == -1) {
629  assert(false);
630  }
631  }
632 
634  &distributor::signal_handler_sdl_key_down, this, _5, _6, _7));
635 
637  &distributor::signal_handler_sdl_text_input, this, _5, _6, _7));
638 
641 
644 
646 }
647 
649 {
651  &distributor::signal_handler_sdl_key_down, this, _5, _6, _7));
652 
654  &distributor::signal_handler_sdl_text_input, this, _5, _6, _7));
655 
658 
661 }
662 
664 {
665  const uint32_t button_state = SDL_GetMouseState(nullptr, nullptr);
666 
670 
672 }
673 
675 {
676  return keyboard_focus_;
677 }
678 
680 {
681  if(keyboard_focus_) {
683  << ".\n";
684 
685  owner_.fire(event::LOSE_KEYBOARD_FOCUS, *keyboard_focus_, nullptr);
686  }
687 
688  keyboard_focus_ = widget;
689 
690  if(keyboard_focus_) {
692  << ".\n";
693 
694  owner_.fire(event::RECEIVE_KEYBOARD_FOCUS, *keyboard_focus_, nullptr);
695  }
696 }
697 
699 {
700  assert(widget);
701  assert(std::find(keyboard_focus_chain_.begin(),
702  keyboard_focus_chain_.end(),
703  widget) == keyboard_focus_chain_.end());
704 
705  keyboard_focus_chain_.push_back(widget);
706 }
707 
709 {
710  assert(w);
711  auto itor = std::find(keyboard_focus_chain_.begin(), keyboard_focus_chain_.end(), w);
712 
713  if(itor != keyboard_focus_chain_.end()) {
714  keyboard_focus_chain_.erase(itor);
715  }
716 }
717 
718 template<typename Fcn, typename P1, typename P2, typename P3>
720 {
721  /** @todo Test whether recursion protection is needed. */
722 
723  DBG_GUI_E << LOG_HEADER << evt << ".\n";
724 
725  if(keyboard_focus_) {
726  // Attempt to cast to styled_widget, to avoid sending events if the
727  // widget is disabled. If the cast fails, we assume the widget
728  // is enabled and ready to receive events.
729  styled_widget* control = dynamic_cast<styled_widget*>(keyboard_focus_);
730  if(!control || control->get_active()) {
731  DBG_GUI_E << LOG_HEADER << "Firing: " << evt
732  << ".\n";
733  if(owner_.fire(evt, *keyboard_focus_, p1, p2, p3)) {
734  return;
735  }
736  }
737  if(text_box_base* tb = dynamic_cast<text_box_base*>(keyboard_focus_)) {
738  if(tb->is_composing()) {
739  return; // Skip the keyboard chain if composition is in progress.
740  }
741  }
742  }
743 
744  for(std::vector<widget*>::reverse_iterator ritor
745  = keyboard_focus_chain_.rbegin();
746  ritor != keyboard_focus_chain_.rend();
747  ++ritor) {
748 
749  if(*ritor == keyboard_focus_) {
750  continue;
751  }
752 
753  if(*ritor == &owner_) {
754  /**
755  * @todo Make sure we're not in the event chain.
756  *
757  * No idea why we're here, but needs to be fixed, otherwise we keep
758  * calling this function recursively upon unhandled events...
759  *
760  * Probably added to make sure the window can grab the events and
761  * handle + block them when needed, this is no longer needed with
762  * the chain.
763  */
764  continue;
765  }
766 
767  // Attempt to cast to styled_widget, to avoid sending events if the
768  // widget is disabled. If the cast fails, we assume the widget
769  // is enabled and ready to receive events.
770  styled_widget* control = dynamic_cast<styled_widget*>(keyboard_focus_);
771  if(control != nullptr && !control->get_active()) {
772  continue;
773  }
774 
775  DBG_GUI_E << LOG_HEADER << "Firing: " << evt << ".\n";
776  if(owner_.fire(evt, **ritor, p1, p2, p3)) {
777 
778  return;
779  }
780  }
781 }
782 
783 void distributor::signal_handler_sdl_key_down(const SDL_Keycode key, const SDL_Keymod modifier, const std::string& unicode)
784 {
785  signal_handler_keyboard_internal<signal_keyboard_function>(event::SDL_KEY_DOWN, key, modifier, unicode);
786 }
787 
788 void distributor::signal_handler_sdl_text_input(const std::string& unicode, int32_t start, int32_t end)
789 {
790  signal_handler_keyboard_internal<signal_text_input_function>(event::SDL_TEXT_INPUT, unicode, start, end);
791 }
792 
793 void distributor::signal_handler_sdl_text_editing(const std::string& unicode, int32_t start, int32_t end)
794 {
795  signal_handler_keyboard_internal<signal_text_input_function>(event::SDL_TEXT_EDITING, unicode, start, end);
796 }
797 
799  const ui_event event)
800 {
801  DBG_GUI_E << LOG_HEADER << event << ".\n";
802 
803  /**
804  * @todo Evaluate whether moving the cleanup parts in the subclasses.
805  *
806  * It might be cleaner to do it that way, but creates extra small
807  * functions...
808  */
809 
810  if(hover_widget_ == &w) {
812  }
813 
816  }
817  if(mouse_button_left::focus_ == &w) {
818  mouse_button_left::focus_ = nullptr;
819  }
820 
823  }
824  if(mouse_button_middle::focus_ == &w) {
825  mouse_button_middle::focus_ = nullptr;
826  }
827 
830  }
831  if(mouse_button_right::focus_ == &w) {
832  mouse_button_right::focus_ = nullptr;
833  }
834 
835  if(mouse_focus_ == &w) {
836  mouse_focus_ = nullptr;
837  }
838 
839  if(keyboard_focus_ == &w) {
840  keyboard_focus_ = nullptr;
841  }
842  const auto itor = std::find(keyboard_focus_chain_.begin(), keyboard_focus_chain_.end(), &w);
843  if(itor != keyboard_focus_chain_.end()) {
844  keyboard_focus_chain_.erase(itor);
845  }
846 }
847 
848 } // namespace event
849 
850 } // namespace gui2
Define the common log macros for the gui toolkit.
uint32_t last_click_stamp_
The time of the last click used for double clicking.
#define ERR_GUI_E
Definition: log.hpp:37
Request the widget to show its hover helptip.
Definition: handler.hpp:105
bool hover_shown_
Has the hover been shown for the widget?
Three subclasses of mouse_button, so that the distributor class can inherit from them; C++ doesn&#39;t al...
An SDL text editing (IME) event.
Definition: handler.hpp:85
void signal_handler_sdl_touch_motion(const event::ui_event event, bool &handled, const point &coordinate, const point &distance)
Abstract base class for text items.
std::vector< widget * > keyboard_focus_chain_
Fall back keyboard focus_ items.
A left mouse button down event for a widget.
Definition: handler.hpp:60
Widget loses keyboard focus.
Definition: handler.hpp:100
unsigned double_click_time
Definition: settings.cpp:39
An SDL wheel right event.
Definition: handler.hpp:80
Base class for event handling.
Definition: dispatcher.hpp:306
void signal_handler_sdl_wheel(const event::ui_event event, bool &handled, const point &coordinate)
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:76
virtual bool get_active() const =0
Gets the active state of the styled_widget.
An SDL left mouse button down event.
Definition: handler.hpp:58
void keyboard_capture(widget *widget)
Captures the keyboard input.
void initialize_state(int32_t button_state)
Initializes the state of the button.
const std::string & id() const
Definition: widget.cpp:109
This file contains the window object, this object is a top level container which has the event manage...
An SDL key down event.
Definition: handler.hpp:83
Base class for all widgets.
Definition: widget.hpp:49
A mouse leave event for a widget.
Definition: handler.hpp:56
widget * focus_
If the mouse isn&#39;t captured we need to verify the up is on the same widget as the down so we send a p...
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:77
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:69
An SDL right mouse button down event.
Definition: handler.hpp:72
void signal_handler_sdl_key_down(const SDL_Keycode key, const SDL_Keymod modifier, const std::string &unicode)
Set of functions that handle certain events and sends them to the proper widget.
std::enable_if_t< is_general_event(E)> disconnect_signal(const signal_function &signal, const queue_position position=back_child)
Disconnect a signal for callback in set_event.
Definition: dispatcher.hpp:522
See LEFT_BUTTON_DOWN.
Definition: handler.hpp:67
bool wants_mouse_hover() const
Contains the event distributor.
An SDL wheel down event.
Definition: handler.hpp:82
See LEFT_BUTTON_UP.
Definition: handler.hpp:75
Widget gains keyboard focus.
Definition: handler.hpp:99
Request the widget to show its hover tooltip.
Definition: handler.hpp:102
widget * last_clicked_widget_
The widget the last click was on, used for double clicking.
void mouse_hover(widget *mouse_over, const point &coordinate)
Called when the mouse moves over a widget.
int x
x coordinate.
Definition: point.hpp:44
void init_mouse_location()
Initializes the location of the mouse.
Definition: handler.cpp:911
Generic file dialog.
Definition: field-fwd.hpp:22
void signal_handler_show_helptip(const event::ui_event event, bool &handled, const point &coordinate)
Request the widget to remove its hover tooltip.
Definition: handler.hpp:103
void keyboard_add_to_chain(widget *widget)
Adds the widget to the keyboard chain.
void signal_handler_sdl_button_down(const event::ui_event event, bool &handled, const point &coordinate)
distributor(widget &owner, const dispatcher::queue_position queue_position)
bool is_down_
Is the button down?
Small helper to keep a resource (boolean) locked.
Definition: distributor.cpp:47
int32_t mask
Bitmask corresponding to this button&#39;s bit in SDL_GetMouseState&#39;s return value.
void signal_handler_keyboard_internal(event::ui_event evt, P1 &&p1, P2 &&p2, P3 &&p3)
This file contains the settings handling of the widget library.
widget & owner_
The widget that owns us.
Definition: distributor.hpp:83
A left mouse button up event for a widget.
Definition: handler.hpp:61
widget * keyboard_focus_
The widget that holds the keyboard focus_.
Sent by a widget to notify others it&#39;s being destroyed.
Definition: handler.hpp:87
widget * parent()
Definition: widget.cpp:159
An SDL middle mouse button down event.
Definition: handler.hpp:65
void start_hover_timer(widget *widget, const point &coordinate)
Starts the hover timer.
virtual bool can_mouse_focus() const
Whether the mouse move/click event go &#39;through&#39; this widget.
Definition: widget.hpp:328
point hover_position_
The anchor point of the hover event.
Definition: distributor.hpp:92
An SDL wheel up event.
Definition: handler.hpp:81
const mouse_button_event_types events_
Which set of SDL events correspond to this button.
An SDL middle mouse button up event.
Definition: handler.hpp:66
void signal_handler_notify_removal(dispatcher &widget, const ui_event event)
void mouse_enter(widget *mouse_over)
Called when the mouse enters a widget.
std::enable_if_t< is_general_event(E)> connect_signal(const signal_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_event.
Definition: dispatcher.hpp:505
#define DBG_GUI_E
Definition: log.hpp:34
void capture_mouse(const bool capture=true)
Captures the mouse input.
An SDL wheel left event.
Definition: handler.hpp:79
widget * mouse_focus_
The widget that currently has the mouse focus_.
Definition: distributor.hpp:77
A mouse motion event for a widget.
Definition: handler.hpp:55
#define WRN_GUI_E
Definition: log.hpp:36
mouse_button(const mouse_button_event_types &events, widget &owner, const dispatcher::queue_position queue_position)
A left mouse button double click event for a widget.
Definition: handler.hpp:63
std::size_t hover_timer_
The timer for the hover event.
Definition: distributor.hpp:86
A mouse enter event for a widget.
Definition: handler.hpp:54
Contains the gui2 timer routines.
Holds a 2D point.
Definition: point.hpp:23
void mouse_leave()
Called when the mouse leaves the current widget.
std::size_t add_timer(const uint32_t interval, const std::function< void(std::size_t id)> &callback, const bool repeat)
Adds a new timer.
Definition: timer.cpp:126
int w
Base class for all visible items.
void signal_handler_sdl_mouse_motion(const event::ui_event event, bool &handled, const point &coordinate)
queue_position
The position where to add a new callback in the signal handler.
Definition: dispatcher.hpp:477
void keyboard_remove_from_chain(widget *widget)
Remove the widget from the keyboard chain.
Handling of system events.
Definition: manager.hpp:42
bool mouse_captured_
Did the current widget capture the focus_?
Definition: distributor.hpp:80
An SDL left mouse button up event.
Definition: handler.hpp:59
point get_mouse_position()
Returns the current mouse position.
Definition: helper.cpp:117
mouse_motion(widget &owner, const dispatcher::queue_position queue_position)
Definition: distributor.cpp:71
void stop_hover_timer()
Stops the current hover timer.
#define LOG_HEADER
void show_tooltip()
Called when the mouse wants the widget to show its tooltip.
An SDL text input (commit) event.
Definition: handler.hpp:84
widget * keyboard_focus() const
Return the widget currently capturing keyboard input.
Small helper metastruct to configure instances of mouse_button.
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:68
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:28
widget * hover_widget_
The widget which should get the hover event.
Definition: distributor.hpp:89
See LEFT_BUTTON_DOWN.
Definition: handler.hpp:74
virtual widget * find_at(const point &coordinate, const bool must_be_active)
Returns the widget at the wanted coordinates.
Definition: widget.cpp:572
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
void signal_handler_sdl_button_up(const event::ui_event event, bool &handled, const point &coordinate)
void signal_handler_sdl_text_editing(const std::string &unicode, int32_t start, int32_t len)
An SDL right mouse button up event.
Definition: handler.hpp:73
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:70
int y
y coordinate.
Definition: point.hpp:47
A left mouse button click event for a widget.
Definition: handler.hpp:62
void mouse_button_click(widget *widget)
void initialize_state()
Initializes the state of the keyboard and mouse.
See LEFT_BUTTON_UP.
Definition: handler.hpp:68
ui_event
The event send to the dispatcher.
Definition: handler.hpp:47
void signal_handler_sdl_text_input(const std::string &unicode, int32_t start, int32_t len)
bool remove_timer(const std::size_t id)
Removes a timer.
Definition: timer.cpp:167
An SDL mouse motion event.
Definition: handler.hpp:53