Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/platform/linuxbsd/wayland/wayland_thread.h
10278 views
1
/**************************************************************************/
2
/* wayland_thread.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#pragma once
32
33
#ifdef WAYLAND_ENABLED
34
35
#include "key_mapping_xkb.h"
36
37
#ifdef SOWRAP_ENABLED
38
#include "wayland/dynwrappers/wayland-client-core-so_wrap.h"
39
#include "wayland/dynwrappers/wayland-cursor-so_wrap.h"
40
#include "wayland/dynwrappers/wayland-egl-core-so_wrap.h"
41
#include "xkbcommon-so_wrap.h"
42
#else
43
#include <wayland-client-core.h>
44
#include <wayland-cursor.h>
45
#ifdef GLES3_ENABLED
46
#include <wayland-egl-core.h>
47
#endif
48
#include <xkbcommon/xkbcommon.h>
49
#endif // SOWRAP_ENABLED
50
51
// These must go after the Wayland client include to work properly.
52
#include "wayland/protocol/idle_inhibit.gen.h"
53
#include "wayland/protocol/primary_selection.gen.h"
54
// These four protocol headers name wl_pointer method arguments as `pointer`,
55
// which is the same name as X11's pointer typedef. This trips some very
56
// annoying shadowing warnings. A `#define` works around this issue.
57
#define pointer wl_pointer
58
#include "wayland/protocol/cursor_shape.gen.h"
59
#include "wayland/protocol/pointer_constraints.gen.h"
60
#include "wayland/protocol/pointer_gestures.gen.h"
61
#include "wayland/protocol/relative_pointer.gen.h"
62
#undef pointer
63
#include "wayland/protocol/fractional_scale.gen.h"
64
#include "wayland/protocol/tablet.gen.h"
65
#include "wayland/protocol/text_input.gen.h"
66
#include "wayland/protocol/viewporter.gen.h"
67
#include "wayland/protocol/wayland.gen.h"
68
#include "wayland/protocol/xdg_activation.gen.h"
69
#include "wayland/protocol/xdg_decoration.gen.h"
70
#include "wayland/protocol/xdg_foreign_v2.gen.h"
71
#include "wayland/protocol/xdg_shell.gen.h"
72
#include "wayland/protocol/xdg_system_bell.gen.h"
73
74
// NOTE: Deprecated.
75
#include "wayland/protocol/xdg_foreign_v1.gen.h"
76
77
#ifdef LIBDECOR_ENABLED
78
#ifdef SOWRAP_ENABLED
79
#include "dynwrappers/libdecor-so_wrap.h"
80
#else
81
#include <libdecor.h>
82
#endif // SOWRAP_ENABLED
83
#endif // LIBDECOR_ENABLED
84
85
#include "core/os/thread.h"
86
#include "servers/display_server.h"
87
88
class WaylandThread {
89
public:
90
// Messages used for exchanging information between Godot's and Wayland's thread.
91
class Message : public RefCounted {
92
GDSOFTCLASS(Message, RefCounted);
93
94
public:
95
Message() {}
96
virtual ~Message() = default;
97
};
98
99
class WindowMessage : public Message {
100
GDSOFTCLASS(WindowMessage, Message);
101
102
public:
103
DisplayServer::WindowID id = DisplayServer::INVALID_WINDOW_ID;
104
};
105
106
// Message data for window rect changes.
107
class WindowRectMessage : public WindowMessage {
108
GDSOFTCLASS(WindowRectMessage, WindowMessage);
109
110
public:
111
// NOTE: This is in "scaled" terms. For example, if there's a 1920x1080 rect
112
// with a scale factor of 2, the actual value of `rect` will be 3840x2160.
113
Rect2i rect;
114
};
115
116
class WindowEventMessage : public WindowMessage {
117
GDSOFTCLASS(WindowEventMessage, WindowMessage);
118
119
public:
120
DisplayServer::WindowEvent event;
121
};
122
123
class InputEventMessage : public Message {
124
GDSOFTCLASS(InputEventMessage, Message);
125
126
public:
127
Ref<InputEvent> event;
128
};
129
130
class DropFilesEventMessage : public WindowMessage {
131
GDSOFTCLASS(DropFilesEventMessage, WindowMessage);
132
133
public:
134
Vector<String> files;
135
};
136
137
class IMEUpdateEventMessage : public WindowMessage {
138
GDSOFTCLASS(IMEUpdateEventMessage, WindowMessage);
139
140
public:
141
String text;
142
Vector2i selection;
143
};
144
145
class IMECommitEventMessage : public WindowMessage {
146
GDSOFTCLASS(IMECommitEventMessage, WindowMessage);
147
148
public:
149
String text;
150
};
151
152
struct RegistryState {
153
WaylandThread *wayland_thread;
154
155
// Core Wayland globals.
156
struct wl_shm *wl_shm = nullptr;
157
uint32_t wl_shm_name = 0;
158
159
struct wl_compositor *wl_compositor = nullptr;
160
uint32_t wl_compositor_name = 0;
161
162
struct wl_subcompositor *wl_subcompositor = nullptr;
163
uint32_t wl_subcompositor_name = 0;
164
165
struct wl_data_device_manager *wl_data_device_manager = nullptr;
166
uint32_t wl_data_device_manager_name = 0;
167
168
List<struct wl_output *> wl_outputs;
169
List<struct wl_seat *> wl_seats;
170
171
// xdg-shell globals.
172
173
struct xdg_wm_base *xdg_wm_base = nullptr;
174
uint32_t xdg_wm_base_name = 0;
175
176
// NOTE: Deprecated.
177
struct zxdg_exporter_v1 *xdg_exporter_v1 = nullptr;
178
uint32_t xdg_exporter_v1_name = 0;
179
180
uint32_t xdg_exporter_v2_name = 0;
181
struct zxdg_exporter_v2 *xdg_exporter_v2 = nullptr;
182
183
// wayland-protocols globals.
184
185
struct wp_viewporter *wp_viewporter = nullptr;
186
uint32_t wp_viewporter_name = 0;
187
188
struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager = nullptr;
189
uint32_t wp_fractional_scale_manager_name = 0;
190
191
struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager = nullptr;
192
uint32_t wp_cursor_shape_manager_name = 0;
193
194
struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr;
195
uint32_t xdg_decoration_manager_name = 0;
196
197
struct xdg_system_bell_v1 *xdg_system_bell = nullptr;
198
uint32_t xdg_system_bell_name = 0;
199
200
struct xdg_activation_v1 *xdg_activation = nullptr;
201
uint32_t xdg_activation_name = 0;
202
203
struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr;
204
uint32_t wp_primary_selection_device_manager_name = 0;
205
206
struct zwp_relative_pointer_manager_v1 *wp_relative_pointer_manager = nullptr;
207
uint32_t wp_relative_pointer_manager_name = 0;
208
209
struct zwp_pointer_constraints_v1 *wp_pointer_constraints = nullptr;
210
uint32_t wp_pointer_constraints_name = 0;
211
212
struct zwp_pointer_gestures_v1 *wp_pointer_gestures = nullptr;
213
uint32_t wp_pointer_gestures_name = 0;
214
215
struct zwp_idle_inhibit_manager_v1 *wp_idle_inhibit_manager = nullptr;
216
uint32_t wp_idle_inhibit_manager_name = 0;
217
218
struct zwp_tablet_manager_v2 *wp_tablet_manager = nullptr;
219
uint32_t wp_tablet_manager_name = 0;
220
221
struct zwp_text_input_manager_v3 *wp_text_input_manager = nullptr;
222
uint32_t wp_text_input_manager_name = 0;
223
224
// We're really not meant to use this one directly but we still need to know
225
// whether it's available.
226
uint32_t wp_fifo_manager_name = 0;
227
};
228
229
// General Wayland-specific states. Shouldn't be accessed directly.
230
// TODO: Make private?
231
232
struct WindowState {
233
DisplayServer::WindowID id = DisplayServer::INVALID_WINDOW_ID;
234
DisplayServer::WindowID parent_id = DisplayServer::INVALID_WINDOW_ID;
235
236
Rect2i rect;
237
DisplayServer::WindowMode mode = DisplayServer::WINDOW_MODE_WINDOWED;
238
bool suspended = false;
239
240
// These are true by default as it isn't guaranteed that we'll find an
241
// xdg-shell implementation with wm_capabilities available. If and once we
242
// receive a wm_capabilities event these will get reset and updated with
243
// whatever the compositor says.
244
bool can_minimize = false;
245
bool can_maximize = false;
246
bool can_fullscreen = false;
247
248
HashSet<struct wl_output *> wl_outputs;
249
250
// NOTE: If for whatever reason this callback is destroyed _while_ the event
251
// thread is still running, it might be a good idea to set its user data to
252
// `nullptr`. From some initial testing of mine, it looks like it might still
253
// be called even after being destroyed, pointing to probably invalid window
254
// data by then and segfaulting hard.
255
struct wl_callback *frame_callback = nullptr;
256
uint64_t last_frame_time = 0;
257
258
struct wl_surface *wl_surface = nullptr;
259
struct xdg_surface *xdg_surface = nullptr;
260
struct xdg_toplevel *xdg_toplevel = nullptr;
261
262
struct wp_viewport *wp_viewport = nullptr;
263
struct wp_fractional_scale_v1 *wp_fractional_scale = nullptr;
264
265
// NOTE: Deprecated.
266
struct zxdg_exported_v1 *xdg_exported_v1 = nullptr;
267
268
struct zxdg_exported_v2 *xdg_exported_v2 = nullptr;
269
270
struct xdg_popup *xdg_popup = nullptr;
271
272
String exported_handle;
273
274
// Currently applied buffer scale.
275
int buffer_scale = 1;
276
277
// Buffer scale must be applied right before rendering but _after_ committing
278
// everything else or otherwise we might have an inconsistent state (e.g.
279
// double scale and odd resolution). This flag assists with that; when set,
280
// on the next frame, we'll commit whatever is set in `buffer_scale`.
281
bool buffer_scale_changed = false;
282
283
// NOTE: The preferred buffer scale is currently only dynamically calculated.
284
// It can be accessed by calling `window_state_get_preferred_buffer_scale`.
285
286
// Override used by the fractional scale add-on object. If less or equal to 0
287
// (default) then the normal output-based scale is used instead.
288
double fractional_scale = 0;
289
290
// What the compositor is recommending us.
291
double preferred_fractional_scale = 0;
292
293
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration = nullptr;
294
295
struct zwp_idle_inhibitor_v1 *wp_idle_inhibitor = nullptr;
296
297
#ifdef LIBDECOR_ENABLED
298
// If this is null the xdg_* variables must be set and vice-versa. This way we
299
// can handle this mess gracefully enough to hopefully being able of getting
300
// rid of this cleanly once we have our own CSDs.
301
struct libdecor_frame *libdecor_frame = nullptr;
302
struct libdecor_configuration *pending_libdecor_configuration = nullptr;
303
#endif
304
305
RegistryState *registry;
306
WaylandThread *wayland_thread;
307
};
308
309
// "High level" Godot-side screen data.
310
struct ScreenData {
311
// Geometry data.
312
Point2i position;
313
314
String make;
315
String model;
316
317
Size2i size;
318
Size2i physical_size;
319
320
float refresh_rate = -1;
321
int scale = 1;
322
};
323
324
struct ScreenState {
325
uint32_t wl_output_name = 0;
326
327
ScreenData pending_data;
328
ScreenData data;
329
330
WaylandThread *wayland_thread;
331
};
332
333
enum class Gesture {
334
NONE,
335
MAGNIFY,
336
};
337
338
enum class PointerConstraint {
339
NONE,
340
LOCKED,
341
CONFINED,
342
};
343
344
struct PointerData {
345
Point2 position;
346
uint32_t motion_time = 0;
347
348
// Relative motion has its own optional event and so needs its own time.
349
Vector2 relative_motion;
350
uint32_t relative_motion_time = 0;
351
352
BitField<MouseButtonMask> pressed_button_mask = MouseButtonMask::NONE;
353
354
MouseButton last_button_pressed = MouseButton::NONE;
355
Point2 last_pressed_position;
356
357
DisplayServer::WindowID pointed_id = DisplayServer::INVALID_WINDOW_ID;
358
DisplayServer::WindowID last_pointed_id = DisplayServer::INVALID_WINDOW_ID;
359
360
// This is needed to check for a new double click every time.
361
bool double_click_begun = false;
362
363
uint32_t button_time = 0;
364
uint32_t button_serial = 0;
365
366
uint32_t scroll_type = WL_POINTER_AXIS_SOURCE_WHEEL;
367
368
// The amount "scrolled" in pixels, in each direction.
369
Vector2 scroll_vector;
370
371
// The amount of scroll "clicks" in each direction, in fractions of 120.
372
Vector2i discrete_scroll_vector_120;
373
374
uint32_t pinch_scale = 1;
375
};
376
377
struct TabletToolData {
378
Point2 position;
379
Vector2 tilt;
380
uint32_t pressure = 0;
381
382
BitField<MouseButtonMask> pressed_button_mask = MouseButtonMask::NONE;
383
384
MouseButton last_button_pressed = MouseButton::NONE;
385
Point2 last_pressed_position;
386
387
bool double_click_begun = false;
388
389
uint64_t button_time = 0;
390
uint64_t motion_time = 0;
391
392
DisplayServer::WindowID proximal_id = DisplayServer::INVALID_WINDOW_ID;
393
DisplayServer::WindowID last_proximal_id = DisplayServer::INVALID_WINDOW_ID;
394
uint32_t proximity_serial = 0;
395
};
396
397
struct TabletToolState {
398
struct wl_seat *wl_seat = nullptr;
399
400
bool is_eraser = false;
401
402
TabletToolData data_pending;
403
TabletToolData data;
404
};
405
406
struct OfferState {
407
HashSet<String> mime_types;
408
};
409
410
struct SeatState {
411
RegistryState *registry = nullptr;
412
413
WaylandThread *wayland_thread = nullptr;
414
415
struct wl_seat *wl_seat = nullptr;
416
uint32_t wl_seat_name = 0;
417
418
// Pointer.
419
struct wl_pointer *wl_pointer = nullptr;
420
421
uint32_t pointer_enter_serial = 0;
422
423
struct wp_cursor_shape_device_v1 *wp_cursor_shape_device = nullptr;
424
425
struct zwp_relative_pointer_v1 *wp_relative_pointer = nullptr;
426
struct zwp_locked_pointer_v1 *wp_locked_pointer = nullptr;
427
struct zwp_confined_pointer_v1 *wp_confined_pointer = nullptr;
428
429
struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch = nullptr;
430
431
// NOTE: According to the wp_pointer_gestures protocol specification, there
432
// can be only one active gesture at a time.
433
Gesture active_gesture = Gesture::NONE;
434
435
// Used for delta calculations.
436
// NOTE: The wp_pointer_gestures protocol keeps track of the total scale of
437
// the pinch gesture, while godot instead wants its delta.
438
wl_fixed_t old_pinch_scale = 0;
439
440
struct wl_surface *cursor_surface = nullptr;
441
struct wl_callback *cursor_frame_callback = nullptr;
442
uint32_t cursor_time_ms = 0;
443
444
// This variable is needed to buffer all pointer changes until a
445
// wl_pointer.frame event, as per Wayland's specification. Everything is
446
// first set in `data_buffer` and then `data` is set with its contents on
447
// an input frame event. All methods should generally read from
448
// `pointer_data` and write to `data_buffer`.
449
PointerData pointer_data_buffer;
450
PointerData pointer_data;
451
452
// Keyboard.
453
struct wl_keyboard *wl_keyboard = nullptr;
454
455
// For key events.
456
DisplayServer::WindowID focused_id = DisplayServer::INVALID_WINDOW_ID;
457
458
struct xkb_context *xkb_context = nullptr;
459
struct xkb_keymap *xkb_keymap = nullptr;
460
struct xkb_state *xkb_state = nullptr;
461
462
const char *keymap_buffer = nullptr;
463
uint32_t keymap_buffer_size = 0;
464
465
HashMap<xkb_keycode_t, Key> pressed_keycodes;
466
467
xkb_layout_index_t current_layout_index = 0;
468
469
int32_t repeat_key_delay_msec = 0;
470
int32_t repeat_start_delay_msec = 0;
471
472
xkb_keycode_t repeating_keycode = XKB_KEYCODE_INVALID;
473
uint64_t last_repeat_start_msec = 0;
474
uint64_t last_repeat_msec = 0;
475
476
bool shift_pressed = false;
477
bool ctrl_pressed = false;
478
bool alt_pressed = false;
479
bool meta_pressed = false;
480
481
uint32_t last_key_pressed_serial = 0;
482
483
struct wl_data_device *wl_data_device = nullptr;
484
485
// Drag and drop.
486
DisplayServer::WindowID dnd_id = DisplayServer::INVALID_WINDOW_ID;
487
struct wl_data_offer *wl_data_offer_dnd = nullptr;
488
uint32_t dnd_enter_serial = 0;
489
490
// Clipboard.
491
struct wl_data_source *wl_data_source_selection = nullptr;
492
Vector<uint8_t> selection_data;
493
494
struct wl_data_offer *wl_data_offer_selection = nullptr;
495
496
// Primary selection.
497
struct zwp_primary_selection_device_v1 *wp_primary_selection_device = nullptr;
498
499
struct zwp_primary_selection_source_v1 *wp_primary_selection_source = nullptr;
500
Vector<uint8_t> primary_data;
501
502
struct zwp_primary_selection_offer_v1 *wp_primary_selection_offer = nullptr;
503
504
// Tablet.
505
struct zwp_tablet_seat_v2 *wp_tablet_seat = nullptr;
506
507
List<struct zwp_tablet_tool_v2 *> tablet_tools;
508
509
// IME.
510
struct zwp_text_input_v3 *wp_text_input = nullptr;
511
DisplayServer::WindowID ime_window_id = DisplayServer::INVALID_WINDOW_ID;
512
bool ime_enabled = false;
513
bool ime_active = false;
514
String ime_text;
515
String ime_text_commit;
516
Vector2i ime_cursor;
517
Rect2i ime_rect;
518
};
519
520
struct CustomCursor {
521
struct wl_buffer *wl_buffer = nullptr;
522
uint32_t *buffer_data = nullptr;
523
uint32_t buffer_data_size = 0;
524
525
Point2i hotspot;
526
};
527
528
private:
529
struct ThreadData {
530
SafeFlag thread_done;
531
Mutex mutex;
532
533
struct wl_display *wl_display = nullptr;
534
};
535
536
// FIXME: Is this the right thing to do?
537
inline static const char *proxy_tag = "godot";
538
539
Thread events_thread;
540
ThreadData thread_data;
541
542
HashMap<DisplayServer::WindowID, WindowState> windows;
543
544
List<Ref<Message>> messages;
545
546
String cursor_theme_name;
547
int unscaled_cursor_size = 24;
548
549
// NOTE: Regarding screen scale handling, the cursor cache is currently
550
// "static", by which I mean that we try to change it as little as possible and
551
// thus will be as big as the largest screen. This is mainly due to the fact
552
// that doing it dynamically doesn't look like it's worth it to me currently,
553
// especially as usually screen scales don't change continuously.
554
int cursor_scale = 1;
555
556
// Use cursor-shape-v1 protocol if the compositor supports it.
557
wp_cursor_shape_device_v1_shape standard_cursors[DisplayServer::CURSOR_MAX] = {
558
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT, //CURSOR_ARROW
559
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT, //CURSOR_IBEAM
560
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER, //CURSOR_POINTING_HAND
561
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR, //CURSOR_CROSS
562
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT, //CURSOR_WAIT
563
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_PROGRESS, //CURSOR_BUSY
564
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB, //CURSOR_DRAG
565
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRABBING, //CURSOR_CAN_DROP
566
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NO_DROP, //CURSOR_FORBIDDEN
567
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE, //CURSOR_VSIZE
568
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE, //CURSOR_HSIZE
569
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE, //CURSOR_BDIAGSIZE
570
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE, //CURSOR_FDIAGSIZE
571
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE, //CURSOR_MOVE
572
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ROW_RESIZE, //CURSOR_VSPLIT
573
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COL_RESIZE, //CURSOR_HSPLIT
574
wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_HELP, //CURSOR_HELP
575
};
576
577
// Fallback to reading $XCURSOR and system themes if the compositor does not.
578
struct wl_cursor_theme *wl_cursor_theme = nullptr;
579
struct wl_cursor *wl_cursors[DisplayServer::CURSOR_MAX] = {};
580
581
// User-defined cursor overrides. Take precedence over standard and wl cursors.
582
HashMap<DisplayServer::CursorShape, CustomCursor> custom_cursors;
583
584
DisplayServer::CursorShape cursor_shape = DisplayServer::CURSOR_ARROW;
585
bool cursor_visible = true;
586
587
PointerConstraint pointer_constraint = PointerConstraint::NONE;
588
589
struct wl_display *wl_display = nullptr;
590
struct wl_registry *wl_registry = nullptr;
591
592
struct wl_seat *wl_seat_current = nullptr;
593
594
bool frame = true;
595
596
RegistryState registry;
597
598
bool initialized = false;
599
600
#ifdef LIBDECOR_ENABLED
601
struct libdecor *libdecor_context = nullptr;
602
#endif // LIBDECOR_ENABLED
603
604
// Main polling method.
605
static void _poll_events_thread(void *p_data);
606
607
// Core Wayland event handlers.
608
static void _wl_registry_on_global(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t version);
609
static void _wl_registry_on_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name);
610
611
static void _wl_surface_on_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output);
612
static void _wl_surface_on_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output);
613
static void _wl_surface_on_preferred_buffer_scale(void *data, struct wl_surface *wl_surface, int32_t factor);
614
static void _wl_surface_on_preferred_buffer_transform(void *data, struct wl_surface *wl_surface, uint32_t transform);
615
616
static void _frame_wl_callback_on_done(void *data, struct wl_callback *wl_callback, uint32_t callback_data);
617
618
static void _wl_output_on_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char *make, const char *model, int32_t transform);
619
static void _wl_output_on_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh);
620
static void _wl_output_on_done(void *data, struct wl_output *wl_output);
621
static void _wl_output_on_scale(void *data, struct wl_output *wl_output, int32_t factor);
622
static void _wl_output_on_name(void *data, struct wl_output *wl_output, const char *name);
623
static void _wl_output_on_description(void *data, struct wl_output *wl_output, const char *description);
624
625
static void _wl_seat_on_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities);
626
static void _wl_seat_on_name(void *data, struct wl_seat *wl_seat, const char *name);
627
628
static void _cursor_frame_callback_on_done(void *data, struct wl_callback *wl_callback, uint32_t time_ms);
629
630
static void _wl_pointer_on_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y);
631
static void _wl_pointer_on_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface);
632
static void _wl_pointer_on_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y);
633
static void _wl_pointer_on_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state);
634
static void _wl_pointer_on_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value);
635
static void _wl_pointer_on_frame(void *data, struct wl_pointer *wl_pointer);
636
static void _wl_pointer_on_axis_source(void *data, struct wl_pointer *wl_pointer, uint32_t axis_source);
637
static void _wl_pointer_on_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis);
638
static void _wl_pointer_on_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete);
639
static void _wl_pointer_on_axis_value120(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t value120);
640
static void _wl_pointer_on_axis_relative_direction(void *data, struct wl_pointer *wl_pointer, uint32_t axis, uint32_t direction);
641
642
static void _wl_keyboard_on_keymap(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size);
643
static void _wl_keyboard_on_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys);
644
static void _wl_keyboard_on_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface);
645
static void _wl_keyboard_on_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state);
646
static void _wl_keyboard_on_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group);
647
static void _wl_keyboard_on_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay);
648
649
static void _wl_data_device_on_data_offer(void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *id);
650
static void _wl_data_device_on_enter(void *data, struct wl_data_device *wl_data_device, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *id);
651
static void _wl_data_device_on_leave(void *data, struct wl_data_device *wl_data_device);
652
static void _wl_data_device_on_motion(void *data, struct wl_data_device *wl_data_device, uint32_t time, wl_fixed_t x, wl_fixed_t y);
653
static void _wl_data_device_on_drop(void *data, struct wl_data_device *wl_data_device);
654
static void _wl_data_device_on_selection(void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *id);
655
656
static void _wl_data_offer_on_offer(void *data, struct wl_data_offer *wl_data_offer, const char *mime_type);
657
static void _wl_data_offer_on_source_actions(void *data, struct wl_data_offer *wl_data_offer, uint32_t source_actions);
658
static void _wl_data_offer_on_action(void *data, struct wl_data_offer *wl_data_offer, uint32_t dnd_action);
659
660
static void _wl_data_source_on_target(void *data, struct wl_data_source *wl_data_source, const char *mime_type);
661
static void _wl_data_source_on_send(void *data, struct wl_data_source *wl_data_source, const char *mime_type, int32_t fd);
662
static void _wl_data_source_on_cancelled(void *data, struct wl_data_source *wl_data_source);
663
static void _wl_data_source_on_dnd_drop_performed(void *data, struct wl_data_source *wl_data_source);
664
static void _wl_data_source_on_dnd_finished(void *data, struct wl_data_source *wl_data_source);
665
static void _wl_data_source_on_action(void *data, struct wl_data_source *wl_data_source, uint32_t dnd_action);
666
667
// xdg-shell event handlers.
668
static void _xdg_wm_base_on_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial);
669
670
static void _xdg_surface_on_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial);
671
672
static void _xdg_toplevel_on_configure(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states);
673
static void _xdg_toplevel_on_close(void *data, struct xdg_toplevel *xdg_toplevel);
674
static void _xdg_toplevel_on_configure_bounds(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height);
675
static void _xdg_toplevel_on_wm_capabilities(void *data, struct xdg_toplevel *xdg_toplevel, struct wl_array *capabilities);
676
677
static void _xdg_popup_on_configure(void *data, struct xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height);
678
static void _xdg_popup_on_popup_done(void *data, struct xdg_popup *xdg_popup);
679
static void _xdg_popup_on_repositioned(void *data, struct xdg_popup *xdg_popup, uint32_t token);
680
681
// wayland-protocols event handlers.
682
static void _wp_fractional_scale_on_preferred_scale(void *data, struct wp_fractional_scale_v1 *wp_fractional_scale_v1, uint32_t scale);
683
684
static void _wp_relative_pointer_on_relative_motion(void *data, struct zwp_relative_pointer_v1 *wp_relative_pointer_v1, uint32_t uptime_hi, uint32_t uptime_lo, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_unaccel, wl_fixed_t dy_unaccel);
685
686
static void _wp_pointer_gesture_pinch_on_begin(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, struct wl_surface *surface, uint32_t fingers);
687
static void _wp_pointer_gesture_pinch_on_update(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, wl_fixed_t rotation);
688
static void _wp_pointer_gesture_pinch_on_end(void *data, struct zwp_pointer_gesture_pinch_v1 *zp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, int32_t cancelled);
689
690
static void _wp_primary_selection_device_on_data_offer(void *data, struct zwp_primary_selection_device_v1 *wp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1 *offer);
691
static void _wp_primary_selection_device_on_selection(void *data, struct zwp_primary_selection_device_v1 *wp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1 *id);
692
693
static void _wp_primary_selection_offer_on_offer(void *data, struct zwp_primary_selection_offer_v1 *wp_primary_selection_offer_v1, const char *mime_type);
694
695
static void _wp_primary_selection_source_on_send(void *data, struct zwp_primary_selection_source_v1 *wp_primary_selection_source_v1, const char *mime_type, int32_t fd);
696
static void _wp_primary_selection_source_on_cancelled(void *data, struct zwp_primary_selection_source_v1 *wp_primary_selection_source_v1);
697
698
static void _wp_tablet_seat_on_tablet_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_v2 *id);
699
static void _wp_tablet_seat_on_tool_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_tool_v2 *id);
700
static void _wp_tablet_seat_on_pad_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_pad_v2 *id);
701
702
static void _wp_tablet_tool_on_type(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t tool_type);
703
static void _wp_tablet_tool_on_hardware_serial(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t hardware_serial_hi, uint32_t hardware_serial_lo);
704
static void _wp_tablet_tool_on_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t hardware_id_hi, uint32_t hardware_id_lo);
705
static void _wp_tablet_tool_on_capability(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t capability);
706
static void _wp_tablet_tool_on_done(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2);
707
static void _wp_tablet_tool_on_removed(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2);
708
static void _wp_tablet_tool_on_proximity_in(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial, struct zwp_tablet_v2 *tablet, struct wl_surface *surface);
709
static void _wp_tablet_tool_on_proximity_out(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2);
710
static void _wp_tablet_tool_on_down(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial);
711
static void _wp_tablet_tool_on_up(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2);
712
static void _wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t x, wl_fixed_t y);
713
static void _wp_tablet_tool_on_pressure(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t pressure);
714
static void _wp_tablet_tool_on_distance(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t distance);
715
static void _wp_tablet_tool_on_tilt(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t tilt_x, wl_fixed_t tilt_y);
716
static void _wp_tablet_tool_on_rotation(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t degrees);
717
static void _wp_tablet_tool_on_slider(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, int32_t position);
718
static void _wp_tablet_tool_on_wheel(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t degrees, int32_t clicks);
719
static void _wp_tablet_tool_on_button(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial, uint32_t button, uint32_t state);
720
static void _wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t time);
721
722
static void _wp_text_input_on_enter(void *data, struct zwp_text_input_v3 *wp_text_input_v3, struct wl_surface *surface);
723
static void _wp_text_input_on_leave(void *data, struct zwp_text_input_v3 *wp_text_input_v3, struct wl_surface *surface);
724
static void _wp_text_input_on_preedit_string(void *data, struct zwp_text_input_v3 *wp_text_input_v3, const char *text, int32_t cursor_begin, int32_t cursor_end);
725
static void _wp_text_input_on_commit_string(void *data, struct zwp_text_input_v3 *wp_text_input_v3, const char *text);
726
static void _wp_text_input_on_delete_surrounding_text(void *data, struct zwp_text_input_v3 *wp_text_input_v3, uint32_t before_length, uint32_t after_length);
727
static void _wp_text_input_on_done(void *data, struct zwp_text_input_v3 *wp_text_input_v3, uint32_t serial);
728
729
static void _xdg_toplevel_decoration_on_configure(void *data, struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration, uint32_t mode);
730
731
// NOTE: Deprecated.
732
static void _xdg_exported_v1_on_handle(void *data, zxdg_exported_v1 *exported, const char *handle);
733
734
static void _xdg_exported_v2_on_handle(void *data, zxdg_exported_v2 *exported, const char *handle);
735
736
static void _xdg_activation_token_on_done(void *data, struct xdg_activation_token_v1 *xdg_activation_token, const char *token);
737
738
// Core Wayland event listeners.
739
static constexpr struct wl_registry_listener wl_registry_listener = {
740
.global = _wl_registry_on_global,
741
.global_remove = _wl_registry_on_global_remove,
742
};
743
744
static constexpr struct wl_surface_listener wl_surface_listener = {
745
.enter = _wl_surface_on_enter,
746
.leave = _wl_surface_on_leave,
747
.preferred_buffer_scale = _wl_surface_on_preferred_buffer_scale,
748
.preferred_buffer_transform = _wl_surface_on_preferred_buffer_transform,
749
};
750
751
static constexpr struct wl_callback_listener frame_wl_callback_listener = {
752
.done = _frame_wl_callback_on_done,
753
};
754
755
static constexpr struct wl_output_listener wl_output_listener = {
756
.geometry = _wl_output_on_geometry,
757
.mode = _wl_output_on_mode,
758
.done = _wl_output_on_done,
759
.scale = _wl_output_on_scale,
760
.name = _wl_output_on_name,
761
.description = _wl_output_on_description,
762
};
763
764
static constexpr struct wl_seat_listener wl_seat_listener = {
765
.capabilities = _wl_seat_on_capabilities,
766
.name = _wl_seat_on_name,
767
};
768
769
static constexpr struct wl_callback_listener cursor_frame_callback_listener = {
770
.done = _cursor_frame_callback_on_done,
771
};
772
773
static constexpr struct wl_pointer_listener wl_pointer_listener = {
774
.enter = _wl_pointer_on_enter,
775
.leave = _wl_pointer_on_leave,
776
.motion = _wl_pointer_on_motion,
777
.button = _wl_pointer_on_button,
778
.axis = _wl_pointer_on_axis,
779
.frame = _wl_pointer_on_frame,
780
.axis_source = _wl_pointer_on_axis_source,
781
.axis_stop = _wl_pointer_on_axis_stop,
782
.axis_discrete = _wl_pointer_on_axis_discrete,
783
.axis_value120 = _wl_pointer_on_axis_value120,
784
.axis_relative_direction = _wl_pointer_on_axis_relative_direction,
785
};
786
787
static constexpr struct wl_keyboard_listener wl_keyboard_listener = {
788
.keymap = _wl_keyboard_on_keymap,
789
.enter = _wl_keyboard_on_enter,
790
.leave = _wl_keyboard_on_leave,
791
.key = _wl_keyboard_on_key,
792
.modifiers = _wl_keyboard_on_modifiers,
793
.repeat_info = _wl_keyboard_on_repeat_info,
794
};
795
796
static constexpr struct wl_data_device_listener wl_data_device_listener = {
797
.data_offer = _wl_data_device_on_data_offer,
798
.enter = _wl_data_device_on_enter,
799
.leave = _wl_data_device_on_leave,
800
.motion = _wl_data_device_on_motion,
801
.drop = _wl_data_device_on_drop,
802
.selection = _wl_data_device_on_selection,
803
};
804
805
static constexpr struct wl_data_offer_listener wl_data_offer_listener = {
806
.offer = _wl_data_offer_on_offer,
807
.source_actions = _wl_data_offer_on_source_actions,
808
.action = _wl_data_offer_on_action,
809
};
810
811
static constexpr struct wl_data_source_listener wl_data_source_listener = {
812
.target = _wl_data_source_on_target,
813
.send = _wl_data_source_on_send,
814
.cancelled = _wl_data_source_on_cancelled,
815
.dnd_drop_performed = _wl_data_source_on_dnd_drop_performed,
816
.dnd_finished = _wl_data_source_on_dnd_finished,
817
.action = _wl_data_source_on_action,
818
};
819
820
// xdg-shell event listeners.
821
static constexpr struct xdg_wm_base_listener xdg_wm_base_listener = {
822
.ping = _xdg_wm_base_on_ping,
823
};
824
825
static constexpr struct xdg_surface_listener xdg_surface_listener = {
826
.configure = _xdg_surface_on_configure,
827
};
828
829
static constexpr struct xdg_toplevel_listener xdg_toplevel_listener = {
830
.configure = _xdg_toplevel_on_configure,
831
.close = _xdg_toplevel_on_close,
832
.configure_bounds = _xdg_toplevel_on_configure_bounds,
833
.wm_capabilities = _xdg_toplevel_on_wm_capabilities,
834
};
835
836
static constexpr struct xdg_popup_listener xdg_popup_listener = {
837
.configure = _xdg_popup_on_configure,
838
.popup_done = _xdg_popup_on_popup_done,
839
.repositioned = _xdg_popup_on_repositioned,
840
};
841
842
// wayland-protocols event listeners.
843
static constexpr struct wp_fractional_scale_v1_listener wp_fractional_scale_listener = {
844
.preferred_scale = _wp_fractional_scale_on_preferred_scale,
845
};
846
847
static constexpr struct zwp_relative_pointer_v1_listener wp_relative_pointer_listener = {
848
.relative_motion = _wp_relative_pointer_on_relative_motion,
849
};
850
851
static constexpr struct zwp_pointer_gesture_pinch_v1_listener wp_pointer_gesture_pinch_listener = {
852
.begin = _wp_pointer_gesture_pinch_on_begin,
853
.update = _wp_pointer_gesture_pinch_on_update,
854
.end = _wp_pointer_gesture_pinch_on_end,
855
};
856
857
static constexpr struct zwp_primary_selection_device_v1_listener wp_primary_selection_device_listener = {
858
.data_offer = _wp_primary_selection_device_on_data_offer,
859
.selection = _wp_primary_selection_device_on_selection,
860
};
861
862
static constexpr struct zwp_primary_selection_offer_v1_listener wp_primary_selection_offer_listener = {
863
.offer = _wp_primary_selection_offer_on_offer,
864
};
865
866
static constexpr struct zwp_primary_selection_source_v1_listener wp_primary_selection_source_listener = {
867
.send = _wp_primary_selection_source_on_send,
868
.cancelled = _wp_primary_selection_source_on_cancelled,
869
};
870
871
static constexpr struct zwp_tablet_seat_v2_listener wp_tablet_seat_listener = {
872
.tablet_added = _wp_tablet_seat_on_tablet_added,
873
.tool_added = _wp_tablet_seat_on_tool_added,
874
.pad_added = _wp_tablet_seat_on_pad_added,
875
};
876
877
static constexpr struct zwp_tablet_tool_v2_listener wp_tablet_tool_listener = {
878
.type = _wp_tablet_tool_on_type,
879
.hardware_serial = _wp_tablet_tool_on_hardware_serial,
880
.hardware_id_wacom = _wp_tablet_tool_on_hardware_id_wacom,
881
.capability = _wp_tablet_tool_on_capability,
882
.done = _wp_tablet_tool_on_done,
883
.removed = _wp_tablet_tool_on_removed,
884
.proximity_in = _wp_tablet_tool_on_proximity_in,
885
.proximity_out = _wp_tablet_tool_on_proximity_out,
886
.down = _wp_tablet_tool_on_down,
887
.up = _wp_tablet_tool_on_up,
888
.motion = _wp_tablet_tool_on_motion,
889
.pressure = _wp_tablet_tool_on_pressure,
890
.distance = _wp_tablet_tool_on_distance,
891
.tilt = _wp_tablet_tool_on_tilt,
892
.rotation = _wp_tablet_tool_on_rotation,
893
.slider = _wp_tablet_tool_on_slider,
894
.wheel = _wp_tablet_tool_on_wheel,
895
.button = _wp_tablet_tool_on_button,
896
.frame = _wp_tablet_tool_on_frame,
897
};
898
899
static constexpr struct zwp_text_input_v3_listener wp_text_input_listener = {
900
.enter = _wp_text_input_on_enter,
901
.leave = _wp_text_input_on_leave,
902
.preedit_string = _wp_text_input_on_preedit_string,
903
.commit_string = _wp_text_input_on_commit_string,
904
.delete_surrounding_text = _wp_text_input_on_delete_surrounding_text,
905
.done = _wp_text_input_on_done,
906
};
907
908
// NOTE: Deprecated.
909
static constexpr struct zxdg_exported_v1_listener xdg_exported_v1_listener = {
910
.handle = _xdg_exported_v1_on_handle,
911
};
912
913
static constexpr struct zxdg_exported_v2_listener xdg_exported_v2_listener = {
914
.handle = _xdg_exported_v2_on_handle,
915
};
916
917
static constexpr struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration_listener = {
918
.configure = _xdg_toplevel_decoration_on_configure,
919
};
920
921
static constexpr struct xdg_activation_token_v1_listener xdg_activation_token_listener = {
922
.done = _xdg_activation_token_on_done,
923
};
924
925
#ifdef LIBDECOR_ENABLED
926
// libdecor event handlers.
927
static void libdecor_on_error(struct libdecor *context, enum libdecor_error error, const char *message);
928
929
static void libdecor_frame_on_configure(struct libdecor_frame *frame, struct libdecor_configuration *configuration, void *user_data);
930
931
static void libdecor_frame_on_close(struct libdecor_frame *frame, void *user_data);
932
933
static void libdecor_frame_on_commit(struct libdecor_frame *frame, void *user_data);
934
935
static void libdecor_frame_on_dismiss_popup(struct libdecor_frame *frame, const char *seat_name, void *user_data);
936
937
// libdecor event listeners.
938
static constexpr struct libdecor_interface libdecor_interface = {
939
.error = libdecor_on_error,
940
.reserved0 = nullptr,
941
.reserved1 = nullptr,
942
.reserved2 = nullptr,
943
.reserved3 = nullptr,
944
.reserved4 = nullptr,
945
.reserved5 = nullptr,
946
.reserved6 = nullptr,
947
.reserved7 = nullptr,
948
.reserved8 = nullptr,
949
.reserved9 = nullptr,
950
};
951
952
static constexpr struct libdecor_frame_interface libdecor_frame_interface = {
953
.configure = libdecor_frame_on_configure,
954
.close = libdecor_frame_on_close,
955
.commit = libdecor_frame_on_commit,
956
.dismiss_popup = libdecor_frame_on_dismiss_popup,
957
.reserved0 = nullptr,
958
.reserved1 = nullptr,
959
.reserved2 = nullptr,
960
.reserved3 = nullptr,
961
.reserved4 = nullptr,
962
.reserved5 = nullptr,
963
.reserved6 = nullptr,
964
.reserved7 = nullptr,
965
.reserved8 = nullptr,
966
.reserved9 = nullptr,
967
};
968
#endif // LIBDECOR_ENABLED
969
970
static Vector<uint8_t> _read_fd(int fd);
971
static int _allocate_shm_file(size_t size);
972
973
static Vector<uint8_t> _wl_data_offer_read(struct wl_display *wl_display, const char *p_mime, struct wl_data_offer *wl_data_offer);
974
static Vector<uint8_t> _wp_primary_selection_offer_read(struct wl_display *wl_display, const char *p_mime, struct zwp_primary_selection_offer_v1 *wp_primary_selection_offer);
975
976
static void _seat_state_set_current(WaylandThread::SeatState &p_ss);
977
static Ref<InputEventKey> _seat_state_get_key_event(SeatState *p_ss, xkb_keycode_t p_keycode, bool p_pressed);
978
static Ref<InputEventKey> _seat_state_get_unstuck_key_event(SeatState *p_ss, xkb_keycode_t p_keycode, bool p_pressed, Key p_key);
979
980
static void _wayland_state_update_cursor();
981
982
void _set_current_seat(struct wl_seat *p_seat);
983
984
bool _load_cursor_theme(int p_cursor_size);
985
986
void _update_scale(int p_scale);
987
988
public:
989
Mutex &mutex = thread_data.mutex;
990
991
struct wl_display *get_wl_display() const;
992
993
// Core Wayland utilities for integrating with our own data structures.
994
static bool wl_proxy_is_godot(struct wl_proxy *p_proxy);
995
static void wl_proxy_tag_godot(struct wl_proxy *p_proxy);
996
997
static WindowState *wl_surface_get_window_state(struct wl_surface *p_surface);
998
static ScreenState *wl_output_get_screen_state(struct wl_output *p_output);
999
static SeatState *wl_seat_get_seat_state(struct wl_seat *p_seat);
1000
static TabletToolState *wp_tablet_tool_get_state(struct zwp_tablet_tool_v2 *p_tool);
1001
static OfferState *wl_data_offer_get_offer_state(struct wl_data_offer *p_offer);
1002
1003
static OfferState *wp_primary_selection_offer_get_offer_state(struct zwp_primary_selection_offer_v1 *p_offer);
1004
1005
void seat_state_unlock_pointer(SeatState *p_ss);
1006
void seat_state_lock_pointer(SeatState *p_ss);
1007
void seat_state_set_hint(SeatState *p_ss, int p_x, int p_y);
1008
void seat_state_confine_pointer(SeatState *p_ss);
1009
1010
static void seat_state_update_cursor(SeatState *p_ss);
1011
1012
void seat_state_echo_keys(SeatState *p_ss);
1013
1014
static int window_state_get_preferred_buffer_scale(WindowState *p_ws);
1015
static double window_state_get_scale_factor(WindowState *p_ws);
1016
static void window_state_update_size(WindowState *p_ws, int p_width, int p_height);
1017
1018
static Vector2i scale_vector2i(const Vector2i &p_vector, double p_amount);
1019
1020
void push_message(Ref<Message> message);
1021
bool has_message();
1022
Ref<Message> pop_message();
1023
1024
void beep() const;
1025
1026
void window_create(DisplayServer::WindowID p_window_id, int p_width, int p_height);
1027
void window_create_popup(DisplayServer::WindowID p_window_id, DisplayServer::WindowID p_parent_id, Rect2i p_rect);
1028
void window_destroy(DisplayServer::WindowID p_window_Id);
1029
1030
void window_set_parent(DisplayServer::WindowID p_window_id, DisplayServer::WindowID p_parent_id);
1031
1032
struct wl_surface *window_get_wl_surface(DisplayServer::WindowID p_window_id) const;
1033
WindowState *window_get_state(DisplayServer::WindowID p_window_id);
1034
1035
void window_start_resize(DisplayServer::WindowResizeEdge p_edge, DisplayServer::WindowID p_window);
1036
1037
void window_set_max_size(DisplayServer::WindowID p_window_id, const Size2i &p_size);
1038
void window_set_min_size(DisplayServer::WindowID p_window_id, const Size2i &p_size);
1039
1040
bool window_can_set_mode(DisplayServer::WindowID p_window_id, DisplayServer::WindowMode p_window_mode) const;
1041
void window_try_set_mode(DisplayServer::WindowID p_window_id, DisplayServer::WindowMode p_window_mode);
1042
DisplayServer::WindowMode window_get_mode(DisplayServer::WindowID p_window_id) const;
1043
1044
void window_set_borderless(DisplayServer::WindowID p_window_id, bool p_borderless);
1045
void window_set_title(DisplayServer::WindowID p_window_id, const String &p_title);
1046
void window_set_app_id(DisplayServer::WindowID p_window_id, const String &p_app_id);
1047
1048
bool window_is_focused(DisplayServer::WindowID p_window_id);
1049
1050
// Optional - requires xdg_activation_v1
1051
void window_request_attention(DisplayServer::WindowID p_window_id);
1052
1053
void window_start_drag(DisplayServer::WindowID p_window_id);
1054
1055
// Optional - require idle_inhibit_unstable_v1
1056
void window_set_idle_inhibition(DisplayServer::WindowID p_window_id, bool p_enable);
1057
bool window_get_idle_inhibition(DisplayServer::WindowID p_window_id) const;
1058
1059
ScreenData screen_get_data(int p_screen) const;
1060
int get_screen_count() const;
1061
1062
void pointer_set_constraint(PointerConstraint p_constraint);
1063
void pointer_set_hint(const Point2i &p_hint);
1064
PointerConstraint pointer_get_constraint() const;
1065
DisplayServer::WindowID pointer_get_pointed_window_id() const;
1066
DisplayServer::WindowID pointer_get_last_pointed_window_id() const;
1067
BitField<MouseButtonMask> pointer_get_button_mask() const;
1068
1069
void cursor_set_visible(bool p_visible);
1070
void cursor_set_shape(DisplayServer::CursorShape p_cursor_shape);
1071
1072
void cursor_set_custom_shape(DisplayServer::CursorShape p_cursor_shape);
1073
void cursor_shape_set_custom_image(DisplayServer::CursorShape p_cursor_shape, Ref<Image> p_image, const Point2i &p_hotspot);
1074
void cursor_shape_clear_custom_image(DisplayServer::CursorShape p_cursor_shape);
1075
1076
void window_set_ime_active(const bool p_active, DisplayServer::WindowID p_window_id);
1077
void window_set_ime_position(const Point2i &p_pos, DisplayServer::WindowID p_window_id);
1078
1079
int keyboard_get_layout_count() const;
1080
int keyboard_get_current_layout_index() const;
1081
void keyboard_set_current_layout_index(int p_index);
1082
String keyboard_get_layout_name(int p_index) const;
1083
1084
Key keyboard_get_key_from_physical(Key p_key) const;
1085
1086
void keyboard_echo_keys();
1087
1088
bool selection_has_mime(const String &p_mime) const;
1089
Vector<uint8_t> selection_get_mime(const String &p_mime) const;
1090
1091
void selection_set_text(const String &p_text);
1092
1093
// Optional primary support - requires wp_primary_selection_unstable_v1
1094
bool primary_has_mime(const String &p_mime) const;
1095
Vector<uint8_t> primary_get_mime(const String &p_mime) const;
1096
1097
void primary_set_text(const String &p_text);
1098
1099
void commit_surfaces();
1100
1101
void set_frame();
1102
bool get_reset_frame();
1103
bool wait_frame_suspend_ms(int p_timeout);
1104
bool is_fifo_available() const;
1105
1106
uint64_t window_get_last_frame_time(DisplayServer::WindowID p_window_id) const;
1107
bool window_is_suspended(DisplayServer::WindowID p_window_id) const;
1108
bool is_suspended() const;
1109
1110
Error init();
1111
void destroy();
1112
};
1113
1114
#endif // WAYLAND_ENABLED
1115
1116