Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wayland: Fix toggling fullscreen with fixed-size windows #4285

Merged
merged 2 commits into from
Apr 7, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 62 additions & 106 deletions src/video/wayland/SDL_waylandwindow.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,60 @@ static float get_window_scale_factor(SDL_Window *window) {
return ((SDL_WindowData*)window->driverdata)->scale_factor;
}

static void
CommitMinMaxDimensions(SDL_Window *window)
{
SDL_WindowData *wind = window->driverdata;
SDL_VideoData *data = wind->waylandData;
int min_width, min_height, max_width, max_height;

if (window->flags & SDL_WINDOW_FULLSCREEN) {
min_width = 0;
min_height = 0;
max_width = 0;
max_height = 0;
} else if (window->flags & SDL_WINDOW_RESIZABLE) {
min_width = window->min_w;
min_height = window->min_h;
max_width = window->max_w;
max_height = window->max_h;
} else {
min_width = window->w;
min_height = window->h;
max_width = window->w;
max_height = window->h;
}

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);
}

wl_surface_commit(wind->surface);
}

static void
SetFullscreen(SDL_Window *window, struct wl_output *output)
{
SDL_WindowData *wind = window->driverdata;
SDL_VideoData *viddata = wind->waylandData;

/* The desktop may try to enforce min/max sizes here, so turn them off for
* fullscreen and on (if applicable) for windowed
*/
CommitMinMaxDimensions(window);

if (viddata->shell.xdg) {
if (output) {
xdg_toplevel_set_fullscreen(wind->shell_surface.xdg.roleobj.toplevel, output);
Expand Down Expand Up @@ -202,8 +250,8 @@ handle_configure_zxdg_toplevel(void *data,
if (!fullscreen) {
if (window->flags & SDL_WINDOW_FULLSCREEN) {
/* We might need to re-enter fullscreen after being restored from minimized */
struct wl_output *output = (struct wl_output *) window->fullscreen_mode.driverdata;
SetFullscreen(window, output);
SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata;
SetFullscreen(window, driverdata->output);
}

if (width == 0 || height == 0) {
Expand Down Expand Up @@ -313,13 +361,13 @@ handle_configure_xdg_toplevel(void *data,
if (*state == XDG_TOPLEVEL_STATE_FULLSCREEN) {
fullscreen = SDL_TRUE;
}
}
}

if (!fullscreen) {
if (window->flags & SDL_WINDOW_FULLSCREEN) {
/* We might need to re-enter fullscreen after being restored from minimized */
struct wl_output *output = (struct wl_output *) window->fullscreen_mode.driverdata;
SetFullscreen(window, output);
SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata;
SetFullscreen(window, driverdata->output);
}

if (width == 0 || height == 0) {
Expand Down Expand Up @@ -413,8 +461,8 @@ update_scale_factor(SDL_WindowData *window) {
new_factor = old_factor;
}

if (FULLSCREEN_VISIBLE(window->sdlwindow) && window->sdlwindow->fullscreen_mode.driverdata) {
SDL_VideoDisplay *display = wl_output_get_user_data(window->sdlwindow->fullscreen_mode.driverdata);
if (FULLSCREEN_VISIBLE(window->sdlwindow)) {
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window->sdlwindow);
SDL_WaylandOutputData* driverdata = display->driverdata;
new_factor = driverdata->scale_factor;
}
Expand Down Expand Up @@ -524,8 +572,8 @@ Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)

void Wayland_ShowWindow(_THIS, SDL_Window *window)
{
struct wl_output *output = (struct wl_output *) window->fullscreen_mode.driverdata;
SetFullscreen(window, (window->flags & SDL_WINDOW_FULLSCREEN) ? output : NULL);
SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata;
SetFullscreen(window, (window->flags & SDL_WINDOW_FULLSCREEN) ? driverdata->output : NULL);
}

#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
Expand Down Expand Up @@ -634,40 +682,7 @@ Wayland_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
void
Wayland_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
{
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);
}
CommitMinMaxDimensions(window);
}

void
Expand Down Expand Up @@ -786,28 +801,12 @@ 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);
Expand Down Expand Up @@ -885,7 +884,8 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
Wayland_input_lock_pointer(c->input);
}

wl_surface_commit(data->surface);
/* This will call wl_surface_commit */
CommitMinMaxDimensions(window);
WAYLAND_wl_display_flush(c->display);

/* we have to wait until the surface gets a "configure" event, or
Expand Down Expand Up @@ -954,39 +954,13 @@ 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);
}
}
CommitMinMaxDimensions(window);
}

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);
}
}
CommitMinMaxDimensions(window);
}

void Wayland_SetWindowSize(_THIS, SDL_Window * window)
Expand All @@ -995,24 +969,6 @@ void Wayland_SetWindowSize(_THIS, SDL_Window * window)
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) {
Expand Down