From 57a927e8d7f4290c7aa696c86144ac88c3bcac3d Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Fri, 12 Feb 2021 14:27:58 -0500 Subject: [PATCH] wayland: Explicitly set min/max size for xdg-shell --- src/video/wayland/SDL_waylandvideo.c | 2 + src/video/wayland/SDL_waylandwindow.c | 111 ++++++++++++++++++++++++-- src/video/wayland/SDL_waylandwindow.h | 2 + 3 files changed, 110 insertions(+), 5 deletions(-) diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 3ddeef08b..95b1af936 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -206,6 +206,8 @@ Wayland_CreateDevice(int devindex) device->SetWindowBordered = Wayland_SetWindowBordered; device->SetWindowResizable = Wayland_SetWindowResizable; device->SetWindowSize = Wayland_SetWindowSize; + device->SetWindowMinimumSize = Wayland_SetWindowMinimumSize; + device->SetWindowMaximumSize = Wayland_SetWindowMaximumSize; device->SetWindowTitle = Wayland_SetWindowTitle; device->DestroyWindow = Wayland_DestroyWindow; device->SetWindowHitTest = Wayland_SetWindowHitTest; diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 90e3928c9..5491d2dbf 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -634,11 +634,40 @@ Wayland_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered) 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. - */ + int min_width, min_height, max_width, max_height; + SDL_VideoData *data = _this->driverdata; + SDL_WindowData *wind = window->driverdata; + + if (resizable) { + /* FIXME: Is there a better way to get max window size from Wayland? -flibit */ + const int maxsize = 0x7FFFFFFF; + min_width = window->min_w; + min_height = window->min_h; + max_width = (window->max_w == 0) ? maxsize : window->max_w; + max_height = (window->max_h == 0) ? maxsize : window->max_h; + } else { + min_width = window->w; + min_height = window->h; + max_width = window->w; + max_height = window->h; + } + + /* Note that this is also handled by the xdg-shell/wl_shell callbacks! */ + if (data->shell.xdg) { + xdg_toplevel_set_min_size(wind->shell_surface.xdg.roleobj.toplevel, + min_width, + min_height); + xdg_toplevel_set_max_size(wind->shell_surface.xdg.roleobj.toplevel, + max_width, + max_height); + } else if (data->shell.zxdg) { + zxdg_toplevel_v6_set_min_size(wind->shell_surface.zxdg.roleobj.toplevel, + min_width, + min_height); + zxdg_toplevel_v6_set_max_size(wind->shell_surface.zxdg.roleobj.toplevel, + max_width, + max_height); + } } void @@ -757,12 +786,28 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window) data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface); xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data); xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname); + if (!(window->flags & SDL_WINDOW_RESIZABLE)) { + xdg_toplevel_set_min_size(data->shell_surface.xdg.roleobj.toplevel, + window->w, + window->h); + xdg_toplevel_set_max_size(data->shell_surface.xdg.roleobj.toplevel, + window->w, + window->h); + } } else if (c->shell.zxdg) { data->shell_surface.zxdg.surface = zxdg_shell_v6_get_xdg_surface(c->shell.zxdg, data->surface); /* !!! FIXME: add popup role */ data->shell_surface.zxdg.roleobj.toplevel = zxdg_surface_v6_get_toplevel(data->shell_surface.zxdg.surface); zxdg_toplevel_v6_add_listener(data->shell_surface.zxdg.roleobj.toplevel, &toplevel_listener_zxdg, data); zxdg_toplevel_v6_set_app_id(data->shell_surface.zxdg.roleobj.toplevel, c->classname); + if (!(window->flags & SDL_WINDOW_RESIZABLE)) { + zxdg_toplevel_v6_set_min_size(data->shell_surface.zxdg.roleobj.toplevel, + window->w, + window->h); + zxdg_toplevel_v6_set_max_size(data->shell_surface.zxdg.roleobj.toplevel, + window->w, + window->h); + } } else { data->shell_surface.wl = wl_shell_get_shell_surface(c->shell.wl, data->surface); wl_shell_surface_set_class(data->shell_surface.wl, c->classname); @@ -906,12 +951,68 @@ Wayland_HandlePendingResize(SDL_Window *window) } } +void +Wayland_SetWindowMinimumSize(_THIS, SDL_Window * window) +{ + SDL_VideoData *data = _this->driverdata; + SDL_WindowData *wind = window->driverdata; + + if (window->flags & SDL_WINDOW_RESIZABLE) { + if (data->shell.xdg) { + xdg_toplevel_set_min_size(wind->shell_surface.xdg.roleobj.toplevel, + window->min_w, + window->min_h); + } else if (data->shell.zxdg) { + zxdg_toplevel_v6_set_min_size(wind->shell_surface.zxdg.roleobj.toplevel, + window->min_w, + window->min_h); + } + } +} + +void +Wayland_SetWindowMaximumSize(_THIS, SDL_Window * window) +{ + SDL_VideoData *data = _this->driverdata; + SDL_WindowData *wind = window->driverdata; + + if (window->flags & SDL_WINDOW_RESIZABLE) { + if (data->shell.xdg) { + xdg_toplevel_set_max_size(wind->shell_surface.xdg.roleobj.toplevel, + window->max_w, + window->max_h); + } else if (data->shell.zxdg) { + zxdg_toplevel_v6_set_max_size(wind->shell_surface.zxdg.roleobj.toplevel, + window->max_w, + window->max_h); + } + } +} + void Wayland_SetWindowSize(_THIS, SDL_Window * window) { SDL_VideoData *data = _this->driverdata; SDL_WindowData *wind = window->driverdata; struct wl_region *region; + if (!(window->flags & SDL_WINDOW_RESIZABLE)) { + if (data->shell.xdg) { + xdg_toplevel_set_min_size(wind->shell_surface.xdg.roleobj.toplevel, + window->w, + window->h); + xdg_toplevel_set_max_size(wind->shell_surface.xdg.roleobj.toplevel, + window->w, + window->h); + } else if (data->shell.zxdg) { + zxdg_toplevel_v6_set_min_size(wind->shell_surface.zxdg.roleobj.toplevel, + window->w, + window->h); + zxdg_toplevel_v6_set_max_size(wind->shell_surface.zxdg.roleobj.toplevel, + window->w, + window->h); + } + } + wl_surface_set_buffer_scale(wind->surface, get_window_scale_factor(window)); if (wind->egl_window) { diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index adaa9dbfd..1545655a4 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -98,6 +98,8 @@ extern void Wayland_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool borde 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 void Wayland_SetWindowTitle(_THIS, SDL_Window * window); extern void Wayland_DestroyWindow(_THIS, SDL_Window *window); extern void Wayland_SuspendScreenSaver(_THIS);