# HG changeset patch # User Ethan Lee # Date 1612558677 18000 # Fri Feb 05 15:57:57 2021 -0500 # Node ID 39998a600a1e9904b3b9343fb2444e631f0fede6 # Parent 60b9ce4ee73e864aef9c297741982cf8a1df6d07 wayland: Add support for libdecoration diff -r 60b9ce4ee73e -r 39998a600a1e include/SDL_config.h.cmake --- a/include/SDL_config.h.cmake Fri Feb 05 00:27:11 2021 +0100 +++ b/include/SDL_config.h.cmake Fri Feb 05 15:57:57 2021 -0500 @@ -375,6 +375,7 @@ #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@ #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR@ #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@ +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECORATION @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECORATION@ #cmakedefine SDL_VIDEO_DRIVER_X11 @SDL_VIDEO_DRIVER_X11@ #cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC @SDL_VIDEO_DRIVER_X11_DYNAMIC@ diff -r 60b9ce4ee73e -r 39998a600a1e include/SDL_config.h.in --- a/include/SDL_config.h.in Fri Feb 05 00:27:11 2021 +0100 +++ b/include/SDL_config.h.in Fri Feb 05 15:57:57 2021 -0500 @@ -362,6 +362,7 @@ #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON +#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECORATION #undef SDL_VIDEO_DRIVER_X11 #undef SDL_VIDEO_DRIVER_RPI #undef SDL_VIDEO_DRIVER_KMSDRM diff -r 60b9ce4ee73e -r 39998a600a1e src/video/wayland/SDL_waylanddyn.c --- a/src/video/wayland/SDL_waylanddyn.c Fri Feb 05 00:27:11 2021 +0100 +++ b/src/video/wayland/SDL_waylanddyn.c Fri Feb 05 15:57:57 2021 -0500 @@ -47,12 +47,16 @@ #ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON #define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON NULL #endif +#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECORATION +#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECORATION NULL +#endif static waylanddynlib waylandlibs[] = { {NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC}, {NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL}, {NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR}, - {NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON} + {NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON}, + {NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECORATION} }; static void * diff -r 60b9ce4ee73e -r 39998a600a1e src/video/wayland/SDL_waylanddyn.h --- a/src/video/wayland/SDL_waylanddyn.h Fri Feb 05 00:27:11 2021 +0100 +++ b/src/video/wayland/SDL_waylanddyn.h Fri Feb 05 15:57:57 2021 -0500 @@ -39,6 +39,10 @@ #include "wayland-util.h" #include "xkbcommon/xkbcommon.h" +#ifdef HAVE_LIBDECORATION_H +#include +#endif + #ifdef __cplusplus extern "C" { @@ -64,7 +68,7 @@ #ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC -#ifdef _WAYLAND_CLIENT_H +#if defined(_WAYLAND_CLIENT_H) || defined(WAYLAND_CLIENT_H) #error Do not include wayland-client ahead of SDL_waylanddyn.h in dynamic loading mode #endif @@ -81,6 +85,8 @@ #define wl_proxy_add_listener (*WAYLAND_wl_proxy_add_listener) #define wl_proxy_marshal_constructor (*WAYLAND_wl_proxy_marshal_constructor) #define wl_proxy_marshal_constructor_versioned (*WAYLAND_wl_proxy_marshal_constructor_versioned) +#define wl_proxy_set_tag (*WAYLAND_wl_proxy_set_tag) +#define wl_proxy_get_tag (*WAYLAND_wl_proxy_get_tag) #define wl_seat_interface (*WAYLAND_wl_seat_interface) #define wl_surface_interface (*WAYLAND_wl_surface_interface) @@ -100,6 +106,30 @@ #define wl_data_source_interface (*WAYLAND_wl_data_source_interface) #define wl_data_device_manager_interface (*WAYLAND_wl_data_device_manager_interface) +#ifdef HAVE_LIBDECORATION_H +#define libdecor_unref (*WAYLAND_libdecor_unref) +#define libdecor_new (*WAYLAND_libdecor_new) +#define libdecor_decorate (*WAYLAND_libdecor_decorate) +#define libdecor_frame_unref (*WAYLAND_libdecor_frame_unref) +#define libdecor_frame_set_title (*WAYLAND_libdecor_frame_set_title) +#define libdecor_frame_set_app_id (*WAYLAND_libdecor_frame_set_app_id) +#define libdecor_frame_set_max_content_size (*WAYLAND_libdecor_frame_set_max_content_size) +#define libdecor_frame_set_min_content_size (*WAYLAND_libdecor_frame_set_min_content_size) +#define libdecor_frame_resize (*WAYLAND_libdecor_frame_resize) +#define libdecor_frame_move (*WAYLAND_libdecor_frame_move) +#define libdecor_frame_commit (*WAYLAND_libdecor_frame_commit) +#define libdecor_frame_set_minimized (*WAYLAND_libdecor_frame_set_minimized) +#define libdecor_frame_set_maximized (*WAYLAND_libdecor_frame_set_maximized) +#define libdecor_frame_set_fullscreen (*WAYLAND_libdecor_frame_set_fullscreen) +#define libdecor_frame_unset_fullscreen (*WAYLAND_libdecor_frame_unset_fullscreen) +#define libdecor_frame_set_capabilities (*WAYLAND_libdecor_frame_set_capabilities) +#define libdecor_frame_unset_capabilities (*WAYLAND_libdecor_frame_unset_capabilities) +#define libdecor_frame_map (*WAYLAND_libdecor_frame_map) +#define libdecor_state_new (*WAYLAND_libdecor_state_new) +#define libdecor_state_free (*WAYLAND_libdecor_state_free) +#define libdecor_configuration_get_content_size (*WAYLAND_libdecor_configuration_get_content_size) +#endif + #endif /* SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC */ #include "wayland-client-protocol.h" diff -r 60b9ce4ee73e -r 39998a600a1e src/video/wayland/SDL_waylandevents.c --- a/src/video/wayland/SDL_waylandevents.c Fri Feb 05 00:27:11 2021 +0100 +++ b/src/video/wayland/SDL_waylandevents.c Fri Feb 05 15:57:57 2021 -0500 @@ -314,6 +314,11 @@ return; } + /* check that this surface belongs to one of the SDL windows */ + if (!SDL_WAYLAND_own_surface(surface)) { + return; + } + /* This handler will be called twice in Wayland 1.4 * Once for the window surface which has valid user data * and again for the mouse cursor surface which does not have valid user data @@ -369,8 +374,18 @@ WL_SHELL_SURFACE_RESIZE_*), but the values are the same. */ const uint32_t *directions_zxdg = directions_wl; +#ifdef HAVE_LIBDECORATION_H + /* ditto for libdecoration. */ + const uint32_t *directions_libdecoration = directions_wl; +#endif + switch (rc) { case SDL_HITTEST_DRAGGABLE: +#ifdef HAVE_LIBDECORATION_H + if (input->display->shell.libdecoration) { + libdecor_frame_move(window_data->shell_surface.libdecoration.frame, input->seat, serial); + } else +#endif if (input->display->shell.xdg) { xdg_toplevel_move(window_data->shell_surface.xdg.roleobj.toplevel, input->seat, serial); } else if (input->display->shell.zxdg) { @@ -388,6 +403,11 @@ case SDL_HITTEST_RESIZE_BOTTOM: case SDL_HITTEST_RESIZE_BOTTOMLEFT: case SDL_HITTEST_RESIZE_LEFT: +#ifdef HAVE_LIBDECORATION_H + if (input->display->shell.libdecoration) { + libdecor_frame_resize(window_data->shell_surface.libdecoration.frame, input->seat, serial, directions_libdecoration[rc - SDL_HITTEST_RESIZE_TOPLEFT]); + } else +#endif if (input->display->shell.xdg) { xdg_toplevel_resize(window_data->shell_surface.xdg.roleobj.toplevel, input->seat, serial, directions_zxdg[rc - SDL_HITTEST_RESIZE_TOPLEFT]); } else if (input->display->shell.zxdg) { diff -r 60b9ce4ee73e -r 39998a600a1e src/video/wayland/SDL_waylandsym.h --- a/src/video/wayland/SDL_waylandsym.h Fri Feb 05 00:27:11 2021 +0100 +++ b/src/video/wayland/SDL_waylandsym.h Fri Feb 05 15:57:57 2021 -0500 @@ -71,6 +71,10 @@ SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_10) SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_marshal_constructor_versioned, (struct wl_proxy *proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, ...)) +SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_18) +SDL_WAYLAND_SYM(void, wl_proxy_set_tag, (struct wl_proxy *, const char * const *)) +SDL_WAYLAND_SYM(const char * const *, wl_proxy_get_tag, (struct wl_proxy *)) + SDL_WAYLAND_INTERFACE(wl_seat_interface) SDL_WAYLAND_INTERFACE(wl_surface_interface) SDL_WAYLAND_INTERFACE(wl_shm_pool_interface) @@ -119,6 +123,50 @@ xkb_layout_index_t latched_layout,\ xkb_layout_index_t locked_layout) ) +#ifdef HAVE_LIBDECORATION_H +SDL_WAYLAND_MODULE(WAYLAND_LIBDECORATION) +SDL_WAYLAND_SYM(void, libdecor_unref, (struct libdecor *)) +SDL_WAYLAND_SYM(struct libdecor *, libdecor_new, (struct wl_display *, struct libdecor_interface *)) +SDL_WAYLAND_SYM(struct libdecor_frame *, libdecor_decorate, (struct libdecor *,\ + struct wl_surface *,\ + struct libdecor_frame_interface *,\ + void *)) +SDL_WAYLAND_SYM(void, libdecor_frame_unref, (struct libdecor_frame *)) +SDL_WAYLAND_SYM(void, libdecor_frame_set_title, (struct libdecor_frame *, const char *)) +SDL_WAYLAND_SYM(void, libdecor_frame_set_app_id, (struct libdecor_frame *, const char *)) +SDL_WAYLAND_SYM(void, libdecor_frame_set_max_content_size, (struct libdecor_frame *frame,\ + int content_width,\ + int content_height)) +SDL_WAYLAND_SYM(void, libdecor_frame_set_min_content_size, (struct libdecor_frame *frame,\ + int content_width,\ + int content_height)) +SDL_WAYLAND_SYM(void, libdecor_frame_resize, (struct libdecor_frame *,\ + struct wl_seat *,\ + uint32_t,\ + enum libdecor_resize_edge)) +SDL_WAYLAND_SYM(void, libdecor_frame_move, (struct libdecor_frame *,\ + struct wl_seat *,\ + uint32_t)) +SDL_WAYLAND_SYM(void, libdecor_frame_commit, (struct libdecor_frame *,\ + struct libdecor_state *,\ + struct libdecor_configuration *)) +SDL_WAYLAND_SYM(void, libdecor_frame_set_minimized, (struct libdecor_frame *)) +SDL_WAYLAND_SYM(void, libdecor_frame_set_maximized, (struct libdecor_frame *)) +SDL_WAYLAND_SYM(void, libdecor_frame_set_fullscreen, (struct libdecor_frame *, struct wl_output *)) +SDL_WAYLAND_SYM(void, libdecor_frame_unset_fullscreen, (struct libdecor_frame *)) +SDL_WAYLAND_SYM(void, libdecor_frame_set_capabilities, (struct libdecor_frame *, \ + enum libdecor_capabilities)) +SDL_WAYLAND_SYM(void, libdecor_frame_unset_capabilities, (struct libdecor_frame *, \ + enum libdecor_capabilities)) +SDL_WAYLAND_SYM(void, libdecor_frame_map, (struct libdecor_frame *)) +SDL_WAYLAND_SYM(struct libdecor_state *, libdecor_state_new, (int, int)) +SDL_WAYLAND_SYM(void, libdecor_state_free, (struct libdecor_state *)) +SDL_WAYLAND_SYM(uint8_t, libdecor_configuration_get_content_size, (struct libdecor_configuration *,\ + struct libdecor_frame *,\ + int *,\ + int *)) +#endif + #undef SDL_WAYLAND_MODULE #undef SDL_WAYLAND_SYM #undef SDL_WAYLAND_INTERFACE diff -r 60b9ce4ee73e -r 39998a600a1e src/video/wayland/SDL_waylandvideo.c --- a/src/video/wayland/SDL_waylandvideo.c Fri Feb 05 00:27:11 2021 +0100 +++ b/src/video/wayland/SDL_waylandvideo.c Fri Feb 05 15:57:57 2021 -0500 @@ -206,6 +206,9 @@ device->SetWindowBordered = Wayland_SetWindowBordered; device->SetWindowResizable = Wayland_SetWindowResizable; device->SetWindowSize = Wayland_SetWindowSize; + device->SetWindowMinimumSize = Wayland_SetWindowMinimumSize; + device->SetWindowMaximumSize = Wayland_SetWindowMaximumSize; + device->GetWindowBordersSize = Wayland_GetWindowBordersSize; device->SetWindowTitle = Wayland_SetWindowTitle; device->DestroyWindow = Wayland_DestroyWindow; device->SetWindowHitTest = Wayland_SetWindowHitTest; @@ -384,6 +387,21 @@ }; +#ifdef HAVE_LIBDECORATION_H +static void +libdecoration_error(struct libdecor *context, + enum libdecor_error error, + const char *message) +{ + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "libdecoration error (%d): %s\n", error, message); +} + +static struct libdecor_interface libdecoration_interface = { + libdecoration_error, +}; +#endif + + static void display_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) @@ -471,6 +489,13 @@ Wayland_InitMouse(); +#ifdef HAVE_LIBDECORATION_H + /* FIXME libdecoration: Shouldn't we check for other types first? */ + if (SDL_WAYLAND_HAVE_WAYLAND_LIBDECORATION) { + data->shell.libdecoration = libdecor_new(data->display, &libdecoration_interface); + } +#endif + /* Get the surface class name, usually the name of the application */ data->classname = get_classname(); @@ -559,6 +584,13 @@ if (data->shell.zxdg) zxdg_shell_v6_destroy(data->shell.zxdg); +#ifdef HAVE_LIBDECORATION_H + if (data->shell.libdecoration) { + libdecor_unref(data->shell.libdecoration); + data->shell.libdecoration = NULL; + } +#endif + if (data->compositor) wl_compositor_destroy(data->compositor); diff -r 60b9ce4ee73e -r 39998a600a1e src/video/wayland/SDL_waylandvideo.h --- a/src/video/wayland/SDL_waylandvideo.h Fri Feb 05 00:27:11 2021 +0100 +++ b/src/video/wayland/SDL_waylandvideo.h Fri Feb 05 15:57:57 2021 -0500 @@ -61,6 +61,9 @@ struct xdg_wm_base *xdg; struct zxdg_shell_v6 *zxdg; struct wl_shell *wl; +#ifdef HAVE_LIBDECORATION_H + struct libdecor *libdecoration; +#endif } shell; struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; struct zwp_pointer_constraints_v1 *pointer_constraints; diff -r 60b9ce4ee73e -r 39998a600a1e src/video/wayland/SDL_waylandwindow.c --- a/src/video/wayland/SDL_waylandwindow.c Fri Feb 05 00:27:11 2021 +0100 +++ b/src/video/wayland/SDL_waylandwindow.c Fri Feb 05 15:57:57 2021 -0500 @@ -39,6 +39,16 @@ #include "org-kde-kwin-server-decoration-manager-client-protocol.h" #include "idle-inhibit-unstable-v1-client-protocol.h" +static const char *SDL_WAYLAND_surface_tag = "sdl-window"; + +SDL_bool SDL_WAYLAND_own_surface(struct wl_surface *surface) +{ + if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT_1_18) { + return wl_proxy_get_tag((struct wl_proxy *) surface) == &SDL_WAYLAND_surface_tag; + } + return SDL_TRUE; /* For older clients we have to assume this is us... */ +} + static float get_window_scale_factor(SDL_Window *window) { return ((SDL_WindowData*)window->driverdata)->scale_factor; } @@ -49,6 +59,15 @@ SDL_WindowData *wind = window->driverdata; SDL_VideoData *viddata = wind->waylandData; +#ifdef HAVE_LIBDECORATION_H + if (viddata->shell.libdecoration) { + if (output) { + libdecor_frame_set_fullscreen(wind->shell_surface.libdecoration.frame, output); + } else { + libdecor_frame_unset_fullscreen(wind->shell_surface.libdecoration.frame); + } + } else +#endif if (viddata->shell.xdg) { if (output) { xdg_toplevel_set_fullscreen(wind->shell_surface.xdg.roleobj.toplevel, output); @@ -372,6 +391,65 @@ +#ifdef HAVE_LIBDECORATION_H +static void +libdecoration_frame_configure(struct libdecor_frame *frame, + struct libdecor_configuration *configuration, + void *user_data) +{ + SDL_WindowData *wind = user_data; + SDL_Window *window = wind->sdlwindow; + int width, height; + struct libdecor_state *state; + + /* window size */ + if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) { + width = window->w; + height = window->h; + } + + wind->resize.width = width; + wind->resize.height = height; + + wind->resize.pending = SDL_TRUE; + wind->resize.configure = SDL_TRUE; + Wayland_HandlePendingResize(window); + wind->shell_surface.libdecoration.initial_configure_seen = SDL_TRUE; + + window->w = wind->resize.width; + window->h = wind->resize.height; + + state = libdecor_state_new(width, height); + libdecor_frame_commit(frame, state, configuration); + libdecor_state_free(state); + + Wayland_SetWindowResizable(SDL_GetVideoDevice(), window, + window->flags & SDL_WINDOW_RESIZABLE); +} + +static void +libdecoration_frame_close(struct libdecor_frame *frame, + void *user_data) +{ + SDL_SendWindowEvent(((SDL_WindowData *)user_data)->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0); +} + +static void +libdecoration_frame_commit(void *user_data) +{ + /* No-op */ +} + +static struct libdecor_frame_interface libdecoration_frame_interface = { + libdecoration_frame_configure, + libdecoration_frame_close, + libdecoration_frame_commit, +}; +#endif + + + + #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH static void handle_onscreen_visibility(void *data, @@ -622,6 +700,11 @@ { SDL_WindowData *wind = window->driverdata; const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata; +#ifdef HAVE_LIBDECORATION_H + if (viddata->shell.libdecoration) { + SDL_SetError("FIXME libdecoration: Implement toggling decorations"); + } else +#endif if ((viddata->decoration_manager) && (wind->server_decoration)) { const enum zxdg_toplevel_decoration_v1_mode mode = bordered ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; zxdg_toplevel_decoration_v1_set_mode(wind->server_decoration, mode); @@ -634,11 +717,21 @@ void Wayland_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable) { - /* No-op, this is handled by the xdg-shell/wl_shell callbacks. - * Also note that we do NOT implement SetMaximumSize/SetMinimumSize, as - * those are also no-ops for the same reason, but SDL_video.c does not - * require a driver implementation. + /* No-op for non-libdecoration. + * This is handled by the xdg-shell/wl_shell callbacks. */ + +#ifdef HAVE_LIBDECORATION_H + SDL_WindowData *wind = window->driverdata; + SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata; + if (viddata->shell.libdecoration) { + if (resizable) { + libdecor_frame_set_capabilities(wind->shell_surface.libdecoration.frame, LIBDECOR_ACTION_RESIZE); + } else { + libdecor_frame_unset_capabilities(wind->shell_surface.libdecoration.frame, LIBDECOR_ACTION_RESIZE); + } + } +#endif } void @@ -647,6 +740,11 @@ SDL_WindowData *wind = window->driverdata; SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata; +#ifdef HAVE_LIBDECORATION_H + if (viddata->shell.libdecoration) { + libdecor_frame_set_maximized(wind->shell_surface.libdecoration.frame); + } else +#endif if (viddata->shell.xdg) { xdg_toplevel_set_maximized(wind->shell_surface.xdg.roleobj.toplevel); } else if (viddata->shell.zxdg) { @@ -664,6 +762,11 @@ SDL_WindowData *wind = window->driverdata; SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata; +#ifdef HAVE_LIBDECORATION_H + if (viddata->shell.libdecoration) { + libdecor_frame_set_minimized(wind->shell_surface.libdecoration.frame); + } else +#endif if (viddata->shell.xdg) { xdg_toplevel_set_minimized(wind->shell_surface.xdg.roleobj.toplevel); } else if (viddata->shell.zxdg) { @@ -751,6 +854,24 @@ wl_compositor_create_surface(c->compositor); wl_surface_add_listener(data->surface, &surface_listener, data); + if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT_1_18) { + wl_proxy_set_tag((struct wl_proxy *)data->surface, &SDL_WAYLAND_surface_tag); + } + +#ifdef HAVE_LIBDECORATION_H + if (c->shell.libdecoration) { + data->shell_surface.libdecoration.frame = libdecor_decorate(c->shell.libdecoration, + data->surface, + &libdecoration_frame_interface, + data); + if (data->shell_surface.libdecoration.frame == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Failed to create libdecoration frame!"); + } else { + libdecor_frame_set_app_id(data->shell_surface.libdecoration.frame, c->classname); + libdecor_frame_map(data->shell_surface.libdecoration.frame); + } + } else +#endif if (c->shell.xdg) { data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface); /* !!! FIXME: add popup role */ @@ -845,6 +966,16 @@ /* we have to wait until the surface gets a "configure" event, or use of this surface will fail. This is a new rule for xdg_shell. */ +#ifdef HAVE_LIBDECORATION_H + if (c->shell.libdecoration) { + if (data->shell_surface.libdecoration.frame) { + while (!data->shell_surface.libdecoration.initial_configure_seen) { + WAYLAND_wl_display_flush(c->display); + WAYLAND_wl_display_dispatch(c->display); + } + } + } else +#endif if (c->shell.xdg) { if (data->shell_surface.xdg.surface) { while (!data->shell_surface.xdg.initial_configure_seen) { @@ -889,6 +1020,11 @@ } if (data->resize.configure) { +#ifdef HAVE_LIBDECORATION_H + if (data->waylandData->shell.libdecoration) { + /* this has already been acknowledged in the the frames's 'configure' callback */ + } else +#endif if (data->waylandData->shell.xdg) { xdg_surface_ack_configure(data->shell_surface.xdg.surface, data->resize.serial); } else if (data->waylandData->shell.zxdg) { @@ -906,6 +1042,42 @@ } } +void +Wayland_SetWindowMinimumSize(_THIS, SDL_Window * window) +{ + /* No-op for non-libdecoration. + * This is handled by the xdg-shell/wl_shell callbacks. + */ + +#ifdef HAVE_LIBDECORATION_H + SDL_WindowData *wind = window->driverdata; + SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata; + if (viddata->shell.libdecoration) { + libdecor_frame_set_min_content_size(wind->shell_surface.libdecoration.frame, + window->min_w, + window->min_h); + } +#endif +} + +void +Wayland_SetWindowMaximumSize(_THIS, SDL_Window * window) +{ + /* No-op for non-libdecoration. + * This is handled by the xdg-shell/wl_shell callbacks. + */ + +#ifdef HAVE_LIBDECORATION_H + SDL_WindowData *wind = window->driverdata; + SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata; + if (viddata->shell.libdecoration) { + libdecor_frame_set_max_content_size(wind->shell_surface.libdecoration.frame, + window->max_w, + window->max_h); + } +#endif +} + void Wayland_SetWindowSize(_THIS, SDL_Window * window) { SDL_VideoData *data = _this->driverdata; @@ -924,12 +1096,37 @@ wl_region_destroy(region); } +int +Wayland_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right) +{ +#ifdef HAVE_LIBDECORATION_H + SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata; + if (viddata->shell.libdecoration) { + *top = 0; + *left = 0; + *bottom = 0; + *right = 0; + return SDL_SetError("FIXME libdecoration: Support GetWindowBordersSize"); + } +#endif + *top = 0; + *left = 0; + *bottom = 0; + *right = 0; + return SDL_SetError("This Wayland instance does not support GetWindowBordersSize!"); +} + void Wayland_SetWindowTitle(_THIS, SDL_Window * window) { SDL_WindowData *wind = window->driverdata; SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata; - + if (window->title != NULL) { +#ifdef HAVE_LIBDECORATION_H + if (viddata->shell.libdecoration) { + libdecor_frame_set_title(wind->shell_surface.libdecoration.frame, window->title); + } else +#endif if (viddata->shell.xdg) { xdg_toplevel_set_title(wind->shell_surface.xdg.roleobj.toplevel, window->title); } else if (viddata->shell.zxdg) { @@ -1005,6 +1202,13 @@ zwp_idle_inhibitor_v1_destroy(wind->idle_inhibitor); } +#ifdef HAVE_LIBDECORATION_H + if (data->shell.libdecoration) { + if (wind->shell_surface.libdecoration.frame) { + libdecor_frame_unref(wind->shell_surface.libdecoration.frame); + } + } else +#endif if (data->shell.xdg) { if (wind->shell_surface.xdg.roleobj.toplevel) { xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel); diff -r 60b9ce4ee73e -r 39998a600a1e src/video/wayland/SDL_waylandwindow.h --- a/src/video/wayland/SDL_waylandwindow.h Fri Feb 05 00:27:11 2021 +0100 +++ b/src/video/wayland/SDL_waylandwindow.h Fri Feb 05 15:57:57 2021 -0500 @@ -50,6 +50,13 @@ SDL_bool initial_configure_seen; } SDL_xdg_shell_surface; +#ifdef HAVE_LIBDECORATION_H +typedef struct { + struct libdecor_frame *frame; + SDL_bool initial_configure_seen; +} SDL_libdecoration_surface; +#endif + typedef struct { SDL_Window *sdlwindow; SDL_VideoData *waylandData; @@ -57,6 +64,9 @@ union { SDL_xdg_shell_surface xdg; SDL_zxdg_shell_surface zxdg; +#ifdef HAVE_LIBDECORATION_H + SDL_libdecoration_surface libdecoration; +#endif struct wl_shell_surface *wl; } shell_surface; struct wl_egl_window *egl_window; @@ -98,6 +108,9 @@ extern void Wayland_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable); extern int Wayland_CreateWindow(_THIS, SDL_Window *window); extern void Wayland_SetWindowSize(_THIS, SDL_Window * window); +extern void Wayland_SetWindowMinimumSize(_THIS, SDL_Window * window); +extern void Wayland_SetWindowMaximumSize(_THIS, SDL_Window * window); +extern int Wayland_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right); extern void Wayland_SetWindowTitle(_THIS, SDL_Window * window); extern void Wayland_DestroyWindow(_THIS, SDL_Window *window); extern void Wayland_SuspendScreenSaver(_THIS); @@ -108,6 +121,8 @@ extern void Wayland_HandlePendingResize(SDL_Window *window); +extern SDL_bool SDL_WAYLAND_own_surface(struct wl_surface *surface); + #endif /* SDL_waylandwindow_h_ */ /* vi: set ts=4 sw=4 expandtab: */