The Battle for Wesnoth  1.19.13+dev
handler.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2025
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 
133  // Mouse forward/back buttons (buttons 4 and 5, SDL_BUTTON_X1/SDL_BUTTON_X2)
142 
152 
153  // Raw mouse forward/back button events
158 
167 
169 
170  SDL_TEXT_INPUT = encode_category(35, event_category::text_input), /**< An SDL text input (commit) event. */
171  SDL_TEXT_EDITING = encode_category(36, event_category::text_input), /**< An SDL text editing (IME) event. */
172 
179 
183 
186 
188 };
189 // clang-format on
190 
191 /**
192  * Checks if a given event is in a given category.
193  *
194  * @note Even though all events currently have only one category bitflag set, this function
195  * works correctly if they ever have multiple flags set, unlike @ref get_event_category.
196  */
197 constexpr bool is_in_category(const ui_event event, const event_category mask)
198 {
199  const uint32_t asu32 = static_cast<uint32_t>(mask);
200  return (event & asu32) == asu32;
201 }
202 
203 /**
204  * Returns the category of a given event.
205  *
206  * @note Since each event has only *one* category flag set, it is safe to simply do an
207  * equality check with this result, which would return the same as @ref is_in_category.
208  */
210 {
211  // Zero-out the first 8 bits since those encode the ui_event value, which we don't want.
212  return static_cast<event_category>((event >> 8u) << 8u);
213 }
214 
215 /**
216  * Connects a dispatcher to the event handler.
217  *
218  * @param dispatcher The dispatcher to connect.
219  */
220 void connect_dispatcher(dispatcher* dispatcher);
221 
222 /**
223  * Disconnects a dispatcher to the event handler.
224  *
225  * @param dispatcher The dispatcher to disconnect.
226  */
227 void disconnect_dispatcher(dispatcher* dispatcher);
228 
229 /**
230  * Gets all event dispatchers in the Z order.
231  */
232 std::vector<dispatcher*>& get_all_dispatchers();
233 
234 /**
235  * Initializes the location of the mouse.
236  *
237  * After a layout of the window the mouse location needs to be updated to
238  * test whether it entered or left a widget. Also after closing a window it's
239  * needed to send a dummy mouse move.
240  */
241 void init_mouse_location();
242 
243 /**
244  * Captures the mouse.
245  *
246  * A dispatcher can capture the mouse, when for example it's pressed on a
247  * button, this means all mouse events after that are send to that widget.
248  *
249  * @param dispatcher The dispatcher which should get the mouse
250  * focus.
251  */
252 void capture_mouse(dispatcher* dispatcher);
253 
254 /**
255  * Releases a captured mouse.
256  *
257  * @param dispatcher The dispatcher which should release the mouse
258  * capture.
259  */
260 void release_mouse(dispatcher* dispatcher);
261 
262 /**
263  * Captures the keyboard.
264  *
265  * A dispatcher can capture the keyboard, when for example it's pressed on a
266  * button, this means all keyboard events after that are send to that widget.
267  *
268  * @param dispatcher The dispatcher which should get the keyboard
269  * focus.
270  */
271 void capture_keyboard(dispatcher* dispatcher);
272 
273 std::ostream& operator<<(std::ostream& stream, const ui_event event);
274 
275 } // namespace event
276 
277 /**
278  * Is a dialog open?
279  *
280  * @note added as backwards compatibility for gui::is_in_dialog.
281  */
282 bool is_in_dialog();
283 
284 } // namespace gui2
ui_event
The event sent to the dispatcher.
Definition: handler.hpp:115
@ MIDDLE_BUTTON_DOWN
Definition: handler.hpp:124
@ SDL_FORWARD_BUTTON_DOWN
Definition: handler.hpp:156
@ NOTIFY_REMOVE_TOOLTIP
Definition: handler.hpp:176
@ FORWARD_BUTTON_DOUBLE_CLICK
Definition: handler.hpp:141
@ FORWARD_BUTTON_CLICK
Definition: handler.hpp:140
@ RIGHT_BUTTON_UP
Definition: handler.hpp:129
@ SDL_RIGHT_BUTTON_DOWN
Definition: handler.hpp:150
@ SDL_TOUCH_DOWN
Definition: handler.hpp:166
@ MIDDLE_BUTTON_DOUBLE_CLICK
Definition: handler.hpp:127
@ BACK_BUTTON_DOWN
Definition: handler.hpp:134
@ NOTIFY_MODIFIED
Definition: handler.hpp:175
@ FORWARD_BUTTON_DOWN
Definition: handler.hpp:138
@ BACK_BUTTON_CLICK
Definition: handler.hpp:136
@ MIDDLE_BUTTON_CLICK
Definition: handler.hpp:126
@ BACK_BUTTON_UP
Definition: handler.hpp:135
@ SDL_LEFT_BUTTON_DOWN
Definition: handler.hpp:146
@ SDL_TEXT_INPUT
An SDL text input (commit) event.
Definition: handler.hpp:170
@ SDL_WHEEL_DOWN
Definition: handler.hpp:162
@ 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:178
@ SDL_MOUSE_MOTION
Definition: handler.hpp:144
@ SDL_TEXT_EDITING
An SDL text editing (IME) event.
Definition: handler.hpp:171
@ LEFT_BUTTON_DOUBLE_CLICK
Definition: handler.hpp:123
@ RIGHT_BUTTON_DOWN
Definition: handler.hpp:128
@ NOTIFY_REMOVAL
Definition: handler.hpp:174
@ RECEIVE_KEYBOARD_FOCUS
Definition: handler.hpp:177
@ SDL_TOUCH_MOTION
Definition: handler.hpp:184
@ SDL_WHEEL_RIGHT
Definition: handler.hpp:160
@ SDL_VIDEO_RESIZE
Definition: handler.hpp:143
@ BACK_BUTTON_DOUBLE_CLICK
Definition: handler.hpp:137
@ LEFT_BUTTON_CLICK
Definition: handler.hpp:122
@ SDL_WHEEL_LEFT
Definition: handler.hpp:159
@ SDL_LEFT_BUTTON_UP
Definition: handler.hpp:147
@ SDL_TOUCH_MULTI_GESTURE
Definition: handler.hpp:185
@ REQUEST_PLACEMENT
Definition: handler.hpp:180
@ SDL_MIDDLE_BUTTON_UP
Definition: handler.hpp:149
@ SDL_BACK_BUTTON_DOWN
Definition: handler.hpp:154
@ SDL_BACK_BUTTON_UP
Definition: handler.hpp:155
@ FORWARD_BUTTON_UP
Definition: handler.hpp:139
@ LEFT_BUTTON_DOWN
Definition: handler.hpp:120
@ SDL_MIDDLE_BUTTON_DOWN
Definition: handler.hpp:148
@ SDL_RIGHT_BUTTON_UP
Definition: handler.hpp:151
@ RIGHT_BUTTON_DOUBLE_CLICK
Definition: handler.hpp:131
@ MESSAGE_SHOW_TOOLTIP
Definition: handler.hpp:181
@ MESSAGE_SHOW_HELPTIP
Definition: handler.hpp:182
@ SDL_FORWARD_BUTTON_UP
Definition: handler.hpp:157
constexpr event_category get_event_category(const ui_event event)
Returns the category of a given event.
Definition: handler.hpp:209
void capture_mouse(dispatcher *dispatcher)
Captures the mouse.
Definition: handler.cpp:906
void release_mouse(dispatcher *dispatcher)
Releases a captured mouse.
Definition: handler.cpp:913
void disconnect_dispatcher(dispatcher *dispatcher)
Disconnects a dispatcher to the event handler.
Definition: handler.cpp:880
void capture_keyboard(dispatcher *dispatcher)
Captures the keyboard.
Definition: handler.cpp:922
event_category
Event category masks.
Definition: handler.hpp:55
@ notification
Callbacks with a sender aka notification messages.
@ keyboard
Callbacks with the keyboard values (these haven't been determined yet).
@ mouse
Callbacks with a coordinate as extra parameter.
@ message
Callbacks with a sender aka notification messages.
@ general
Callbacks without extra parameters.
void connect_dispatcher(dispatcher *dispatcher)
Connects a dispatcher to the event handler.
Definition: handler.cpp:873
std::vector< dispatcher * > & get_all_dispatchers()
Gets all event dispatchers in the Z order.
Definition: handler.cpp:887
constexpr uint32_t encode_category(const uint32_t input, const event_category mask)
Definition: handler.hpp:96
std::ostream & operator<<(std::ostream &stream, const ui_event event)
Definition: handler.cpp:931
void init_mouse_location()
Initializes the location of the mouse.
Definition: handler.cpp:893
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:197
Generic file dialog.
bool is_in_dialog()
Is a dialog open?
Definition: handler.cpp:1122
The message callbacks hold a reference to a message.
Definition: message.hpp:46