GUI2/Dispatcher: encode event categories in their enum values (#6621)

This commit is contained in:
Charles Dang 2022-04-10 17:56:27 -04:00 committed by GitHub
parent a76aa9bddc
commit 65d8c201a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 162 additions and 239 deletions

View file

@ -68,7 +68,7 @@ bool dispatcher::has_event(const ui_event event, const event_queue_type event_ty
bool dispatcher::fire(const ui_event event, widget& target)
{
assert(is_general_event(event));
assert(is_in_category(event, event_category::general));
switch(event) {
case LEFT_BUTTON_DOUBLE_CLICK:
return fire_event_double_click<LEFT_BUTTON_CLICK, LEFT_BUTTON_DOUBLE_CLICK,
@ -89,7 +89,7 @@ bool dispatcher::fire(const ui_event event, widget& target)
bool dispatcher::fire(const ui_event event, widget& target, const point& coordinate)
{
assert(is_mouse_event(event));
assert(is_in_category(event, event_category::mouse));
return fire_event<signal_mouse_function>(event, this, &target, coordinate);
}
@ -99,43 +99,43 @@ bool dispatcher::fire(const ui_event event,
const SDL_Keymod modifier,
const std::string& unicode)
{
assert(is_keyboard_event(event));
assert(is_in_category(event, event_category::keyboard));
return fire_event<signal_keyboard_function>(event, this, &target, key, modifier, unicode);
}
bool dispatcher::fire(const ui_event event, widget& target, const point& pos, const point& distance)
{
assert(is_touch_motion_event(event));
assert(is_in_category(event, event_category::touch_motion));
return fire_event<signal_touch_motion_function>(event, this, &target, pos, distance);
}
bool dispatcher::fire(const ui_event event, widget& target, const point& center, float dTheta, float dDist, uint8_t numFingers)
{
assert(is_touch_gesture_event(event));
assert(is_in_category(event, event_category::touch_gesture));
return fire_event<signal_touch_gesture_function>(event, this, &target, center, dTheta, dDist, numFingers);
}
bool dispatcher::fire(const ui_event event, widget& target, const SDL_Event& sdlevent)
{
assert(is_raw_event_event(event));
assert(is_in_category(event, event_category::raw_event));
return fire_event<signal_raw_event_function>(event, this, &target, sdlevent);
}
bool dispatcher::fire(const ui_event event, widget& target, const std::string& text, int32_t start, int32_t len)
{
assert(is_text_input_event(event));
assert(is_in_category(event, event_category::text_input));
return fire_event<signal_text_input_function>(event, this, &target, text, start, len);
}
bool dispatcher::fire(const ui_event event, widget& target, void*)
{
assert(is_notification_event(event));
assert(is_in_category(event, event_category::notification));
return fire_event<signal_notification_function>(event, this, &target, nullptr);
}
bool dispatcher::fire(const ui_event event, widget& target, const message& msg)
{
assert(is_message_event(event));
assert(is_in_category(event, event_category::message));
return fire_event<signal_message_function>(event, this, &target, msg);
}

View file

@ -35,146 +35,6 @@ class widget;
namespace event
{
/**
* Helper for catching use error of @ref dispatcher::connect_signal.
*
* This helper is needed as a user can't supply the wrong kind of callback
* functions to dispatcher::connect_signal. If a wrong callback would be send
* it will never get called.
*
* This version is for callbacks without extra parameters.
* NOTE some mouse functions like MOUSE_ENTER don't send the mouse coordinates
* to the callback function so they are also in this category.
*/
constexpr bool is_general_event(const ui_event event)
{
return event == DRAW
|| event == CLOSE_WINDOW
|| event == MOUSE_ENTER
|| event == MOUSE_LEAVE
|| event == LEFT_BUTTON_DOWN
|| event == LEFT_BUTTON_UP
|| event == LEFT_BUTTON_CLICK
|| event == LEFT_BUTTON_DOUBLE_CLICK
|| event == MIDDLE_BUTTON_DOWN
|| event == MIDDLE_BUTTON_UP
|| event == MIDDLE_BUTTON_CLICK
|| event == MIDDLE_BUTTON_DOUBLE_CLICK
|| event == RIGHT_BUTTON_DOWN
|| event == RIGHT_BUTTON_UP
|| event == RIGHT_BUTTON_CLICK
|| event == RIGHT_BUTTON_DOUBLE_CLICK;
}
/**
* Helper for catching use error of @ref dispatcher::connect_signal.
*
* This version is for callbacks with a coordinate as extra parameter.
*/
constexpr bool is_mouse_event(const ui_event event)
{
return event == SDL_VIDEO_RESIZE
|| event == SDL_MOUSE_MOTION
|| event == MOUSE_MOTION
|| event == SDL_LEFT_BUTTON_DOWN
|| event == SDL_LEFT_BUTTON_UP
|| event == SDL_MIDDLE_BUTTON_DOWN
|| event == SDL_MIDDLE_BUTTON_UP
|| event == SDL_RIGHT_BUTTON_DOWN
|| event == SDL_RIGHT_BUTTON_UP
|| event == SHOW_TOOLTIP
|| event == SHOW_HELPTIP
|| event == SDL_WHEEL_UP
|| event == SDL_WHEEL_DOWN
|| event == SDL_WHEEL_LEFT
|| event == SDL_WHEEL_RIGHT
|| event == SDL_TOUCH_UP
|| event == SDL_TOUCH_DOWN;
}
/**
* Helper for catching use error of @ref dispatcher::connect_signal.
*
* This version is for callbacks with the keyboard values (these haven't been
* determined yet).
*/
constexpr bool is_keyboard_event(const ui_event event)
{
return event == SDL_KEY_DOWN;
}
/**
* Helper for catching use error of @ref dispatcher::connect_signal.
*
* This version is for callbacks of touch motion events.
*/
constexpr bool is_touch_motion_event(const ui_event event)
{
return event == SDL_TOUCH_MOTION;
}
/**
* Helper for catching use error of @ref dispatcher::connect_signal.
*
* This version is for callbacks of touch gesture events.
*/
constexpr bool is_touch_gesture_event(const ui_event event)
{
return event == SDL_TOUCH_MULTI_GESTURE;
}
/**
* Helper for catching use error of @ref dispatcher::connect_signal.
*
* This version is for callbacks with a sender aka notification messages. Like the
* ones in set_event it has no extra parameters, but this version is only
* send to the target and not using the pre and post queue.
*/
constexpr bool is_notification_event(const ui_event event)
{
return event == NOTIFY_REMOVAL
|| event == NOTIFY_MODIFIED
|| event == RECEIVE_KEYBOARD_FOCUS
|| event == LOSE_KEYBOARD_FOCUS
|| event == NOTIFY_REMOVE_TOOLTIP
|| event == SDL_ACTIVATE;
}
/**
* Helper for catching use error of @ref dispatcher::connect_signal.
*
* This version is for callbacks with a sender aka notification messages.
* Unlike the notifications this message is send through the chain. The event
* is send from a widget all the way up to the window, who always is the
* receiver of the message (unless somebody grabbed it before).
*/
constexpr bool is_message_event(const ui_event event)
{
return event == MESSAGE_SHOW_TOOLTIP
|| event == MESSAGE_SHOW_HELPTIP
|| event == REQUEST_PLACEMENT;
}
/**
* Helper for catching use error of @ref dispatcher::connect_signal.
*
* This version is for callbacks of raw events.
*/
constexpr bool is_raw_event_event(const ui_event event)
{
return event == SDL_RAW_EVENT;
}
/**
* Helper for catching use error of @ref dispatcher::connect_signal.
*
* This version is for callbacks of text input events.
*/
constexpr bool is_text_input_event(const ui_event event)
{
return event == SDL_TEXT_INPUT || event == SDL_TEXT_EDITING;
}
struct message;
/**
@ -195,14 +55,14 @@ using dispatcher_callback_func = std::function<void(widget&, const ui_event, boo
/**
* Callback function signature.
*
* This is used for events matching @ref is_general_event.
* This is used for events in event_category::general.
*/
using signal_function = dispatcher_callback_func<>;
/**
* Callback function signature.
*
* This is used for events matching @ref is_mouse_event.
* This is used for events in event_category::mouse.
*
* Extra parameters:
* 5. The x,y coordinate of the mouse when this event is fired.
@ -212,7 +72,7 @@ using signal_mouse_function = dispatcher_callback_func<const point&>;
/**
* Callback function signature.
*
* This is used for events matching @ref is_keyboard_event.
* This is used for events in event_category::keyboard.
*
* Extra parameters:
* 5. The keycode of the key that triggered this event.
@ -224,7 +84,7 @@ using signal_keyboard_function = dispatcher_callback_func<const SDL_Keycode, con
/**
* Callback function signature.
*
* This is used for events matching @ref is_touch_motion_event.
* This is used for events in event_category::touch_motion.
*
* Extra parameters:
* 5. Origin of the touch event, in x,y format.
@ -235,7 +95,7 @@ using signal_touch_motion_function = dispatcher_callback_func<const point&, cons
/**
* Callback function signature.
*
* This is used for events matching @ref is_touch_gesture_event.
* This is used for events in event_category::touch_gesture.
*
* Extra parameters: (TODO: document what these actually are)
* 5. center
@ -248,7 +108,7 @@ using signal_touch_gesture_function = dispatcher_callback_func<const point&, flo
/**
* Callback function signature.
*
* This is used for events matching @ref is_notification_event.
* This is used for events in event_category::notification.
*
* Extra parameters:
* 5. A dummy void* parameter which will always be nullptr, used to differentiate
@ -259,7 +119,7 @@ using signal_notification_function = dispatcher_callback_func<void*>;
/**
* Callback function signature.
*
* This is used for events matching @ref is_message_event.
* This is used for events in event_category::message.
*
* Extra parameters:
* 5. The applicable data this event requires.
@ -269,7 +129,7 @@ using signal_message_function = dispatcher_callback_func<const message&>;
/**
* Raw event callback function signature.
*
* This is used for events matching @ref is_raw_event_event.
* This is used for events in event_category::raw_event.
*
* Extra parameters:
* 5. The raw SDL_Event.
@ -279,7 +139,7 @@ using signal_raw_event_function = dispatcher_callback_func<const SDL_Event&>;
/**
* Callback function signature.
*
* This is used for events matching @ref is_text_input_event.
* This is used for eventsin event_category::text_input.
*
* Extra parameters:
* 5. The text entered.
@ -507,23 +367,23 @@ public:
template<ui_event E, typename F>
void connect_signal(const F& func, const queue_position position = back_child)
{
if constexpr(is_general_event(E)) {
if constexpr(is_in_category(E, event_category::general)) {
VALIDATE_AND_ADD_TO_QUEUE(signal)
} else if constexpr(is_mouse_event(E)) {
} else if constexpr(is_in_category(E, event_category::mouse)) {
VALIDATE_AND_ADD_TO_QUEUE(signal_mouse)
} else if constexpr(is_keyboard_event(E)) {
} else if constexpr(is_in_category(E, event_category::keyboard)) {
VALIDATE_AND_ADD_TO_QUEUE(signal_keyboard)
} else if constexpr(is_touch_motion_event(E)) {
} else if constexpr(is_in_category(E, event_category::touch_motion)) {
VALIDATE_AND_ADD_TO_QUEUE(signal_touch_motion)
} else if constexpr(is_touch_gesture_event(E)) {
} else if constexpr(is_in_category(E, event_category::touch_gesture)) {
VALIDATE_AND_ADD_TO_QUEUE(signal_touch_gesture)
} else if constexpr(is_notification_event(E)) {
} else if constexpr(is_in_category(E, event_category::notification)) {
VALIDATE_AND_ADD_TO_QUEUE(signal_notification)
} else if constexpr(is_message_event(E)) {
} else if constexpr(is_in_category(E, event_category::message)) {
VALIDATE_AND_ADD_TO_QUEUE(signal_message)
} else if constexpr(is_raw_event_event(E)) {
} else if constexpr(is_in_category(E, event_category::raw_event)) {
VALIDATE_AND_ADD_TO_QUEUE(signal_raw_event)
} else if constexpr(is_text_input_event(E)) {
} else if constexpr(is_in_category(E, event_category::text_input)) {
VALIDATE_AND_ADD_TO_QUEUE(signal_text_input)
} else {
static_assert(utils::dependent_false_v<E>, "No matching signal queue found for event");
@ -551,23 +411,23 @@ public:
template<ui_event E, typename F>
void disconnect_signal(const F& func, const queue_position position = back_child)
{
if constexpr(is_general_event(E)) {
if constexpr(is_in_category(E, event_category::general)) {
VALIDATE_AND_REMOVE_FROM_QUEUE(signal)
} else if constexpr(is_mouse_event(E)) {
} else if constexpr(is_in_category(E, event_category::mouse)) {
VALIDATE_AND_REMOVE_FROM_QUEUE(signal_mouse)
} else if constexpr(is_keyboard_event(E)) {
} else if constexpr(is_in_category(E, event_category::keyboard)) {
VALIDATE_AND_REMOVE_FROM_QUEUE(signal_keyboard)
} else if constexpr(is_touch_motion_event(E)) {
} else if constexpr(is_in_category(E, event_category::touch_motion)) {
VALIDATE_AND_REMOVE_FROM_QUEUE(signal_touch_motion)
} else if constexpr(is_touch_gesture_event(E)) {
} else if constexpr(is_in_category(E, event_category::touch_gesture)) {
VALIDATE_AND_REMOVE_FROM_QUEUE(signal_touch_gesture)
} else if constexpr(is_notification_event(E)) {
} else if constexpr(is_in_category(E, event_category::notification)) {
VALIDATE_AND_REMOVE_FROM_QUEUE(signal_notification)
} else if constexpr(is_message_event(E)) {
} else if constexpr(is_in_category(E, event_category::message)) {
VALIDATE_AND_REMOVE_FROM_QUEUE(signal_message)
} else if constexpr(is_raw_event_event(E)) {
} else if constexpr(is_in_category(E, event_category::raw_event)) {
VALIDATE_AND_REMOVE_FROM_QUEUE(signal_raw_event)
} else if constexpr(is_text_input_event(E)) {
} else if constexpr(is_in_category(E, event_category::text_input)) {
VALIDATE_AND_REMOVE_FROM_QUEUE(signal_text_input)
} else {
static_assert(utils::dependent_false_v<E>, "No matching signal queue found for event");

View file

@ -66,7 +66,7 @@ struct dispatcher_implementation
#undef FUNCTION_QUEUE_CHECK
#define RUNTIME_EVENT_SIGNAL_CHECK(TYPE) \
else if(is_##TYPE##_event(event)) { \
else if(is_in_category(event, event_category::TYPE)) { \
return queue_check(dispatcher.signal_##TYPE##_queue_); \
}
@ -85,7 +85,7 @@ struct dispatcher_implementation
return !queue_set.queue[event].empty(queue_type);
};
if(is_general_event(event)) {
if(is_in_category(event, event_category::general)) {
return queue_check(dispatcher.signal_queue_);
}

View file

@ -15,6 +15,7 @@
#pragma once
#include <cstdint>
#include <iosfwd>
#include <vector>
@ -34,7 +35,68 @@ public:
};
/**
* The event send to the dispatcher.
* Event category masks.
*
* These begin at 2^8 to allow for 8 bits for the event identifiers themselves.
* This means ui_event can have up to 256 unique members. Since each mask needs
* its own place value, we can have 24 categories since ui_event's underlying
* type is 32 bits:
*
* USABLE CATEGORY BITS NULL
* |------------------------|--------|
* MASK 000000000000000000000000 00000000
*
* ENCODED CATEGORY EVENT
* |------------------------|--------|
* UI_EVENT 000000000000000000000000 00000000
*/
enum class event_category : uint32_t {
/**
* Callbacks without extra parameters.
* @note Some mouse events like MOUSE_ENTER don't send the mouse coordinates
* to the callback function so they are also in this category.
*/
general = 1u << 8,
/**
* Callbacks with a coordinate as extra parameter.
*/
mouse = 1u << 9,
/**
* Callbacks with the keyboard values (these haven't been determined yet).
*/
keyboard = 1u << 10,
touch_motion = 1u << 11,
touch_gesture = 1u << 12,
/**
* Callbacks with a sender aka notification messages. Like general events
* it has no extra parameters, but this version is only sent to the target
* and does not use the pre and post queue.
*/
notification = 1u << 13,
/**
* Callbacks with a sender aka notification messages.
* Unlike the notifications this message is send through the chain. The event
* is sent from a widget all the way up to the window, who is always the
* receiver of the message (unless somebody grabbed it before).
*/
message = 1u << 14,
raw_event = 1u << 15,
text_input = 1u << 16,
};
constexpr uint32_t encode_category(const uint32_t input, const event_category mask)
{
return input | static_cast<uint32_t>(mask);
}
/**
* The event sent to the dispatcher.
*
* Events prefixed by SDL are (semi)-real SDL events. The handler does some
* minor decoding like splitting the button down event to the proper event but
@ -45,75 +107,76 @@ public:
*
* @note When adding a new entry to the enum also add a unit test.
*/
enum ui_event {
SDL_ACTIVATE, /**< The main application window is activated. */
DRAW, /**< Periodic redraw request. */
CLOSE_WINDOW, /**< A request to close the current window. */
SDL_VIDEO_RESIZE, /**< An SDL resize request, coordinate is the new window size. */
enum ui_event : uint32_t {
DRAW = encode_category(1 , event_category::general),
CLOSE_WINDOW = encode_category(2 , event_category::general),
MOUSE_ENTER = encode_category(3 , event_category::general),
MOUSE_LEAVE = encode_category(4 , event_category::general),
LEFT_BUTTON_DOWN = encode_category(5 , event_category::general),
LEFT_BUTTON_UP = encode_category(6 , event_category::general),
LEFT_BUTTON_CLICK = encode_category(7 , event_category::general),
LEFT_BUTTON_DOUBLE_CLICK = encode_category(8 , event_category::general),
MIDDLE_BUTTON_DOWN = encode_category(9 , event_category::general),
MIDDLE_BUTTON_UP = encode_category(10, event_category::general),
MIDDLE_BUTTON_CLICK = encode_category(11, event_category::general),
MIDDLE_BUTTON_DOUBLE_CLICK = encode_category(12, event_category::general),
RIGHT_BUTTON_DOWN = encode_category(13, event_category::general),
RIGHT_BUTTON_UP = encode_category(14, event_category::general),
RIGHT_BUTTON_CLICK = encode_category(15, event_category::general),
RIGHT_BUTTON_DOUBLE_CLICK = encode_category(16, event_category::general),
SDL_MOUSE_MOTION, /**< An SDL mouse motion event. */
MOUSE_ENTER, /**< A mouse enter event for a widget. */
MOUSE_MOTION, /**< A mouse motion event for a widget. */
MOUSE_LEAVE, /**< A mouse leave event for a widget. */
SDL_VIDEO_RESIZE = encode_category(17, event_category::mouse),
SDL_MOUSE_MOTION = encode_category(18, event_category::mouse),
MOUSE_MOTION = encode_category(19, event_category::mouse),
SDL_LEFT_BUTTON_DOWN = encode_category(20, event_category::mouse),
SDL_LEFT_BUTTON_UP = encode_category(21, event_category::mouse),
SDL_MIDDLE_BUTTON_DOWN = encode_category(22, event_category::mouse),
SDL_MIDDLE_BUTTON_UP = encode_category(23, event_category::mouse),
SDL_RIGHT_BUTTON_DOWN = encode_category(24, event_category::mouse),
SDL_RIGHT_BUTTON_UP = encode_category(25, event_category::mouse),
SDL_WHEEL_LEFT = encode_category(26, event_category::mouse),
SDL_WHEEL_RIGHT = encode_category(27, event_category::mouse),
SDL_WHEEL_UP = encode_category(28, event_category::mouse),
SDL_WHEEL_DOWN = encode_category(29, event_category::mouse),
SHOW_TOOLTIP = encode_category(30, event_category::mouse),
SHOW_HELPTIP = encode_category(31, event_category::mouse),
SDL_TOUCH_UP = encode_category(32, event_category::mouse),
SDL_TOUCH_DOWN = encode_category(33, event_category::mouse),
SDL_LEFT_BUTTON_DOWN, /**< An SDL left mouse button down event. */
SDL_LEFT_BUTTON_UP, /**< An SDL left mouse button up event. */
LEFT_BUTTON_DOWN, /**< A left mouse button down event for a widget. */
LEFT_BUTTON_UP, /**< A left mouse button up event for a widget. */
LEFT_BUTTON_CLICK, /**< A left mouse button click event for a widget. */
LEFT_BUTTON_DOUBLE_CLICK, /**< A left mouse button double click event for a widget. */
SDL_KEY_DOWN = encode_category(34, event_category::keyboard),
SDL_MIDDLE_BUTTON_DOWN, /**< An SDL middle mouse button down event. */
SDL_MIDDLE_BUTTON_UP, /**< An SDL middle mouse button up event. */
MIDDLE_BUTTON_DOWN, /**< See LEFT_BUTTON_DOWN. */
MIDDLE_BUTTON_UP, /**< See LEFT_BUTTON_UP. */
MIDDLE_BUTTON_CLICK, /**< See LEFT_BUTTON_CLICK. */
MIDDLE_BUTTON_DOUBLE_CLICK, /**< See LEFT_BUTTON_DOUBLE_CLICK. */
SDL_TEXT_INPUT = encode_category(35, event_category::text_input), /**< An SDL text input (commit) event. */
SDL_TEXT_EDITING = encode_category(36, event_category::text_input), /**< An SDL text editing (IME) event. */
SDL_RIGHT_BUTTON_DOWN, /**< An SDL right mouse button down event. */
SDL_RIGHT_BUTTON_UP, /**< An SDL right mouse button up event. */
RIGHT_BUTTON_DOWN, /**< See LEFT_BUTTON_DOWN. */
RIGHT_BUTTON_UP, /**< See LEFT_BUTTON_UP. */
RIGHT_BUTTON_CLICK, /**< See LEFT_BUTTON_CLICK. */
RIGHT_BUTTON_DOUBLE_CLICK, /**< See LEFT_BUTTON_DOUBLE_CLICK. */
SDL_ACTIVATE = encode_category(37, event_category::notification),
NOTIFY_REMOVAL = encode_category(38, event_category::notification),
NOTIFY_MODIFIED = encode_category(39, event_category::notification),
NOTIFY_REMOVE_TOOLTIP = encode_category(40, event_category::notification),
RECEIVE_KEYBOARD_FOCUS = encode_category(41, event_category::notification),
LOSE_KEYBOARD_FOCUS = encode_category(42, event_category::notification),
SDL_WHEEL_LEFT, /**< An SDL wheel left event. */
SDL_WHEEL_RIGHT, /**< An SDL wheel right event. */
SDL_WHEEL_UP, /**< An SDL wheel up event. */
SDL_WHEEL_DOWN, /**< An SDL wheel down event. */
SDL_KEY_DOWN, /**< An SDL key down event. */
SDL_TEXT_INPUT, /**< An SDL text input (commit) event. */
SDL_TEXT_EDITING, /**< An SDL text editing (IME) event. */
REQUEST_PLACEMENT = encode_category(43, event_category::message),
MESSAGE_SHOW_TOOLTIP = encode_category(44, event_category::message),
MESSAGE_SHOW_HELPTIP = encode_category(45, event_category::message),
NOTIFY_REMOVAL, /**< Sent by a widget to notify others it's being destroyed. */
NOTIFY_MODIFIED, /**<
* Sent by a widget to notify others its contents or state are modified.
*
* What modified means is documented per widget. If not documented the request
* means nothing.
*/
REQUEST_PLACEMENT, /**<
* Request to place the widget. This may also trigger an update of other
* layout components.
*/
SDL_TOUCH_MOTION = encode_category(46, event_category::touch_motion),
SDL_TOUCH_MULTI_GESTURE = encode_category(47, event_category::touch_gesture),
RECEIVE_KEYBOARD_FOCUS, /**< Widget gains keyboard focus. */
LOSE_KEYBOARD_FOCUS, /**< Widget loses keyboard focus. */
SHOW_TOOLTIP, /**< Request the widget to show its hover tooltip. */
NOTIFY_REMOVE_TOOLTIP, /**< Request the widget to remove its hover tooltip. */
MESSAGE_SHOW_TOOLTIP, /**< Request to show a tooltip based on the data sent. */
SHOW_HELPTIP, /**< Request the widget to show its hover helptip. */
MESSAGE_SHOW_HELPTIP, /**< Request to show a helptip based on the data sent. */
SDL_TOUCH_MOTION,
SDL_TOUCH_UP,
SDL_TOUCH_DOWN,
SDL_TOUCH_MULTI_GESTURE,
SDL_RAW_EVENT /**< Raw SDL event. */
SDL_RAW_EVENT = encode_category(48, event_category::raw_event)
};
constexpr bool is_in_category(const ui_event event, const event_category mask)
{
const uint32_t asu32 = static_cast<uint32_t>(mask);
return (event & asu32) == asu32;
}
constexpr event_category get_event_category(const ui_event event)
{
// Zero-out the first 8 bits since those encode the ui_event value, which we don't want.
return static_cast<event_category>((event >> 8u) << 8u);
}
/**
* Connects a dispatcher to the event handler.
*