From 7def1438c340d779642ba21052ffe263f7a491d9 Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Wed, 1 Feb 2023 11:18:03 -0500
Subject: [PATCH] wayland: Refactor for video core changes
Accommodate the new video core changes.
The new video core changes allow for some window geometry calculation refactoring that simplify the system:
- Removal of helper functions
- Eliminate some discrepancies between the libdecor and xdg-toplevel paths
- No need to short-circuit the video core window size event deduplication check
- Exclusive fullscreen windows will always end up on the correct output, even when fullscreen is initiated from the compositor
- Better handling of cases where the desktop is scaled, but does not expose the viewport protocol
- Return the display bounds for the emulated mode if an exclusive fullscreen window has focus
- Fixed cases where changing display properties during runtime wouldn't update the display mode lists
- General cleanup
---
src/video/wayland/SDL_waylandvideo.c | 148 +++++-----
src/video/wayland/SDL_waylandwindow.c | 385 ++++++++++----------------
src/video/wayland/SDL_waylandwindow.h | 9 +-
3 files changed, 235 insertions(+), 307 deletions(-)
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index e1bf8c8a5afe..1575f78270de 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -361,7 +361,7 @@ static const struct zxdg_output_v1_listener xdg_output_listener = {
xdg_output_handle_description,
};
-static void AddEmulatedModes(SDL_VideoDisplay *dpy, SDL_bool rot_90)
+static void AddEmulatedModes(SDL_DisplayData *dispdata, SDL_bool rot_90)
{
struct EmulatedMode
{
@@ -413,8 +413,9 @@ static void AddEmulatedModes(SDL_VideoDisplay *dpy, SDL_bool rot_90)
int i;
SDL_DisplayMode mode;
- const int native_width = dpy->desktop_mode.pixel_w;
- const int native_height = dpy->desktop_mode.pixel_h;
+ SDL_VideoDisplay *dpy = dispdata->display ? SDL_GetVideoDisplay(dispdata->display) : &dispdata->placeholder;
+ const int native_width = dispdata->pixel_width;
+ const int native_height = dispdata->pixel_height;
for (i = 0; i < SDL_arraysize(mode_list); ++i) {
SDL_zero(mode);
@@ -423,18 +424,19 @@ static void AddEmulatedModes(SDL_VideoDisplay *dpy, SDL_bool rot_90)
mode.refresh_rate = dpy->desktop_mode.refresh_rate;
mode.driverdata = dpy->desktop_mode.driverdata;
- if (rot_90) {
- mode.pixel_w = mode_list[i].h;
- mode.pixel_h = mode_list[i].w;
- } else {
- mode.pixel_w = mode_list[i].w;
- mode.pixel_h = mode_list[i].h;
- }
-
/* Only add modes that are smaller than the native mode. */
- if ((mode.pixel_w < native_width && mode.pixel_h < native_height) ||
- (mode.pixel_w < native_width && mode.pixel_h == native_height) ||
- (mode.pixel_w == native_width && mode.pixel_h < native_height)) {
+ if ((mode_list[i].w < native_width && mode_list[i].h < native_height) ||
+ (mode_list[i].w < native_width && mode_list[i].h == native_height) ||
+ (mode_list[i].w == native_width && mode_list[i].h < native_height)) {
+
+ if (rot_90) {
+ mode.pixel_w = mode_list[i].h;
+ mode.pixel_h = mode_list[i].w;
+ } else {
+ mode.pixel_w = mode_list[i].w;
+ mode.pixel_h = mode_list[i].h;
+ }
+
SDL_AddFullscreenDisplayMode(dpy, &mode);
}
}
@@ -452,22 +454,6 @@ static void display_handle_geometry(void *data,
{
SDL_DisplayData *driverdata = (SDL_DisplayData *)data;
- SDL_VideoDisplay *display;
- int i;
-
- if (driverdata->wl_output_done_count) {
- /* Clear the wl_output ref so Reset doesn't free it */
- display = SDL_GetVideoDisplay(driverdata->display);
- for (i = 0; i < display->num_fullscreen_modes; ++i) {
- display->fullscreen_modes[i].driverdata = NULL;
- }
-
- /* Okay, now it's safe to reset */
- SDL_ResetFullscreenDisplayModes(display);
-
- /* The display has officially started over. */
- driverdata->wl_output_done_count = 0;
- }
/* Apply the change from wl-output only if xdg-output is not supported */
if (!driverdata->has_logical_position) {
@@ -558,14 +544,29 @@ static void display_handle_done(void *data,
driverdata->wl_output_done_count = SDL_min(driverdata->wl_output_done_count + 1, event_await_count + 1);
- if (driverdata->wl_output_done_count != event_await_count) {
+ if (driverdata->wl_output_done_count < event_await_count) {
return;
}
+ /* If the display was already created, reset and rebuild the mode list. */
+ if (driverdata->display != 0) {
+ int i;
+ dpy = SDL_GetVideoDisplay(driverdata->display);
+
+ /* Clear the wl_output ref so Reset doesn't free it */
+ for (i = 0; i < dpy->num_fullscreen_modes; ++i) {
+ dpy->fullscreen_modes[i].driverdata = NULL;
+ }
+
+ /* Okay, now it's safe to reset */
+ SDL_ResetFullscreenDisplayModes(dpy);
+ }
+
/* The native display resolution */
SDL_zero(native_mode);
native_mode.format = SDL_PIXELFORMAT_RGB888;
+ /* Transform the pixel values, if necessary. */
if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
native_mode.pixel_w = driverdata->pixel_height;
native_mode.pixel_h = driverdata->pixel_width;
@@ -577,27 +578,29 @@ static void display_handle_done(void *data,
native_mode.refresh_rate = ((100 * driverdata->refresh) / 1000) / 100.0f; /* mHz to Hz */
native_mode.driverdata = driverdata->output;
- /* The scaled desktop mode */
- SDL_zero(desktop_mode);
- desktop_mode.format = SDL_PIXELFORMAT_RGB888;
-
- if (driverdata->has_logical_size) { /* If xdg-output is present, calculate the true scale of the desktop */
+ if (driverdata->has_logical_size) { /* If xdg-output is present... */
if (video->viewporter) {
+ /* ...and viewports are supported, calculate the true scale of the output. */
driverdata->scale_factor = (float)native_mode.pixel_w / (float)driverdata->screen_width;
+ } else {
+ /* ...otherwise, the 'native' pixel values are a multiple of the logical screen size. */
+ driverdata->pixel_width = driverdata->screen_width * (int)driverdata->scale_factor;
+ driverdata->pixel_height = driverdata->screen_height * (int)driverdata->scale_factor;
}
- } else { /* Scale the desktop coordinates, if xdg-output isn't present */
- driverdata->screen_width /= driverdata->scale_factor;
- driverdata->screen_height /= driverdata->scale_factor;
- }
-
- /* xdg-output dimensions are already transformed, so no need to rotate. */
- if (driverdata->has_logical_size || !(driverdata->transform & WL_OUTPUT_TRANSFORM_90)) {
- desktop_mode.pixel_w = driverdata->pixel_width;
- desktop_mode.pixel_h = driverdata->pixel_height;
} else {
- desktop_mode.pixel_w = driverdata->pixel_height;
- desktop_mode.pixel_h = driverdata->pixel_width;
+ /* Calculate the screen coordinates from the pixel values, if xdg-output isn't present.
+ * Use the native mode pixel values since they are pre-transformed.
+ */
+ driverdata->screen_width = native_mode.pixel_w / (int)driverdata->scale_factor;
+ driverdata->screen_height = native_mode.pixel_h / (int)driverdata->scale_factor;
}
+
+ /* The scaled desktop mode */
+ SDL_zero(desktop_mode);
+ desktop_mode.format = SDL_PIXELFORMAT_RGB888;
+
+ desktop_mode.screen_w = driverdata->screen_width;
+ desktop_mode.screen_h = driverdata->screen_height;
desktop_mode.display_scale = driverdata->scale_factor;
desktop_mode.refresh_rate = ((100 * driverdata->refresh) / 1000) / 100.0f; /* mHz to Hz */
desktop_mode.driverdata = driverdata->output;
@@ -609,25 +612,23 @@ static void display_handle_done(void *data,
}
/* Set the desktop display mode. */
- SDL_memcpy(&dpy->desktop_mode, &desktop_mode, sizeof(&dpy->desktop_mode));
+ SDL_SetDesktopDisplayMode(dpy, &desktop_mode);
- /* If the desktop is scaled... */
- if (driverdata->scale_factor > 1.0f) {
- /* ...expose the native resolution if viewports are available... */
- if (video->viewporter != NULL) {
- SDL_AddFullscreenDisplayMode(dpy, &native_mode);
- } else {
- /* ...if not, expose some smaller, integer scaled resolutions. */
- int i;
- const int base_pixel_w = desktop_mode.pixel_w / (int)desktop_mode.display_scale;
- const int base_pixel_h = desktop_mode.pixel_h / (int)desktop_mode.display_scale;
- for (i = 1; i < (int)desktop_mode.display_scale; ++i) {
- desktop_mode.pixel_w = base_pixel_w * i;
- desktop_mode.pixel_h = base_pixel_h * i;
- desktop_mode.display_scale = (float)i;
-
- SDL_AddFullscreenDisplayMode(dpy, &desktop_mode);
- }
+ /* ...expose the unscaled, native resolution if the scale is 1.0 or viewports are available... */
+ if (driverdata->scale_factor == 1.0f || video->viewporter != NULL) {
+ SDL_AddFullscreenDisplayMode(dpy, &native_mode);
+ } else {
+ /* ...if not, expose the integer scaled variants of the desktop resolution down to 1. */
+ int i;
+
+ desktop_mode.pixel_w = 0;
+ desktop_mode.pixel_h = 0;
+ desktop_mode.screen_w = driverdata->screen_width;
+ desktop_mode.screen_h = driverdata->screen_height;
+
+ for (i = (int)driverdata->scale_factor; i > 0; --i) {
+ desktop_mode.display_scale = (float)i;
+ SDL_AddFullscreenDisplayMode(dpy, &desktop_mode);
}
}
@@ -635,7 +636,7 @@ static void display_handle_done(void *data,
if (video->viewporter && mode_emulation_enabled) {
const SDL_bool rot_90 = ((driverdata->transform & WL_OUTPUT_TRANSFORM_90) != 0) ||
(driverdata->screen_width < driverdata->screen_height);
- AddEmulatedModes(dpy, rot_90);
+ AddEmulatedModes(driverdata, rot_90);
}
/* Calculate the display DPI */
@@ -974,8 +975,19 @@ static int Wayland_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *
SDL_DisplayData *driverdata = display->driverdata;
rect->x = driverdata->x;
rect->y = driverdata->y;
- rect->w = display->current_mode->screen_w;
- rect->h = display->current_mode->screen_h;
+
+ /* When an emulated, exclusive fullscreen window has focus, treat the mode dimensions as the display bounds. */
+ if (display->fullscreen_window &&
+ display->fullscreen_window->fullscreen_exclusive &&
+ display->fullscreen_window == SDL_GetFocusWindow() &&
+ display->fullscreen_window->fullscreen_mode.screen_w != 0 &&
+ display->fullscreen_window->fullscreen_mode.screen_h != 0) {
+ rect->w = display->fullscreen_window->fullscreen_mode.screen_w;
+ rect->h = display->fullscreen_window->fullscreen_mode.screen_h;
+ } else {
+ rect->w = display->current_mode->screen_w;
+ rect->h = display->current_mode->screen_h;
+ }
return 0;
}
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 6e9297bca543..5519a7975d89 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -53,70 +53,10 @@ SDL_FORCE_INLINE SDL_bool FloatEqual(float a, float b)
return diff <= largest * SDL_FLT_EPSILON;
}
-static void GetFullScreenDimensions(SDL_Window *window, int *width, int *height, int *drawable_width, int *drawable_height)
-{
- SDL_WindowData *wind = window->driverdata;
- SDL_VideoDisplay *disp = SDL_GetVideoDisplayForWindow(window);
- SDL_DisplayData *output = disp->driverdata;
-
- int fs_width, fs_height;
- int buf_width, buf_height;
- const int output_width = wind->fs_output_width ? wind->fs_output_width : output->screen_width;
- const int output_height = wind->fs_output_height ? wind->fs_output_height : output->screen_height;
-
- if (window->fullscreen_exclusive) {
- /* If a mode was set, use it, otherwise use the native resolution. */
- const SDL_DisplayMode *mode = SDL_GetWindowFullscreenMode(window);
- if (!mode) {
- mode = &disp->desktop_mode;
- }
- fs_width = mode->screen_w;
- fs_height = mode->screen_h;
- buf_width = mode->pixel_w;
- buf_height = mode->pixel_h;
- } else {
- /*
- * Fullscreen desktop mandates a desktop sized window, so that's what
- * applications will get. If the application is DPI aware, it will need
- * to handle the transformations between the differently sized window
- * and backbuffer spaces on its own.
- */
- fs_width = output_width;
- fs_height = output_height;
-
- /* If the application is DPI aware, we can expose the true backbuffer size */
- if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
- buf_width = output->pixel_width;
- buf_height = output->pixel_height;
- } else {
- buf_width = fs_width;
- buf_height = fs_height;
- }
- }
-
- if (width) {
- *width = fs_width;
- }
- if (height) {
- *height = fs_height;
- }
- if (drawable_width) {
- *drawable_width = buf_width;
- }
- if (drawable_height) {
- *drawable_height = buf_height;
- }
-}
-
-SDL_FORCE_INLINE SDL_bool FullscreenModeEmulation(SDL_Window *window)
-{
- return window->fullscreen_exclusive;
-}
-
-SDL_bool SurfaceScaleIsFractional(SDL_Window *window)
+static SDL_bool SurfaceScaleIsFractional(SDL_Window *window)
{
SDL_WindowData *data = window->driverdata;
- const float scale_value = !FullscreenModeEmulation(window) ? data->windowed_scale_factor : window->fullscreen_mode.display_scale;
+ const float scale_value = !(window->fullscreen_exclusive) ? data->windowed_scale_factor : window->fullscreen_mode.display_scale;
return !FloatEqual(SDL_roundf(scale_value), scale_value);
}
@@ -125,9 +65,8 @@ static SDL_bool WindowNeedsViewport(SDL_Window *window)
SDL_WindowData *wind = window->driverdata;
SDL_VideoData *video = wind->waylandData;
SDL_DisplayData *output = SDL_GetDisplayDriverDataForWindow(window);
- const int output_width = wind->fs_output_width ? wind->fs_output_width : output->screen_width;
- const int output_height = wind->fs_output_height ? wind->fs_output_height : output->screen_height;
- int fs_width, fs_height;
+ const int output_width = wind->requested_window_width ? wind->requested_window_width : output->screen_width;
+ const int output_height = wind->requested_window_height ? wind->requested_window_height : output->screen_height;
/*
* A viewport is only required when scaling is enabled and:
@@ -137,9 +76,8 @@ static SDL_bool WindowNeedsViewport(SDL_Window *window)
if (video->viewporter != NULL) {
if (SurfaceScaleIsFractional(window)) {
return SDL_TRUE;
- } else if (FullscreenModeEmulation(window)) {
- GetFullScreenDimensions(window, &fs_width, &fs_height, NULL, NULL);
- if (fs_width != output_width || fs_height != output_height) {
+ } else if (window->fullscreen_exclusive) {
+ if (window->fullscreen_mode.screen_w != output_width || window->fullscreen_mode.screen_h != output_height) {
return SDL_TRUE;
}
}
@@ -154,16 +92,13 @@ static void GetBufferSize(SDL_Window *window, int *width, int *height)
int buf_width;
int buf_height;
- if (FullscreenModeEmulation(window)) {
- GetFullScreenDimensions(window, NULL, NULL, &buf_width, &buf_height);
- } else if (WindowNeedsViewport(window)) {
- /* Round fractional backbuffer sizes halfway away from zero. */
- buf_width = (int)SDL_lroundf((float)window->w * data->windowed_scale_factor);
- buf_height = (int)SDL_lroundf((float)window->h * data->windowed_scale_factor);
+ if (window->fullscreen_exclusive) {
+ buf_width = window->fullscreen_mode.pixel_w;
+ buf_height = window->fullscreen_mode.pixel_h;
} else {
- /* Integer scaled windowed or fullscreen with no viewport */
- buf_width = window->w * (int)data->windowed_scale_factor;
- buf_height = window->h * (int)data->windowed_scale_factor;
+ /* Round fractional backbuffer sizes halfway away from zero. */
+ buf_width = (int)SDL_lroundf((float)data->requested_window_width * data->windowed_scale_factor);
+ buf_height = (int)SDL_lroundf((float)data->requested_window_height * data->windowed_scale_factor);
}
if (width) {
@@ -204,9 +139,9 @@ static void ConfigureWindowGeometry(SDL_Window *window)
SDL_WindowData *data = window->driverdata;
SDL_VideoData *viddata = data->waylandData;
SDL_DisplayData *output = SDL_GetDisplayDriverDataForWindow(window);
- struct wl_region *region;
const int old_dw = data->drawable_width;
const int old_dh = data->drawable_height;
+ int window_width, window_height;
SDL_bool window_size_changed;
SDL_bool drawable_size_changed;
@@ -221,52 +156,56 @@ static void ConfigureWindowGeometry(SDL_Window *window)
0, 0);
}
- if (FullscreenModeEmulation(window)) {
- int fs_width, fs_height;
- const int output_width = data->fs_output_width ? data->fs_output_width : output->screen_width;
- const int output_height = data->fs_output_height ? data->fs_output_height : output->screen_height;
+ if (window->fullscreen_exclusive) {
+ /* If the compositor supplied fullscreen dimensions, use them, otherwise fall back to the display dimensions. */
+ const int output_width = data->requested_window_width ? data->requested_window_width : output->screen_width;
+ const int output_height = data->requested_window_height ? data->requested_window_height : output->screen_height;
+ window_width = window->fullscreen_mode.screen_w;
+ window_height = window->fullscreen_mode.screen_h;
- window_size_changed = data->window_width != output_width || data->window_height != output_height;
+ window_size_changed = window_width != window->w || window_height != window->h ||
+ data->wl_window_width != output_width || data->wl_window_height != output_height;
if (window_size_changed || drawable_size_changed) {
- GetFullScreenDimensions(window, &fs_width, &fs_height, NULL, NULL);
-
if (WindowNeedsViewport(window)) {
/* Set the buffer scale to 1 since a viewport will be used. */
wl_surface_set_buffer_scale(data->surface, 1);
SetDrawSurfaceViewport(window, data->drawable_width, data->drawable_height,
output_width, output_height);
- data->window_width = output_width;
- data->window_height = output_height;
-
- data->pointer_scale_x = (float)fs_width / (float)output_width;
- data->pointer_scale_y = (float)fs_height / (float)output_height;
+ data->wl_window_width = output_width;
+ data->wl_window_height = output_height;
} else {
+ /* Always use the mode dimensions for integer scaling. */
+ UnsetDrawSurfaceViewport(window);
wl_surface_set_buffer_scale(data->surface, (int32_t)window->fullscreen_mode.display_scale);
- data->window_width = fs_width;
- data->window_height = fs_height;
-
- data->pointer_scale_x = 1.0f;
- data->pointer_scale_y = 1.0f;
+ data->wl_window_width = window->fullscreen_mode.screen_w;
+ data->wl_window_height = window->fullscreen_mode.screen_h;
}
+
+ data->pointer_scale_x = (float)window_width / (float)data->wl_window_width;
+ data->pointer_scale_y = (float)window_height / (float)data->wl_window_height;
}
} else {
- window_size_changed = data->window_width != window->w || data->window_height != window->h;
+ window_width = data->requested_window_width;
+ window_height = data->requested_window_height;
+
+ window_size_changed = window_width != window->w || window_height != window->h;
if (window_size_changed || drawable_size_changed) {
if (WindowNeedsViewport(window)) {
wl_surface_set_buffer_scale(data->surface, 1);
- SetDrawSurfaceViewport(window, data->drawable_width, data->drawable_height, window->w, window->h);
+ SetDrawSurfaceViewport(window, data->drawable_width, data->drawable_height,
+ window_width, window_height);
} else {
UnsetDrawSurfaceViewport(window);
wl_surface_set_buffer_scale(data->surface, (int32_t)data->windowed_scale_factor);
}
/* Clamp the physical window size to the system minimum required size. */
- data->window_width = SDL_max(window->w, data->system_min_required_width);
- data->window_height = SDL_max(window->h, data->system_min_required_height);
+ data->wl_window_width = SDL_max(window_width, data->system_min_required_width);
+ data->wl_window_height = SDL_max(window_height, data->system_min_required_height);
data->pointer_scale_x = 1.0f;
data->pointer_scale_y = 1.0f;
@@ -278,16 +217,18 @@ static void ConfigureWindowGeometry(SDL_Window *window)
* need to be recalculated if the output size has changed.
*/
if (window_size_changed) {
+ struct wl_region *region;
+
/* libdecor does this internally on frame commits, so it's only needed for xdg surfaces. */
if (data->shell_surface_type != WAYLAND_SURFACE_LIBDECOR &&
viddata->shell.xdg && data->shell_surface.xdg.surface != NULL) {
- xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->window_width, data->window_height);
+ xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->wl_window_width, data->wl_window_height);
}
if (!viddata->egl_transparency_enabled) {
region = wl_compositor_create_region(viddata->compositor);
wl_region_add(region, 0, 0,
- data->window_width, data->window_height);
+ data->wl_window_width, data->wl_window_height);
wl_surface_set_opaque_region(data->surface, region);
wl_region_destroy(region);
}
@@ -296,6 +237,10 @@ static void ConfigureWindowGeometry(SDL_Window *window)
Wayland_input_confine_pointer(viddata->input, window);
}
}
+
+ /* Unconditionally send the window and drawable size, the video core will deduplicate when required. */
+ SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window_width, window_height);
+ SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED, data->drawable_width, data->drawable_height);
}
static void CommitLibdecorFrame(SDL_Window *window)
@@ -304,7 +249,7 @@ static void CommitLibdecorFrame(SDL_Window *window)
SDL_WindowData *wind = window->driverdata;
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR && wind->shell_surface.libdecor.frame) {
- struct libdecor_state *state = libdecor_state_new(wind->window_width, wind->window_height);
+ struct libdecor_state *state = libdecor_state_new(wind->wl_window_width, wind->wl_window_height);
libdecor_frame_commit(wind->shell_surface.libdecor.frame, state, NULL);
libdecor_state_free(state);
}
@@ -326,7 +271,7 @@ static void SetMinMaxDimensions(SDL_Window *window, SDL_bool commit)
return;
}
- if (window->fullscreen_exclusive) {
+ if (window->flags & SDL_WINDOW_FULLSCREEN) {
min_width = 0;
min_height = 0;
max_width = 0;
@@ -439,22 +384,23 @@ static void UpdateWindowFullscreen(SDL_Window *window, SDL_bool fullscreen)
SDL_WindowData *wind = window->driverdata;
if (fullscreen) {
- if ((window->flags & SDL_WINDOW_FULLSCREEN) == 0) {
+ if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
wind->is_fullscreen = SDL_TRUE;
+
wind->in_fullscreen_transition = SDL_TRUE;
SDL_SetWindowFullscreen(window, SDL_TRUE);
wind->in_fullscreen_transition = SDL_FALSE;
}
} else {
/* Don't change the fullscreen flags if the window is hidden or being hidden. */
- if (!window->is_hiding && !(window->flags & SDL_WINDOW_HIDDEN)) {
- if ((window->flags & SDL_WINDOW_FULLSCREEN) != 0) {
- wind->is_fullscreen = SDL_FALSE;
- wind->in_fullscreen_transition = SDL_TRUE;
- SDL_SetWindowFullscreen(window, SDL_FALSE);
- wind->in_fullscreen_transition = SDL_FALSE;
- SetMinMaxDimensions(window, SDL_FALSE);
- }
+ if ((window->flags & SDL_WINDOW_FULLSCREEN) && !window->is_hiding && !(window->flags & SDL_WINDOW_HIDDEN)) {
+ wind->is_fullscreen = SDL_FALSE;
+
+ wind->in_fullscreen_transition = SDL_TRUE;
+ SDL_SetWindowFullscreen(window, SDL_FALSE);
+ wind->in_fullscreen_transition = SDL_FALSE;
+
+ SetMinMaxDimensions(window, SDL_FALSE);
}
}
}
@@ -474,7 +420,7 @@ static void surface_damage_frame_done(void *data, struct wl_callback *cb, uint32
wind->drawable_width, wind->drawable_height);
} else {
wl_surface_damage(wind->surface, 0, 0,
- wind->window_width, wind->window_height);
+ wind->wl_window_width, wind->wl_window_height);
}
wl_callback_destroy(cb);
@@ -503,14 +449,12 @@ static const struct wl_callback_listener gles_swap_frame_listener = {
gles_swap_frame_done
};
-static void Wayland_HandleResize(SDL_Window *window, int width, int height);
-
static void handle_configure_xdg_shell_surface(void *data, struct xdg_surface *xdg, uint32_t serial)
{
SDL_WindowData *wind = (SDL_WindowData *)data;
SDL_Window *window = wind->sdlwindow;
- Wayland_HandleResize(window, window->w, window->h);
+ ConfigureWindowGeometry(window);
xdg_surface_ack_configure(xdg, serial);
wind->shell_surface.xdg.initial_configure_seen = SDL_TRUE;
@@ -533,6 +477,7 @@ static void handle_configure_xdg_toplevel(void *data,
SDL_bool fullscreen = SDL_FALSE;
SDL_bool maximized = SDL_FALSE;
SDL_bool floating = SDL_TRUE;
+ SDL_bool focused = SDL_FALSE;
wl_array_for_each (state, states) {
switch (*state) {
case XDG_TOPLEVEL_STATE_FULLSCREEN:
@@ -543,6 +488,9 @@ static void handle_configure_xdg_toplevel(void *data,
maximized = SDL_TRUE;
floating = SDL_FALSE;
break;
+ case XDG_TOPLEVEL_STATE_ACTIVATED:
+ focused = SDL_TRUE;
+ break;
case XDG_TOPLEVEL_STATE_TILED_LEFT:
case XDG_TOPLEVEL_STATE_TILED_RIGHT:
case XDG_TOPLEVEL_STATE_TILED_TOP:
@@ -557,18 +505,18 @@ static void handle_configure_xdg_toplevel(void *data,
UpdateWindowFullscreen(window, fullscreen);
if (!fullscreen) {
- if ((floating && !wind->was_floating) || width == 0 || height == 0) {
- /* This usually happens when we're being restored from a
- * non-floating state, so use the cached floating size here.
- */
- width = wind->floating_width;
- height = wind->floating_height;
- }
-
/* xdg_toplevel spec states that this is a suggestion.
- Ignore if less than or greater than max/min size. */
-
+ * Ignore if less than or greater than max/min size.
+ */
if ((window->flags & SDL_WINDOW_RESIZABLE)) {
+ if ((floating && !wind->floating) || width == 0 || height == 0) {
+ /* This happens when we're being restored from a
+ * non-floating state, so use the cached floating size here.
+ */
+ width = wind->floating_width;
+ height = wind->floating_height;
+ }
+
if (window->max_w > 0) {
width = SDL_min(width, window->max_w);
}
@@ -586,6 +534,12 @@ static void handle_configure_xdg_toplevel(void *data,
height = window->windowed.h;
}
+ /* Store current floating dimensions for restoring */
+ if (floating) {
+ wind->floating_width = width;
+ wind->floating_height = height;
+ }
+
/* Always send a maximized/restore event; if the event is redundant it will
* automatically be discarded (see src/events/SDL_windowevents.c)
*
@@ -594,45 +548,25 @@ static void handle_configure_xdg_toplevel(void *data,
SDL_SendWindowEvent(window,
maximized ? SDL_EVENT_WINDOW_MAXIMIZED : SDL_EVENT_WINDOW_RESTORED,
0, 0);
-
- /* Store current floating dimensions for restoring */
- if (floating) {
- wind->floating_width = width;
- wind->floating_height = height;
- }
-
- /* Store this now so the xdg_surface configure knows what to resize to */
- if (window->w != width || window->h != height) {
- window->w = width;
- window->h = height;
- wind->needs_resize_event = SDL_TRUE;
- }
} else {
- /* For fullscreen, foolishly do what the compositor says. If it's wrong,
- * don't blame us, we were explicitly instructed to do this.
- *
- * UPDATE: Nope, sure enough a compositor sends 0,0. This is a known bug:
- * https://bugs.kde.org/show_bug.cgi?id=444962
- */
- if (width && height) {
- wind->fs_output_width = width;
- wind->fs_output_height = height;
- } else {
- wind->fs_output_width = 0;
- wind->fs_output_height = 0;
- }
-
- if (FullscreenModeEmulation(window)) {
- GetFullScreenDimensions(window, &width, &height, NULL, NULL);
- }
- if (width != 0 && height != 0 && (window->w != width || window->h != height)) {
- window->w = width;
- window->h = height;
- wind->needs_resize_event = SDL_TRUE;
+ /* If an exclusive fullscreen mode was requested, ensure it is placed on the appropriate output. */
+ if (window->fullscreen_exclusive && wind->fullscreen_display != window->fullscreen_mode.displayID) {
+ SDL_VideoDisplay *disp = SDL_GetVideoDisplay(window->fullscreen_mode.displayID);
+ if (disp) {
+ wind->fullscreen_display = disp->id;
+ xdg_toplevel_set_fullscreen(xdg_toplevel, disp->driverdata->output);
+ }
}
}
- wind->was_floating = floating;
+ /* Similar to maximized/restore events above, send focus events too! */
+ SDL_Se
(Patch may be truncated, please check the link at the top of this post.)