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