CYD-UI
A C++ library for building native graphic user interfaces
Loading...
Searching...
No Matches
window_events.cppm
Go to the documentation of this file.
1
5module;
6#include <cyd_fabric_modules/headers/macros/async_events.h>
7#include <tracy/Tracy.hpp>
8#define SDL_MAIN_HANDLED
9#include <SDL3/SDL.h>
10
11export module cydui.window_events;
12
13import std;
14import reflect;
15import fabric.logging;
16
17import fabric.async;
18
19export import cydui.events;
20
21
22export namespace cydui {
23 EVENT(StopApplicationEvent){};
24}
25
27 std::unique_ptr<std::thread> thread_ptr{nullptr};
28 std::atomic_flag running{};
29
30 using window_map = std::map<std::size_t, fabric::async::async_bus_t*>;
31
32 struct {
33 std::unordered_map<std::size_t, std::pair<float, float>> accs{};
34
35 void reset() {
36 accs.clear();
37 }
38
39 void accumulate(const std::size_t bus_id, const float x, const float y) {
40 if (not accs.contains(bus_id)) {
41 accs[bus_id] = {x, y};
42 } else {
43 auto& [ax, ay] = accs.at(bus_id);
44 ax = x;
45 ay = y;
46 }
47 }
48
49 void dispatch(window_map* busses) {
50 auto bus = [&](std::size_t id, auto&& ev) {
51 if (busses->contains(id)) {
52 busses->at(id)->emit(ev);
53 return;
54 }
55 LOG::print{INFO}("Received event for window {}, but it does not exit", id);
56 };
57 for (const auto& [id, motion]: accs) {
58 bus(
59 id,
60 MotionEvent{
61 .x = motion.first,
62 .y = motion.second,
63 }
64 );
65 }
66 }
68
69 struct {
70 std::unordered_map<std::size_t, std::pair<float, float>> accs{};
71
72 void reset() {
73 accs.clear();
74 }
75
76 void accumulate(const std::size_t bus_id, const float w, const float h) {
77 if (not accs.contains(bus_id)) {
78 accs[bus_id] = {w, h};
79 } else {
80 auto& [aw, ah] = accs.at(bus_id);
81 aw = w;
82 ah = h;
83 }
84 }
85
86 void dispatch(window_map* busses) {
87 auto bus = [&](std::size_t id, auto&& ev) {
88 if (busses->contains(id)) {
89 busses->at(id)->emit(ev);
90 return;
91 }
92 LOG::print{INFO}("Received event for window {}, but it does not exit", id);
93 };
94 for (const auto& [id, size]: accs) {
95 bus(
96 id,
97 ResizeEvent{
98 .w = size.first,
99 .h = size.second,
100 }
101 );
102 }
103 }
105
106 struct {
107 std::unordered_set<std::size_t> accs{};
108
109 void reset() {
110 accs.clear();
111 }
112
113 void accumulate(const std::size_t bus_id) {
114 accs.insert(bus_id);
115 }
116
117 void dispatch(window_map* busses) {
118 auto bus = [&](std::size_t id, auto&& ev) {
119 if (busses->contains(id)) {
120 busses->at(id)->emit(ev);
121 return;
122 }
123 LOG::print{INFO}("Received event for window {}, but it does not exit", id);
124 };
125 for (const auto& id: accs) {
126 bus(id, RedrawEvent{});
127 }
128 }
130
131 void dispatch_window_event(window_map* busses, const SDL_WindowEvent& event) {
132 auto bus = [&](std::size_t id, auto&& ev) {
133 if (busses->contains(id)) {
134 busses->at(id)->emit(ev);
135 return;
136 }
137 LOG::print{INFO}("Received event for window {}, but it does not exit", id);
138 };
139
140 switch (event.type) {
141 case SDL_EVENT_WINDOW_RESIZED:
142 resize_accumulator.accumulate(event.windowID, event.data1, event.data2);
143 break;
144 case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
145 LOG::print{INFO}("Closing...");
146 bus(event.windowID, WindowClosed{});
147 break;
148 case SDL_EVENT_WINDOW_EXPOSED:
149 redraw_accumulator.accumulate(event.windowID);
150 break;
151 case SDL_EVENT_WINDOW_MOUSE_ENTER:
152 break;
153 case SDL_EVENT_WINDOW_MOUSE_LEAVE:
154 motion_accumulator.accumulate(event.windowID, -1, -1);
155 break;
156 default:
157 break;
158 }
159 }
160
161 void dispatch_display_event(window_map* busses, const SDL_DisplayEvent& event) {
162 auto bus = [&](std::size_t id, auto&& ev) {
163 if (busses->contains(id)) {
164 busses->at(id)->emit(ev);
165 return;
166 }
167 LOG::print{INFO}("Received event for window {}, but it does not exits", id);
168 };
169
170 switch (event.type) {
171 case SDL_EVENT_DISPLAY_ORIENTATION:
172 break;
173 case SDL_EVENT_DISPLAY_ADDED:
174 break;
175 case SDL_EVENT_DISPLAY_REMOVED:
176 break;
177 case SDL_EVENT_DISPLAY_MOVED:
178 break;
179 default:
180 break;
181 }
182 }
183
184 void
185 dispatch_event(fabric::async::async_bus_t* app_bus, window_map* busses, const SDL_Event& event) {
186 auto bus = [&](std::size_t id, auto&& ev) {
187 if (busses->contains(id)) {
188 busses->at(id)->emit(ev);
189 return;
190 }
191 LOG::print{INFO}("Received event for window {}, but it does not exits", id);
192 };
193
194 if (event.type >= SDL_EVENT_WINDOW_FIRST and event.type <= SDL_EVENT_WINDOW_LAST) {
195 dispatch_window_event(busses, event.window);
196 } else if (event.type >= SDL_EVENT_DISPLAY_FIRST and event.type <= SDL_EVENT_DISPLAY_LAST) {
197 dispatch_display_event(busses, event.display);
198 } else {
199 switch (event.type) {
200 case SDL_EVENT_QUIT:
201 app_bus->emit<StopApplicationEvent>();
202 break;
203 case SDL_EVENT_RENDER_TARGETS_RESET:
204 case SDL_EVENT_RENDER_DEVICE_RESET:
205 break;
206 case SDL_EVENT_MOUSE_BUTTON_DOWN:
207 case SDL_EVENT_MOUSE_BUTTON_UP:
208 bus(
209 event.button.windowID,
210 ButtonEvent{
211 .button = event.button.button,
212 .x = event.button.x,
213 .y = event.button.y,
214 .pressed = event.button.down,
215 .released = not event.button.down,
216 }
217 );
218 break;
219 case SDL_EVENT_MOUSE_WHEEL:
220 bus(
221 event.wheel.windowID,
222 ScrollEvent{
223 .dy = event.wheel.y * (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED ? -1 : 1),
224 .dx = event.wheel.x * (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED ? -1 : 1),
225 .x = event.wheel.mouse_x,
226 .y = event.wheel.mouse_y
227 }
228 );
229 break;
230 case SDL_EVENT_MOUSE_MOTION:
231 motion_accumulator.accumulate(event.motion.windowID, event.motion.x, event.motion.y);
232 break;
233 case SDL_EVENT_FINGER_DOWN:
234 case SDL_EVENT_FINGER_UP:
235 case SDL_EVENT_FINGER_MOTION:
236 break;
237 case SDL_EVENT_KEY_DOWN:
238 case SDL_EVENT_KEY_UP:
239 bus(
240 event.key.windowID,
241 KeyEvent{
242 .keysym =
243 {.scancode = event.key.scancode, .code = event.key.key, .mod = event.key.mod},
244 .pressed = event.key.down,
245 .released = not event.key.down,
246 }
247 );
248 break;
249 case SDL_EVENT_TEXT_INPUT:
250 bus(
251 event.text.windowID,
252 TextInputEvent{
253 .text = event.text.text,
254 }
255 );
256 break;
257 case SDL_EVENT_TEXT_EDITING:
258 bus(
259 event.edit.windowID,
260 TextInputEvent{
261 .text = std::string{event.edit.text, static_cast<std::size_t>(event.edit.length)},
262 .compositing_event = true,
263 .compositing_state =
264 {
265 .cursor = event.edit.start,
266 .selection = event.edit.length,
267 }
268 }
269 );
270 break;
271 case SDL_EVENT_TEXT_EDITING_CANDIDATES:
272 // TODO
273 // bus(
274 // event.edit_candidates.windowID,
275 // TextInputEvent{
276 // .text = std::string{event.edit_candidates.,
277 // static_cast<std::size_t>(event.edit.length)}, .compositing_event = true,
278 // .compositing_state =
279 // {
280 // .cursor = event.edit_candidates.start,
281 // .selection = event.edit_candidates.length,
282 // }
283 // }
284 // );
285 // SDL_free(event.editExt.text);
286 break;
287 case SDL_EVENT_KEYMAP_CHANGED:
288 break;
289 case SDL_EVENT_DROP_FILE:
290 case SDL_EVENT_DROP_TEXT:
291 case SDL_EVENT_DROP_BEGIN:
292 case SDL_EVENT_DROP_COMPLETE:
293 break;
294 default:
295 break;
296 }
297 }
298 }
299
300 void task(fabric::async::async_bus_t* app_bus, window_map* busses) {
301 ZoneScopedN("Polling events");
302 redraw_accumulator.reset();
303 motion_accumulator.reset();
304 resize_accumulator.reset();
305
306 SDL_Event event;
307 while (SDL_PollEvent(&event)) {
308 dispatch_event(app_bus, busses, event);
309 }
310
311 motion_accumulator.dispatch(busses);
312 resize_accumulator.dispatch(busses);
313 redraw_accumulator.dispatch(busses);
314 }
315} // namespace cydui::window_events
316
317export namespace cydui::window_events {
318 // void start_thread_if_needed() {
319 // thread::running.test_and_set();
320 // if (thread::thread_ptr == nullptr) {
321 // thread::thread_ptr = std::make_unique<std::thread>(thread::task);
322 // }
323 // }
324 //
325 void poll_events(fabric::async::async_bus_t* app_bus, window_map* busses) {
326 task(app_bus, busses);
327 }
328} // namespace cydui::window_events
EVENT(RedrawEvent)
struct cydui::window_events::@035333332202215202002017375212037336126054115201 resize_accumulator
std::unique_ptr< std::thread > thread_ptr
void poll_events(fabric::async::async_bus_t *app_bus, window_map *busses)
std::unordered_map< std::size_t, std::pair< float, float > > accs
void dispatch_event(fabric::async::async_bus_t *app_bus, window_map *busses, const SDL_Event &event)
void task(fabric::async::async_bus_t *app_bus, window_map *busses)
void dispatch_display_event(window_map *busses, const SDL_DisplayEvent &event)
struct cydui::window_events::@266353315245074326133023264262255003163310363211 redraw_accumulator
std::map< std::size_t, fabric::async::async_bus_t * > window_map
std::atomic_flag running
void dispatch_window_event(window_map *busses, const SDL_WindowEvent &event)
struct cydui::window_events::@356047141260151102366262332324033273277246122305 motion_accumulator