The Battle for Wesnoth  1.17.8+dev
handler.hpp
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 #pragma once
17 
18 #include <cstdint>
19 #include <iosfwd>
20 #include <vector>
21 
22 namespace gui2
23 {
24 class window;
25 
26 namespace event
27 {
28 class dispatcher;
29 
30 class manager
31 {
32 public:
33  manager();
34  ~manager();
35 };
36 
37 // clang-format off
38 
39 /**
40  * Event category masks.
41  *
42  * These begin at 2^8 to allow for 8 bits for the event identifiers themselves.
43  * This means ui_event can have up to 256 unique members. Since each mask needs
44  * its own place value, we can have 24 categories since ui_event's underlying
45  * type is 32 bits:
46  *
47  * USABLE CATEGORY BITS NULL
48  * |------------------------|--------|
49  * MASK 000000000000000000000000 00000000
50  *
51  * ENCODED CATEGORY EVENT
52  * |------------------------|--------|
53  * UI_EVENT 000000000000000000000000 00000000
54  */
55 enum class event_category : uint32_t {
56  /**
57  * Callbacks without extra parameters.
58  * @note Some mouse events like MOUSE_ENTER don't send the mouse coordinates
59  * to the callback function so they are also in this category.
60  */
61  general = 1u << 8,
62 
63  /**
64  * Callbacks with a coordinate as extra parameter.
65  */
66  mouse = 1u << 9,
67 
68  /**
69  * Callbacks with the keyboard values (these haven't been determined yet).
70  */
71  keyboard = 1u << 10,
72 
73  touch_motion = 1u << 11,
74  touch_gesture = 1u << 12,
75 
76  /**
77  * Callbacks with a sender aka notification messages. Like general events
78  * it has no extra parameters, but this version is only sent to the target
79  * and does not use the pre and post queue.
80  */
81  notification = 1u << 13,
82 
83  /**
84  * Callbacks with a sender aka notification messages.
85  * Unlike the notifications this message is send through the chain. The event
86  * is sent from a widget all the way up to the window, who is always the
87  * receiver of the message (unless somebody grabbed it before).
88  */
89  message = 1u << 14,
90 
91  raw_event = 1u << 15,
92  text_input = 1u << 16,
93 };
94 // clang-format on
95 
96 constexpr uint32_t encode_category(const uint32_t input, const event_category mask)
97 {
98  return input | static_cast<uint32_t>(mask);
99 }
100 
101 // clang-format off
102 
103 /**
104  * The event sent to the dispatcher.
105  *
106  * Events prefixed by SDL are (semi)-real SDL events. The handler does some
107  * minor decoding like splitting the button down event to the proper event but
108  * nothing more. Events without an SDL prefix are generated by another signal
109  * eg the windows signal handler for SDL_MOUSE_MOTION can generate a
110  * MOUSE_ENTER, MOUSE_MOTION and MOUSE_LEAVE event and send that to it's
111  * children.
112  *
113  * @note When adding a new entry to the enum also add a unit test.
114  */
115 enum ui_event : uint32_t {
132 
150 
152 
153  SDL_TEXT_INPUT = encode_category(35, event_category::text_input), /**< An SDL text input (commit) event. */
154  SDL_TEXT_EDITING = encode_category(36, event_category::text_input), /**< An SDL text editing (IME) event. */
155 
162 
166 
169 
171 };
172 // clang-format on
173 
174 /**
175  * Checks if a given event is in a given category.
176  *
177  * @note Even though all events currently have only one category bitflag set, this function
178  * works correctly if they ever have multiple flags set, unlike @ref get_event_category.
179  */
180 constexpr bool is_in_category(const ui_event event, const event_category mask)
181 {
182  const uint32_t asu32 = static_cast<uint32_t>(mask);
183  return (event & asu32) == asu32;
184 }
185 
186 /**
187  * Returns the category of a given event.
188  *
189  * @note Since each event has only *one* category flag set, it is safe to simply do an
190  * equality check with this result, which would return the same as @ref is_in_category.
191  */
193 {
194  // Zero-out the first 8 bits since those encode the ui_event value, which we don't want.
195  return static_cast<event_category>((event >> 8u) << 8u);
196 }
197 
198 /**
199  * Connects a dispatcher to the event handler.
200  *
201  * @param dispatcher The dispatcher to connect.
202  */
204 
205 /**
206  * Disconnects a dispatcher to the event handler.
207  *
208  * @param dispatcher The dispatcher to disconnect.
209  */
210 void disconnect_dispatcher(dispatcher* dispatcher);
211 
212 /**
213  * Gets all event dispatchers in the Z order.
214  */
215 std::vector<dispatcher*>& get_all_dispatchers();
216 
217 /**
218  * Initializes the location of the mouse.
219  *
220  * After a layout of the window the mouse location needs to be updated to
221  * test whether it entered or left a widget. Also after closing a window it's
222  * needed to send a dummy mouse move.
223  */
224 void init_mouse_location();
225 
226 /**
227  * Captures the mouse.
228  *
229  * A dispatcher can capture the mouse, when for example it's pressed on a
230  * button, this means all mouse events after that are send to that widget.
231  *
232  * @param dispatcher The dispatcher which should get the mouse
233  * focus.
234  */
235 void capture_mouse(dispatcher* dispatcher);
236 
237 /**
238  * Releases a captured mouse.
239  *
240  * @param dispatcher The dispatcher which should release the mouse
241  * capture.
242  */
243 void release_mouse(dispatcher* dispatcher);
244 
245 /**
246  * Captures the keyboard.
247  *
248  * A dispatcher can capture the keyboard, when for example it's pressed on a
249  * button, this means all keyboard events after that are send to that widget.
250  *
251  * @param dispatcher The dispatcher which should get the keyboard
252  * focus.
253  */
254 void capture_keyboard(dispatcher* dispatcher);
255 
256 std::ostream& operator<<(std::ostream& stream, const ui_event event);
257 
258 } // namespace event
259 
260 /**
261  * Keeps track of any open windows of any type (modal, non-modal, or tooltip) in the
262  * order in which they were opened. Currently only used as a helper for is_in_dialog(),
263  * but could potentially be useful for other things in the future.
264  */
265 extern std::vector<window*> open_window_stack;
266 
267 /** Removes a entry from the open_window_stack list. This should be used instead of pop_back. */
269 
270 /**
271  * Is a dialog open?
272  *
273  * @note added as backwards compatibility for gui::is_in_dialog.
274  */
275 bool is_in_dialog();
276 
277 } // namespace gui2
Callbacks without extra parameters.
constexpr event_category get_event_category(const ui_event event)
Returns the category of a given event.
Definition: handler.hpp:192
ui_event
The event sent to the dispatcher.
Definition: handler.hpp:115
Base class for event handling.
Definition: dispatcher.hpp:151
An SDL text input (commit) event.
Definition: handler.hpp:153
bool is_in_dialog()
Is a dialog open?
Definition: handler.cpp:1085
constexpr uint32_t encode_category(const uint32_t input, const event_category mask)
Definition: handler.hpp:96
void capture_mouse(dispatcher *dispatcher)
Captures the mouse.
Definition: handler.cpp:893
void capture_keyboard(dispatcher *dispatcher)
Captures the keyboard.
Definition: handler.cpp:909
void init_mouse_location()
Initializes the location of the mouse.
Definition: handler.cpp:880
Generic file dialog.
The message callbacks hold a reference to a message.
Definition: message.hpp:45
An SDL text editing (IME) event.
Definition: handler.hpp:154
Callbacks with a sender aka notification messages.
std::vector< dispatcher * > & get_all_dispatchers()
Gets all event dispatchers in the Z order.
Definition: handler.cpp:874
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
void connect_dispatcher(dispatcher *dispatcher)
Connects a dispatcher to the event handler.
Definition: handler.cpp:860
event_category
Event category masks.
Definition: handler.hpp:55
Callbacks with a sender aka notification messages.
Callbacks with the keyboard values (these haven&#39;t been determined yet).
std::ostream & operator<<(std::ostream &stream, const ui_event event)
Definition: handler.cpp:918
Callbacks with a coordinate as extra parameter.
constexpr bool is_in_category(const ui_event event, const event_category mask)
Checks if a given event is in a given category.
Definition: handler.hpp:180
void release_mouse(dispatcher *dispatcher)
Releases a captured mouse.
Definition: handler.cpp:900
base class of top level items, the only item which needs to store the final canvases to draw on...
Definition: window.hpp:66
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