22 #include "../../SDL_internal.h"
24 #if SDL_VIDEO_DRIVER_WAYLAND
29 #include "../../events/SDL_events_c.h"
40 #include <sys/types.h>
43 #include <xkbcommon/xkbcommon.h>
46 #include <wayland-util.h>
48 #include "xdg-shell-client-protocol.h"
49 #include "xdg-shell-unstable-v6-client-protocol.h"
50 #include "xdg-decoration-unstable-v1-client-protocol.h"
51 #include "org-kde-kwin-server-decoration-manager-client-protocol.h"
53 #define WAYLANDVID_DRIVER_NAME "wayland"
57 Wayland_VideoInit(
_THIS);
65 Wayland_VideoQuit(
_THIS);
79 #if defined(__LINUX__) || defined(__FREEBSD__)
86 spot =
SDL_getenv(
"SDL_VIDEO_WAYLAND_WMCLASS");
98 #if defined(__LINUX__) || defined(__FREEBSD__)
99 #if defined(__LINUX__)
101 #elif defined(__FREEBSD__)
105 #error Where can we find the executable name?
107 linksize = readlink(procfile, linkfile,
sizeof(linkfile) - 1);
109 linkfile[linksize] =
'\0';
125 Wayland_Available(
void)
127 struct wl_display *display =
NULL;
129 display = WAYLAND_wl_display_connect(
NULL);
130 if (display !=
NULL) {
131 WAYLAND_wl_display_disconnect(display);
136 return (display !=
NULL);
147 Wayland_CreateDevice(
int devindex)
164 device->VideoInit = Wayland_VideoInit;
165 device->VideoQuit = Wayland_VideoQuit;
166 device->SetDisplayMode = Wayland_SetDisplayMode;
167 device->GetDisplayModes = Wayland_GetDisplayModes;
199 device->Vulkan_LoadLibrary = Wayland_Vulkan_LoadLibrary;
200 device->Vulkan_UnloadLibrary = Wayland_Vulkan_UnloadLibrary;
201 device->Vulkan_GetInstanceExtensions = Wayland_Vulkan_GetInstanceExtensions;
202 device->Vulkan_CreateSurface = Wayland_Vulkan_CreateSurface;
203 device->Vulkan_GetDrawableSize = Wayland_Vulkan_GetDrawableSize;
206 device->free = Wayland_DeleteDevice;
212 WAYLANDVID_DRIVER_NAME,
"SDL Wayland video driver",
213 Wayland_Available, Wayland_CreateDevice
217 display_handle_geometry(
void *
data,
234 display_handle_mode(
void *
data,
248 mode.refresh_rate = refresh / 1000;
252 if (
flags & WL_OUTPUT_MODE_CURRENT) {
259 display_handle_done(
void *
data,
271 display_handle_scale(
void *
data,
279 static const struct wl_output_listener output_listener = {
280 display_handle_geometry,
298 output = wl_registry_bind(
d->registry,
id, &wl_output_interface, 2);
306 data->scale_factor = 1.0;
309 wl_output_add_listener(
output, &output_listener, display);
312 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
314 windowmanager_hints(
void *
data,
struct qt_windowmanager *qt_windowmanager,
320 windowmanager_quit(
void *
data,
struct qt_windowmanager *qt_windowmanager)
325 static const struct qt_windowmanager_listener windowmanager_listener = {
333 handle_ping_zxdg_shell(
void *
data,
struct zxdg_shell_v6 *zxdg,
uint32_t serial)
335 zxdg_shell_v6_pong(zxdg, serial);
338 static const struct zxdg_shell_v6_listener shell_listener_zxdg = {
339 handle_ping_zxdg_shell
344 handle_ping_xdg_wm_base(
void *
data,
struct xdg_wm_base *xdg,
uint32_t serial)
346 xdg_wm_base_pong(xdg, serial);
349 static const struct xdg_wm_base_listener shell_listener_xdg = {
350 handle_ping_xdg_wm_base
355 display_handle_global(
void *
data,
struct wl_registry *registry,
uint32_t id,
356 const char *interface,
uint32_t version)
362 if (strcmp(interface,
"wl_compositor") == 0) {
363 d->compositor = wl_registry_bind(
d->registry,
id, &wl_compositor_interface,
SDL_min(3, version));
364 }
else if (strcmp(interface,
"wl_output") == 0) {
365 Wayland_add_display(
d,
id);
366 }
else if (strcmp(interface,
"wl_seat") == 0) {
368 }
else if (strcmp(interface,
"xdg_wm_base") == 0) {
369 d->shell.xdg = wl_registry_bind(
d->registry,
id, &xdg_wm_base_interface, 1);
370 xdg_wm_base_add_listener(
d->shell.xdg, &shell_listener_xdg,
NULL);
371 }
else if (strcmp(interface,
"zxdg_shell_v6") == 0) {
372 d->shell.zxdg = wl_registry_bind(
d->registry,
id, &zxdg_shell_v6_interface, 1);
373 zxdg_shell_v6_add_listener(
d->shell.zxdg, &shell_listener_zxdg,
NULL);
374 }
else if (strcmp(interface,
"wl_shell") == 0) {
375 d->shell.wl = wl_registry_bind(
d->registry,
id, &wl_shell_interface, 1);
376 }
else if (strcmp(interface,
"wl_shm") == 0) {
377 d->shm = wl_registry_bind(registry,
id, &wl_shm_interface, 1);
378 d->cursor_theme = WAYLAND_wl_cursor_theme_load(
NULL, 32,
d->shm);
379 }
else if (strcmp(interface,
"zwp_relative_pointer_manager_v1") == 0) {
381 }
else if (strcmp(interface,
"zwp_pointer_constraints_v1") == 0) {
383 }
else if (strcmp(interface,
"wl_data_device_manager") == 0) {
384 d->data_device_manager = wl_registry_bind(
d->registry,
id, &wl_data_device_manager_interface,
SDL_min(3, version));
385 }
else if (strcmp(interface,
"zxdg_decoration_manager_v1") == 0) {
386 d->decoration_manager = wl_registry_bind(
d->registry,
id, &zxdg_decoration_manager_v1_interface, 1);
387 }
else if (strcmp(interface,
"org_kde_kwin_server_decoration_manager") == 0) {
388 d->kwin_server_decoration_manager = wl_registry_bind(
d->registry,
id, &org_kde_kwin_server_decoration_manager_interface, 1);
390 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
391 }
else if (strcmp(interface,
"qt_touch_extension") == 0) {
392 Wayland_touch_create(
d,
id);
393 }
else if (strcmp(interface,
"qt_surface_extension") == 0) {
394 d->surface_extension = wl_registry_bind(registry,
id,
395 &qt_surface_extension_interface, 1);
396 }
else if (strcmp(interface,
"qt_windowmanager") == 0) {
397 d->windowmanager = wl_registry_bind(registry,
id,
398 &qt_windowmanager_interface, 1);
399 qt_windowmanager_add_listener(
d->windowmanager, &windowmanager_listener,
d);
405 display_remove_global(
void *
data,
struct wl_registry *registry,
uint32_t id) {}
407 static const struct wl_registry_listener registry_listener = {
408 display_handle_global,
409 display_remove_global
413 Wayland_VideoInit(
_THIS)
421 data->xkb_context = WAYLAND_xkb_context_new(0);
422 if (!
data->xkb_context) {
426 data->display = WAYLAND_wl_display_connect(
NULL);
428 return SDL_SetError(
"Failed to connect to a Wayland display");
431 data->registry = wl_display_get_registry(
data->display);
433 return SDL_SetError(
"Failed to get the Wayland registry");
436 wl_registry_add_listener(
data->registry, ®istry_listener,
data);
439 WAYLAND_wl_display_roundtrip(
data->display);
442 WAYLAND_wl_display_roundtrip(
data->display);
447 data->classname = get_classname();
449 WAYLAND_wl_display_flush(
data->display);
468 Wayland_VideoQuit(
_THIS)
473 Wayland_FiniMouse ();
492 if (
data->xkb_context) {
493 WAYLAND_xkb_context_unref(
data->xkb_context);
496 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
497 if (
data->windowmanager)
498 qt_windowmanager_destroy(
data->windowmanager);
500 if (
data->surface_extension)
501 qt_surface_extension_destroy(
data->surface_extension);
503 Wayland_touch_destroy(
data);
507 wl_shm_destroy(
data->shm);
509 if (
data->cursor_theme)
510 WAYLAND_wl_cursor_theme_destroy(
data->cursor_theme);
513 wl_shell_destroy(
data->shell.wl);
516 xdg_wm_base_destroy(
data->shell.xdg);
518 if (
data->shell.zxdg)
519 zxdg_shell_v6_destroy(
data->shell.zxdg);
521 if (
data->compositor)
522 wl_compositor_destroy(
data->compositor);
525 wl_registry_destroy(
data->registry);
528 WAYLAND_wl_display_flush(
data->display);
529 WAYLAND_wl_display_disconnect(
data->display);