MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
WaylandWindow.hpp
Go to the documentation of this file.
1#pragma once
2
3#ifdef MAYAFLUX_PLATFORM_LINUX
4
7
8#include <wayland-client.h>
9#include <xkbcommon/xkbcommon.h>
10
11#include "wayland-xdg-decoration-unstable-v1-client-protocol.h"
12#include "wayland-xdg-shell-client-protocol.h"
13
14namespace MayaFlux::Core {
15
16/**
17 * @class WaylandWindow
18 * @brief Native Wayland window backend, no GLFW dependency.
19 *
20 * Connects directly to the Wayland compositor via wl_display. Keyboard
21 * translation uses xkbcommon with the keymap supplied by the compositor
22 * over the wl_keyboard::keymap event fd. poll() calls
23 * wl_display_dispatch_pending + wl_display_flush synchronously on the
24 * graphics thread; no dedicated UI thread is required because all Wayland
25 * callbacks fire on the thread that calls wl_display_dispatch_pending.
26 *
27 * WindowManager::process() calls poll() on each WaylandWindow directly,
28 * matching the Win32 pattern.
29 */
30class MAYAFLUX_API WaylandWindow : public Window {
31public:
32 WaylandWindow(const WindowCreateInfo& create_info,
33 const GlobalGraphicsConfig& graphics_config);
34
35 ~WaylandWindow() override;
36
37 WaylandWindow(const WaylandWindow&) = delete;
38 WaylandWindow& operator=(const WaylandWindow&) = delete;
39 WaylandWindow(WaylandWindow&&) = delete;
40 WaylandWindow& operator=(WaylandWindow&&) = delete;
41
42 void show() override;
43 void hide() override;
44 void destroy() override;
45 void poll() override;
46
47 [[nodiscard]] bool should_close() const override;
48
49 [[nodiscard]] const WindowState& get_state() const override { return m_state; }
50 [[nodiscard]] const WindowCreateInfo& get_create_info() const override { return m_create_info; }
51
52 void set_input_config(const InputConfig& config) override { m_input_config = config; }
53 [[nodiscard]] const InputConfig& get_input_config() const override { return m_input_config; }
54
55 void set_event_callback(WindowEventCallback callback) override;
56
57 [[nodiscard]] void* get_native_handle() const override;
58 [[nodiscard]] void* get_native_display() const override;
59
60 void set_title(const std::string& title) override;
61 void set_size(uint32_t width, uint32_t height) override;
62 void set_position(uint32_t x, uint32_t y) override;
63 void set_color(const std::array<float, 4>& color) override;
64
65 Vruta::WindowEventSource& get_event_source() override { return m_event_source; }
66 [[nodiscard]] const Vruta::WindowEventSource& get_event_source() const override { return m_event_source; }
67
68 [[nodiscard]] bool is_graphics_registered() const override { return m_graphics_registered.load(); }
69 void set_graphics_registered(bool registered) override { m_graphics_registered.store(registered); }
70
71 void register_rendering_buffer(std::shared_ptr<Buffers::VKBuffer> buffer) override;
72 void unregister_rendering_buffer(std::shared_ptr<Buffers::VKBuffer> buffer) override;
73 void track_frame_command(uint64_t cmd_id) override;
74 [[nodiscard]] const std::vector<uint64_t>& get_frame_commands() const override;
75 void clear_frame_commands() override;
76 [[nodiscard]] std::vector<std::shared_ptr<Buffers::VKBuffer>> get_rendering_buffers() const override;
77
78 [[nodiscard]] bool is_capture_enabled() const override { return m_capture_enabled.load(std::memory_order_acquire); }
79 void set_capture_enabled(bool enabled) override { m_capture_enabled.store(enabled, std::memory_order_release); }
80
81private:
82 // -------------------------------------------------------------------------
83 // Wayland globals
84 // -------------------------------------------------------------------------
85 wl_display* m_display {};
86 wl_registry* m_registry {};
87 wl_compositor* m_compositor {};
88 wl_seat* m_seat {};
89 xdg_wm_base* m_xdg_wm_base {};
90 zxdg_decoration_manager_v1* m_decoration_manager {};
91
92 // -------------------------------------------------------------------------
93 // Per-window objects
94 // -------------------------------------------------------------------------
95 wl_surface* m_surface {};
96 xdg_surface* m_xdg_surface {};
97 xdg_toplevel* m_xdg_toplevel {};
98 zxdg_toplevel_decoration_v1* m_decoration {};
99
100 // -------------------------------------------------------------------------
101 // Input
102 // -------------------------------------------------------------------------
103 wl_pointer* m_pointer {};
104 wl_keyboard* m_keyboard {};
105
106 xkb_context* m_xkb_context {};
107 xkb_keymap* m_xkb_keymap {};
108 xkb_state* m_xkb_state {};
109
110 double m_pointer_x {};
111 double m_pointer_y {};
112
113 int m_repeat_fd { -1 };
114 std::unordered_map<int16_t, WindowEvent::KeyData> m_held_keys;
115
116 // -------------------------------------------------------------------------
117 // Window state
118 // -------------------------------------------------------------------------
119
120 KeyRepeatConfig m_key_repeat_config;
121 WindowCreateInfo m_create_info;
122 WindowState m_state;
123 InputConfig m_input_config;
124 WindowEventCallback m_event_callback;
125 Vruta::WindowEventSource m_event_source;
126
127 std::atomic<bool> m_should_close { false };
128 std::atomic<bool> m_graphics_registered { false };
129 std::atomic<bool> m_pending_configure { false };
130 std::atomic<bool> m_capture_enabled { false };
131 uint32_t m_pending_width {};
132 uint32_t m_pending_height {};
133
134 // -------------------------------------------------------------------------
135 // Render tracking
136 // -------------------------------------------------------------------------
137 mutable std::mutex m_render_tracking_mutex;
138 std::vector<std::weak_ptr<Buffers::VKBuffer>> m_rendering_buffers;
139 std::vector<uint64_t> m_frame_commands;
140
141 // -------------------------------------------------------------------------
142 // Internal helpers
143 // -------------------------------------------------------------------------
144
145 /** @brief Signal an event through both the event source and the callback. */
146 void emit(const WindowEvent& ev);
147
148 // -------------------------------------------------------------------------
149 // Registry listener (static trampoline + instance handler)
150 // -------------------------------------------------------------------------
151 static void on_registry_global(void* data, wl_registry*, uint32_t name,
152 const char* iface, uint32_t version);
153 static void on_registry_global_remove(void* data, wl_registry*, uint32_t name);
154 static constexpr wl_registry_listener s_registry_listener {
155 .global = on_registry_global,
156 .global_remove = on_registry_global_remove,
157 };
158
159 // -------------------------------------------------------------------------
160 // xdg_wm_base listener
161 // -------------------------------------------------------------------------
162 static void on_wm_base_ping(void* data, xdg_wm_base*, uint32_t serial);
163 static constexpr xdg_wm_base_listener s_wm_base_listener {
164 .ping = on_wm_base_ping,
165 };
166
167 // -------------------------------------------------------------------------
168 // xdg_surface listener
169 // -------------------------------------------------------------------------
170 static void on_xdg_surface_configure(void* data, xdg_surface*, uint32_t serial);
171 static constexpr xdg_surface_listener s_xdg_surface_listener {
172 .configure = on_xdg_surface_configure,
173 };
174
175 // -------------------------------------------------------------------------
176 // xdg_toplevel listener
177 // -------------------------------------------------------------------------
178 static void on_toplevel_configure(void* data, xdg_toplevel*,
179 int32_t w, int32_t h, wl_array* states);
180
181 static void on_toplevel_close(void* data, xdg_toplevel*);
182
183 static void on_toplevel_configure_bounds(void* data, xdg_toplevel*,
184 int32_t w, int32_t h);
185
186 static void on_toplevel_wm_capabilities(void* data, xdg_toplevel*,
187 wl_array* capabilities);
188
189 static constexpr xdg_toplevel_listener s_toplevel_listener {
190 .configure = on_toplevel_configure,
191 .close = on_toplevel_close,
192 .configure_bounds = on_toplevel_configure_bounds,
193 .wm_capabilities = on_toplevel_wm_capabilities,
194 };
195
196 // -------------------------------------------------------------------------
197 // wl_seat listener
198 // -------------------------------------------------------------------------
199 static void on_seat_capabilities(void* data, wl_seat*, uint32_t caps);
200 static void on_seat_name(void* data, wl_seat*, const char* name);
201 static constexpr wl_seat_listener s_seat_listener {
202 .capabilities = on_seat_capabilities,
203 .name = on_seat_name,
204 };
205
206 // -------------------------------------------------------------------------
207 // wl_keyboard listener
208 // -------------------------------------------------------------------------
209 static void on_keyboard_keymap(void* data, wl_keyboard*,
210 uint32_t fmt, int fd, uint32_t size);
211 static void on_keyboard_enter(void* data, wl_keyboard*,
212 uint32_t serial, wl_surface*, wl_array* keys);
213 static void on_keyboard_leave(void* data, wl_keyboard*,
214 uint32_t serial, wl_surface*);
215 static void on_keyboard_key(void* data, wl_keyboard*,
216 uint32_t serial, uint32_t time, uint32_t key, uint32_t state);
217 static void on_keyboard_modifiers(void* data, wl_keyboard*,
218 uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
219 uint32_t mods_locked, uint32_t group);
220 static void on_keyboard_repeat_info(void* data, wl_keyboard*,
221 int32_t rate, int32_t delay);
222 static constexpr wl_keyboard_listener s_keyboard_listener {
223 .keymap = on_keyboard_keymap,
224 .enter = on_keyboard_enter,
225 .leave = on_keyboard_leave,
226 .key = on_keyboard_key,
227 .modifiers = on_keyboard_modifiers,
228 .repeat_info = on_keyboard_repeat_info,
229 };
230
231 // -------------------------------------------------------------------------
232 // wl_pointer listener
233 // -------------------------------------------------------------------------
234 static void on_pointer_enter(void* data, wl_pointer*,
235 uint32_t serial, wl_surface*, wl_fixed_t sx, wl_fixed_t sy);
236 static void on_pointer_leave(void* data, wl_pointer*,
237 uint32_t serial, wl_surface*);
238 static void on_pointer_motion(void* data, wl_pointer*,
239 uint32_t time, wl_fixed_t sx, wl_fixed_t sy);
240 static void on_pointer_button(void* data, wl_pointer*,
241 uint32_t serial, uint32_t time, uint32_t button, uint32_t state);
242 static void on_pointer_axis(void* data, wl_pointer*,
243 uint32_t time, uint32_t axis, wl_fixed_t value);
244 static void on_pointer_frame(void* data, wl_pointer*);
245 static void on_pointer_axis_source(void* data, wl_pointer*, uint32_t source);
246 static void on_pointer_axis_stop(void* data, wl_pointer*, uint32_t time, uint32_t axis);
247 static void on_pointer_axis_discrete(void* data, wl_pointer*, uint32_t axis, int32_t discrete);
248 static constexpr wl_pointer_listener s_pointer_listener {
249 .enter = on_pointer_enter,
250 .leave = on_pointer_leave,
251 .motion = on_pointer_motion,
252 .button = on_pointer_button,
253 .axis = on_pointer_axis,
254 .frame = on_pointer_frame,
255 .axis_source = on_pointer_axis_source,
256 .axis_stop = on_pointer_axis_stop,
257 .axis_discrete = on_pointer_axis_discrete,
258 };
259};
260
261} // namespace MayaFlux::Core
262
263#endif // MAYAFLUX_PLATFORM_LINUX
uint32_t width
Definition Decoder.cpp:59
uint32_t h
Definition InkPress.cpp:28
std::function< void(const WindowEvent &)> WindowEventCallback