MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
WindowEventSource.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "EventSource.hpp"
4
7
8#include <deque>
9
10namespace MayaFlux::Kriya {
11class WindowEventAwaiter;
12}
13
14namespace MayaFlux::Vruta {
15
16// =============================================================================
17// EventFilter
18// =============================================================================
19
20/**
21 * @struct WindowEventFilter
22 * @brief Filter criteria for window input events.
23 *
24 * Multiple criteria are ANDed. An empty filter matches any event.
25 */
26struct MAYAFLUX_API WindowEventFilter : public EventFilter {
27 std::optional<Core::WindowEventType> event_type;
28 std::optional<IO::Keys> key_code;
29 std::optional<IO::MouseButtons> button;
30
31 WindowEventFilter() = default;
32
33 /**
34 * @brief Constructs a filter matching a specific event type.
35 * @param type Event type to match.
36 */
38 : event_type(type)
39 {
40 }
41
42 /**
43 * @brief Constructs a filter matching a specific key.
44 * @param key Key to match.
45 */
47 : key_code(key)
48 {
49 }
50};
51
52// =============================================================================
53// WindowEventSource
54// =============================================================================
55
56/**
57 * @class WindowEventSource
58 * @brief Awaitable stream of window input events.
59 *
60 * Signals are produced by the window backend's poll(), on the polling thread. Coroutines
61 * suspend via WindowEventAwaiter and are resumed synchronously from signal().
62 * Every suspended awaiter whose filter matches receives the event, in registration
63 * order. An event no awaiter took is queued until one arrives, up to
64 * k_max_pending_events per event type; beyond that the oldest queued event of
65 * the same type is dropped, so a flood of one type never evicts another.
66 * Tracks input state for immediate polling via is_key_pressed(),
67 * is_mouse_pressed(), and get_mouse_position().
68 *
69 * @see EventSource
70 * @see WindowEventAwaiter
71 * @see EventFilter
72 */
73class MAYAFLUX_API WindowEventSource : public EventSource {
74public:
75 /// @brief Most events of one type held for a later awaiter before the oldest of that type is dropped.
76 static constexpr size_t k_max_pending_events = 1024;
77
78 WindowEventSource() = default;
79 ~WindowEventSource() override = default;
80
83 WindowEventSource(WindowEventSource&&) noexcept = default;
84 WindowEventSource& operator=(WindowEventSource&&) noexcept = default;
85
86 /**
87 * @brief Enqueue a window event and resume matching waiters.
88 * @param event Event produced by the window backend.
89 *
90 * Updates input state caches before dispatching.
91 */
92 void signal(Core::WindowEvent event);
93
94 /**
95 * @brief Run an action after the active outermost window-event dispatch.
96 * @param action Action to run after event waiters, or immediately when
97 * the source is idle.
98 */
99 void defer(std::function<void()> action);
100
101 /**
102 * @brief Creates an awaiter that resumes on the next event of any type.
103 */
104 Kriya::WindowEventAwaiter next_event();
105
106 /**
107 * @brief Creates an awaiter that resumes on the next event matching a type.
108 * @param type Event type to wait for.
109 */
110 Kriya::WindowEventAwaiter await_event(Core::WindowEventType type);
111
112 [[nodiscard]] bool has_pending() const override { return !m_pending_events.empty(); }
113 [[nodiscard]] size_t pending_count() const { return m_pending_events.size(); }
114 void clear() override
115 {
116 m_pending_events.clear();
117 m_pending_counts.fill(0);
118 }
119
120 /**
121 * @brief Returns true if the given key is currently held.
122 * @param key Key to query.
123 */
124 [[nodiscard]] bool is_key_pressed(IO::Keys key) const;
125
126 /**
127 * @brief Returns true if the given mouse button is currently held.
128 * @param button Button index.
129 */
130 [[nodiscard]] bool is_mouse_pressed(int button) const;
131
132 /**
133 * @brief Returns the last known cursor position in screen coordinates.
134 */
135 [[nodiscard]] std::pair<double, double> get_mouse_position() const;
136
137private:
138 std::deque<Core::WindowEvent> m_pending_events;
139 std::array<size_t, 256> m_pending_counts {};
140 std::unordered_map<int16_t, bool> m_key_states;
141 std::unordered_map<int, bool> m_button_states;
142 double m_mouse_x {};
143 double m_mouse_y {};
144 std::vector<std::function<void()>> m_deferred_actions;
145 size_t m_signal_depth {};
146 size_t m_resumed {};
147
148 /**
149 * @brief Removes and returns the first pending event matching the filter.
150 * @param filter Filter criteria.
151 */
152 std::optional<Core::WindowEvent> pop_event(const WindowEventFilter& filter);
153
155};
156
157} // namespace MayaFlux::Vruta
vk::PhysicalDeviceType type
Definition VKDevice.cpp:126
Awaiter for suspending on window input events with optional filtering.
Base for event filters used by EventSources to match signals to awaiters.
Abstract base for all awaitable signal sources.
WindowEventSource & operator=(const WindowEventSource &)=delete
WindowEventSource(WindowEventSource &&) noexcept=default
std::unordered_map< int16_t, bool > m_key_states
void clear() override
Discards all buffered signals.
std::vector< std::function< void()> > m_deferred_actions
std::deque< Core::WindowEvent > m_pending_events
~WindowEventSource() override=default
WindowEventSource(const WindowEventSource &)=delete
std::unordered_map< int, bool > m_button_states
Awaitable stream of window input events.
WindowEventType
Types of window and input events.
std::optional< Core::WindowEventType > event_type
WindowEventFilter(Core::WindowEventType type)
Constructs a filter matching a specific event type.
WindowEventFilter(IO::Keys key)
Constructs a filter matching a specific key.
std::optional< IO::MouseButtons > button
Filter criteria for window input events.