MayaFlux 0.5.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 /** @brief Log the display error, mark the window closed, emit WINDOW_CLOSED once. */
149 void handle_display_error();
150
151 // -------------------------------------------------------------------------
152 // Registry listener (static trampoline + instance handler)
153 // -------------------------------------------------------------------------
154 static void on_registry_global(void* data, wl_registry*, uint32_t name,
155 const char* iface, uint32_t version);
156 static void on_registry_global_remove(void* data, wl_registry*, uint32_t name);
157 static constexpr wl_registry_listener s_registry_listener {
158 .global = on_registry_global,
159 .global_remove = on_registry_global_remove,
160 };
161
162 // -------------------------------------------------------------------------
163 // xdg_wm_base listener
164 // -------------------------------------------------------------------------
165 static void on_wm_base_ping(void* data, xdg_wm_base*, uint32_t serial);
166 static constexpr xdg_wm_base_listener s_wm_base_listener {
167 .ping = on_wm_base_ping,
168 };
169
170 // -------------------------------------------------------------------------
171 // xdg_surface listener
172 // -------------------------------------------------------------------------
173 static void on_xdg_surface_configure(void* data, xdg_surface*, uint32_t serial);
174 static constexpr xdg_surface_listener s_xdg_surface_listener {
175 .configure = on_xdg_surface_configure,
176 };
177
178 // -------------------------------------------------------------------------
179 // xdg_toplevel listener
180 // -------------------------------------------------------------------------
181 static void on_toplevel_configure(void* data, xdg_toplevel*,
182 int32_t w, int32_t h, wl_array* states);
183
184 static void on_toplevel_close(void* data, xdg_toplevel*);
185
186 static void on_toplevel_configure_bounds(void* data, xdg_toplevel*,
187 int32_t w, int32_t h);
188
189 static void on_toplevel_wm_capabilities(void* data, xdg_toplevel*,
190 wl_array* capabilities);
191
192 static constexpr xdg_toplevel_listener s_toplevel_listener {
193 .configure = on_toplevel_configure,
194 .close = on_toplevel_close,
195 .configure_bounds = on_toplevel_configure_bounds,
196 .wm_capabilities = on_toplevel_wm_capabilities,
197 };
198
199 // -------------------------------------------------------------------------
200 // wl_seat listener
201 // -------------------------------------------------------------------------
202 static void on_seat_capabilities(void* data, wl_seat*, uint32_t caps);
203 static void on_seat_name(void* data, wl_seat*, const char* name);
204 static constexpr wl_seat_listener s_seat_listener {
205 .capabilities = on_seat_capabilities,
206 .name = on_seat_name,
207 };
208
209 // -------------------------------------------------------------------------
210 // wl_keyboard listener
211 // -------------------------------------------------------------------------
212 static void on_keyboard_keymap(void* data, wl_keyboard*,
213 uint32_t fmt, int fd, uint32_t size);
214 static void on_keyboard_enter(void* data, wl_keyboard*,
215 uint32_t serial, wl_surface*, wl_array* keys);
216 static void on_keyboard_leave(void* data, wl_keyboard*,
217 uint32_t serial, wl_surface*);
218 static void on_keyboard_key(void* data, wl_keyboard*,
219 uint32_t serial, uint32_t time, uint32_t key, uint32_t state);
220 static void on_keyboard_modifiers(void* data, wl_keyboard*,
221 uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
222 uint32_t mods_locked, uint32_t group);
223 static void on_keyboard_repeat_info(void* data, wl_keyboard*,
224 int32_t rate, int32_t delay);
225 static constexpr wl_keyboard_listener s_keyboard_listener {
226 .keymap = on_keyboard_keymap,
227 .enter = on_keyboard_enter,
228 .leave = on_keyboard_leave,
229 .key = on_keyboard_key,
230 .modifiers = on_keyboard_modifiers,
231 .repeat_info = on_keyboard_repeat_info,
232 };
233
234 // -------------------------------------------------------------------------
235 // wl_pointer listener
236 // -------------------------------------------------------------------------
237 static void on_pointer_enter(void* data, wl_pointer*,
238 uint32_t serial, wl_surface*, wl_fixed_t sx, wl_fixed_t sy);
239 static void on_pointer_leave(void* data, wl_pointer*,
240 uint32_t serial, wl_surface*);
241 static void on_pointer_motion(void* data, wl_pointer*,
242 uint32_t time, wl_fixed_t sx, wl_fixed_t sy);
243 static void on_pointer_button(void* data, wl_pointer*,
244 uint32_t serial, uint32_t time, uint32_t button, uint32_t state);
245 static void on_pointer_axis(void* data, wl_pointer*,
246 uint32_t time, uint32_t axis, wl_fixed_t value);
247 static void on_pointer_frame(void* data, wl_pointer*);
248 static void on_pointer_axis_source(void* data, wl_pointer*, uint32_t source);
249 static void on_pointer_axis_stop(void* data, wl_pointer*, uint32_t time, uint32_t axis);
250 static void on_pointer_axis_discrete(void* data, wl_pointer*, uint32_t axis, int32_t discrete);
251 static constexpr wl_pointer_listener s_pointer_listener {
252 .enter = on_pointer_enter,
253 .leave = on_pointer_leave,
254 .motion = on_pointer_motion,
255 .button = on_pointer_button,
256 .axis = on_pointer_axis,
257 .frame = on_pointer_frame,
258 .axis_source = on_pointer_axis_source,
259 .axis_stop = on_pointer_axis_stop,
260 .axis_discrete = on_pointer_axis_discrete,
261 };
262};
263
264} // namespace MayaFlux::Core
265
266#endif // MAYAFLUX_PLATFORM_LINUX
float rate
uint32_t h
Definition InkPress.cpp:28
std::string name
Definition VKDevice.cpp:143
float value
uint32_t width
uint32_t height
std::function< void(const WindowEvent &)> WindowEventCallback