MayaFlux 1.0.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.
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 void request_close() override;
49
50 [[nodiscard]] const WindowState& get_state() const override { return m_state; }
51 [[nodiscard]] const WindowCreateInfo& get_create_info() const override { return m_create_info; }
52
53 void set_input_config(const InputConfig& config) override { m_input_config = config; }
54 [[nodiscard]] const InputConfig& get_input_config() const override { return m_input_config; }
55
56 void set_event_callback(WindowEventCallback callback) override;
57
58 [[nodiscard]] void* get_native_handle() const override;
59 [[nodiscard]] void* get_native_display() const override;
60
61 void set_title(const std::string& title) override;
62 void set_size(uint32_t width, uint32_t height) override;
63 void set_position(uint32_t x, uint32_t y) override;
64 void set_color(const std::array<float, 4>& color) override;
65
66 Vruta::WindowEventSource& get_event_source() override { return m_event_source; }
67 [[nodiscard]] const Vruta::WindowEventSource& get_event_source() const override { return m_event_source; }
68
69 [[nodiscard]] bool is_graphics_registered() const override { return m_graphics_registered.load(); }
70 void set_graphics_registered(bool registered) override { m_graphics_registered.store(registered); }
71
72 void register_rendering_buffer(std::shared_ptr<Buffers::VKBuffer> buffer) override;
73 void unregister_rendering_buffer(std::shared_ptr<Buffers::VKBuffer> buffer) override;
74 void track_frame_command(uint64_t cmd_id) override;
75 [[nodiscard]] const std::vector<uint64_t>& get_frame_commands() const override;
76 void clear_frame_commands() override;
77 [[nodiscard]] std::vector<std::shared_ptr<Buffers::VKBuffer>> get_rendering_buffers() const override;
78
79 [[nodiscard]] bool is_capture_enabled() const override { return m_capture_enabled.load(std::memory_order_acquire); }
80 void set_capture_enabled(bool enabled) override { m_capture_enabled.store(enabled, std::memory_order_release); }
81
82private:
83 // -------------------------------------------------------------------------
84 // Wayland globals
85 // -------------------------------------------------------------------------
86 wl_display* m_display {};
87 wl_registry* m_registry {};
88 wl_compositor* m_compositor {};
89 wl_seat* m_seat {};
90 xdg_wm_base* m_xdg_wm_base {};
91 zxdg_decoration_manager_v1* m_decoration_manager {};
92
93 // -------------------------------------------------------------------------
94 // Per-window objects
95 // -------------------------------------------------------------------------
96 wl_surface* m_surface {};
97 xdg_surface* m_xdg_surface {};
98 xdg_toplevel* m_xdg_toplevel {};
99 zxdg_toplevel_decoration_v1* m_decoration {};
100
101 // -------------------------------------------------------------------------
102 // Input
103 // -------------------------------------------------------------------------
104 wl_pointer* m_pointer {};
105 wl_keyboard* m_keyboard {};
106
107 xkb_context* m_xkb_context {};
108 xkb_keymap* m_xkb_keymap {};
109 xkb_state* m_xkb_state {};
110
111 double m_pointer_x {};
112 double m_pointer_y {};
113
114 int m_repeat_fd { -1 };
115 int m_text_repeat_fd { -1 };
116 std::unordered_map<int16_t, WindowEvent::KeyData> m_held_keys;
117 std::optional<std::pair<int16_t, uint32_t>> m_active_text_key;
118
119 // -------------------------------------------------------------------------
120 // Window state
121 // -------------------------------------------------------------------------
122
123 KeyRepeatConfig m_key_repeat_config;
124 WindowCreateInfo m_create_info;
125 WindowState m_state;
126 InputConfig m_input_config;
127 WindowEventCallback m_event_callback;
128 Vruta::WindowEventSource m_event_source;
129
130 std::atomic<bool> m_should_close { false };
131 std::atomic<bool> m_graphics_registered { false };
132 std::atomic<bool> m_pending_configure { false };
133 bool m_resizing { false };
134 std::atomic<bool> m_capture_enabled { false };
135 uint32_t m_pending_width {};
136 uint32_t m_pending_height {};
137
138 // -------------------------------------------------------------------------
139 // Render tracking
140 // -------------------------------------------------------------------------
141 mutable std::mutex m_render_tracking_mutex;
142 std::vector<std::weak_ptr<Buffers::VKBuffer>> m_rendering_buffers;
143 std::vector<uint64_t> m_frame_commands;
144
145 // -------------------------------------------------------------------------
146 // Internal helpers
147 // -------------------------------------------------------------------------
148
149 /** @brief Signal an event through both the event source and the callback. */
150 void emit(const WindowEvent& ev);
151
152 /** @brief Log the display error, mark the window closed, emit WINDOW_CLOSED once. */
153 void handle_display_error();
154
155 // -------------------------------------------------------------------------
156 // Registry listener (static trampoline + instance handler)
157 // -------------------------------------------------------------------------
158 static void on_registry_global(void* data, wl_registry*, uint32_t name,
159 const char* iface, uint32_t version);
160 static void on_registry_global_remove(void* data, wl_registry*, uint32_t name);
161 static constexpr wl_registry_listener s_registry_listener {
162 .global = on_registry_global,
163 .global_remove = on_registry_global_remove,
164 };
165
166 // -------------------------------------------------------------------------
167 // xdg_wm_base listener
168 // -------------------------------------------------------------------------
169 static void on_wm_base_ping(void* data, xdg_wm_base*, uint32_t serial);
170 static constexpr xdg_wm_base_listener s_wm_base_listener {
171 .ping = on_wm_base_ping,
172 };
173
174 // -------------------------------------------------------------------------
175 // xdg_surface listener
176 // -------------------------------------------------------------------------
177 static void on_xdg_surface_configure(void* data, xdg_surface*, uint32_t serial);
178 static constexpr xdg_surface_listener s_xdg_surface_listener {
179 .configure = on_xdg_surface_configure,
180 };
181
182 // -------------------------------------------------------------------------
183 // xdg_toplevel listener
184 // -------------------------------------------------------------------------
185 static void on_toplevel_configure(void* data, xdg_toplevel*,
186 int32_t w, int32_t h, wl_array* states);
187
188 static void on_toplevel_close(void* data, xdg_toplevel*);
189
190 static void on_toplevel_configure_bounds(void* data, xdg_toplevel*,
191 int32_t w, int32_t h);
192
193 static void on_toplevel_wm_capabilities(void* data, xdg_toplevel*,
194 wl_array* capabilities);
195
196 static constexpr xdg_toplevel_listener s_toplevel_listener {
197 .configure = on_toplevel_configure,
198 .close = on_toplevel_close,
199 .configure_bounds = on_toplevel_configure_bounds,
200 .wm_capabilities = on_toplevel_wm_capabilities,
201 };
202
203 // -------------------------------------------------------------------------
204 // wl_seat listener
205 // -------------------------------------------------------------------------
206 static void on_seat_capabilities(void* data, wl_seat*, uint32_t caps);
207 static void on_seat_name(void* data, wl_seat*, const char* name);
208 static constexpr wl_seat_listener s_seat_listener {
209 .capabilities = on_seat_capabilities,
210 .name = on_seat_name,
211 };
212
213 // -------------------------------------------------------------------------
214 // wl_keyboard listener
215 // -------------------------------------------------------------------------
216 static void on_keyboard_keymap(void* data, wl_keyboard*,
217 uint32_t fmt, int fd, uint32_t size);
218 static void on_keyboard_enter(void* data, wl_keyboard*,
219 uint32_t serial, wl_surface*, wl_array* keys);
220 static void on_keyboard_leave(void* data, wl_keyboard*,
221 uint32_t serial, wl_surface*);
222 static void on_keyboard_key(void* data, wl_keyboard*,
223 uint32_t serial, uint32_t time, uint32_t key, uint32_t state);
224 static void on_keyboard_modifiers(void* data, wl_keyboard*,
225 uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
226 uint32_t mods_locked, uint32_t group);
227 static void on_keyboard_repeat_info(void* data, wl_keyboard*,
228 int32_t rate, int32_t delay);
229 static constexpr wl_keyboard_listener s_keyboard_listener {
230 .keymap = on_keyboard_keymap,
231 .enter = on_keyboard_enter,
232 .leave = on_keyboard_leave,
233 .key = on_keyboard_key,
234 .modifiers = on_keyboard_modifiers,
235 .repeat_info = on_keyboard_repeat_info,
236 };
237
238 // -------------------------------------------------------------------------
239 // wl_pointer listener
240 // -------------------------------------------------------------------------
241 static void on_pointer_enter(void* data, wl_pointer*,
242 uint32_t serial, wl_surface*, wl_fixed_t sx, wl_fixed_t sy);
243 static void on_pointer_leave(void* data, wl_pointer*,
244 uint32_t serial, wl_surface*);
245 static void on_pointer_motion(void* data, wl_pointer*,
246 uint32_t time, wl_fixed_t sx, wl_fixed_t sy);
247 static void on_pointer_button(void* data, wl_pointer*,
248 uint32_t serial, uint32_t time, uint32_t button, uint32_t state);
249 static void on_pointer_axis(void* data, wl_pointer*,
250 uint32_t time, uint32_t axis, wl_fixed_t value);
251 static void on_pointer_frame(void* data, wl_pointer*);
252 static void on_pointer_axis_source(void* data, wl_pointer*, uint32_t source);
253 static void on_pointer_axis_stop(void* data, wl_pointer*, uint32_t time, uint32_t axis);
254 static void on_pointer_axis_discrete(void* data, wl_pointer*, uint32_t axis, int32_t discrete);
255 static constexpr wl_pointer_listener s_pointer_listener {
256 .enter = on_pointer_enter,
257 .leave = on_pointer_leave,
258 .motion = on_pointer_motion,
259 .button = on_pointer_button,
260 .axis = on_pointer_axis,
261 .frame = on_pointer_frame,
262 .axis_source = on_pointer_axis_source,
263 .axis_stop = on_pointer_axis_stop,
264 .axis_discrete = on_pointer_axis_discrete,
265 };
266};
267
268} // namespace MayaFlux::Core
269
270#endif // MAYAFLUX_PLATFORM_LINUX
glm::vec3 color
Definition Decoder.cpp:97
bool size
float rate
uint32_t h
Definition InkPress.cpp:29
std::shared_ptr< NetworkGeometryBuffer > buffer
PickCallback callback
Definition Picker.cpp:22
glm::vec3 value
std::string name
Definition VKDevice.cpp:123
uint32_t width
uint32_t height
std::function< void(const WindowEvent &)> WindowEventCallback
void destroy(Surface &surface, uint32_t id)
Tear down an element and everything related to it.
Definition Forma.cpp:90