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 cleanupmain
parent
47cdb532f1
commit
7def1438c3
|
@ -361,7 +361,7 @@ static const struct zxdg_output_v1_listener xdg_output_listener = {
|
||||||
xdg_output_handle_description,
|
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
|
struct EmulatedMode
|
||||||
{
|
{
|
||||||
|
@ -413,8 +413,9 @@ static void AddEmulatedModes(SDL_VideoDisplay *dpy, SDL_bool rot_90)
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
const int native_width = dpy->desktop_mode.pixel_w;
|
SDL_VideoDisplay *dpy = dispdata->display ? SDL_GetVideoDisplay(dispdata->display) : &dispdata->placeholder;
|
||||||
const int native_height = dpy->desktop_mode.pixel_h;
|
const int native_width = dispdata->pixel_width;
|
||||||
|
const int native_height = dispdata->pixel_height;
|
||||||
|
|
||||||
for (i = 0; i < SDL_arraysize(mode_list); ++i) {
|
for (i = 0; i < SDL_arraysize(mode_list); ++i) {
|
||||||
SDL_zero(mode);
|
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.refresh_rate = dpy->desktop_mode.refresh_rate;
|
||||||
mode.driverdata = dpy->desktop_mode.driverdata;
|
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. */
|
/* Only add modes that are smaller than the native mode. */
|
||||||
if ((mode.pixel_w < native_width && mode.pixel_h < native_height) ||
|
if ((mode_list[i].w < native_width && mode_list[i].h < native_height) ||
|
||||||
(mode.pixel_w < native_width && mode.pixel_h == native_height) ||
|
(mode_list[i].w < native_width && mode_list[i].h == native_height) ||
|
||||||
(mode.pixel_w == native_width && mode.pixel_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);
|
SDL_AddFullscreenDisplayMode(dpy, &mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -452,22 +454,6 @@ static void display_handle_geometry(void *data,
|
||||||
|
|
||||||
{
|
{
|
||||||
SDL_DisplayData *driverdata = (SDL_DisplayData *)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 */
|
/* Apply the change from wl-output only if xdg-output is not supported */
|
||||||
if (!driverdata->has_logical_position) {
|
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);
|
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;
|
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 */
|
/* The native display resolution */
|
||||||
SDL_zero(native_mode);
|
SDL_zero(native_mode);
|
||||||
native_mode.format = SDL_PIXELFORMAT_RGB888;
|
native_mode.format = SDL_PIXELFORMAT_RGB888;
|
||||||
|
|
||||||
|
/* Transform the pixel values, if necessary. */
|
||||||
if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
|
if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
|
||||||
native_mode.pixel_w = driverdata->pixel_height;
|
native_mode.pixel_w = driverdata->pixel_height;
|
||||||
native_mode.pixel_h = driverdata->pixel_width;
|
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.refresh_rate = ((100 * driverdata->refresh) / 1000) / 100.0f; /* mHz to Hz */
|
||||||
native_mode.driverdata = driverdata->output;
|
native_mode.driverdata = driverdata->output;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
/* 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 */
|
/* The scaled desktop mode */
|
||||||
SDL_zero(desktop_mode);
|
SDL_zero(desktop_mode);
|
||||||
desktop_mode.format = SDL_PIXELFORMAT_RGB888;
|
desktop_mode.format = SDL_PIXELFORMAT_RGB888;
|
||||||
|
|
||||||
if (driverdata->has_logical_size) { /* If xdg-output is present, calculate the true scale of the desktop */
|
desktop_mode.screen_w = driverdata->screen_width;
|
||||||
if (video->viewporter) {
|
desktop_mode.screen_h = driverdata->screen_height;
|
||||||
driverdata->scale_factor = (float)native_mode.pixel_w / (float)driverdata->screen_width;
|
|
||||||
}
|
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
desktop_mode.display_scale = driverdata->scale_factor;
|
desktop_mode.display_scale = driverdata->scale_factor;
|
||||||
desktop_mode.refresh_rate = ((100 * driverdata->refresh) / 1000) / 100.0f; /* mHz to Hz */
|
desktop_mode.refresh_rate = ((100 * driverdata->refresh) / 1000) / 100.0f; /* mHz to Hz */
|
||||||
desktop_mode.driverdata = driverdata->output;
|
desktop_mode.driverdata = driverdata->output;
|
||||||
|
@ -609,25 +612,23 @@ static void display_handle_done(void *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the desktop display mode. */
|
/* 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... */
|
/* ...expose the unscaled, native resolution if the scale is 1.0 or viewports are available... */
|
||||||
if (driverdata->scale_factor > 1.0f) {
|
if (driverdata->scale_factor == 1.0f || video->viewporter != NULL) {
|
||||||
/* ...expose the native resolution if viewports are available... */
|
SDL_AddFullscreenDisplayMode(dpy, &native_mode);
|
||||||
if (video->viewporter != NULL) {
|
} else {
|
||||||
SDL_AddFullscreenDisplayMode(dpy, &native_mode);
|
/* ...if not, expose the integer scaled variants of the desktop resolution down to 1. */
|
||||||
} else {
|
int i;
|
||||||
/* ...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);
|
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) {
|
if (video->viewporter && mode_emulation_enabled) {
|
||||||
const SDL_bool rot_90 = ((driverdata->transform & WL_OUTPUT_TRANSFORM_90) != 0) ||
|
const SDL_bool rot_90 = ((driverdata->transform & WL_OUTPUT_TRANSFORM_90) != 0) ||
|
||||||
(driverdata->screen_width < driverdata->screen_height);
|
(driverdata->screen_width < driverdata->screen_height);
|
||||||
AddEmulatedModes(dpy, rot_90);
|
AddEmulatedModes(driverdata, rot_90);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the display DPI */
|
/* Calculate the display DPI */
|
||||||
|
@ -974,8 +975,19 @@ static int Wayland_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *
|
||||||
SDL_DisplayData *driverdata = display->driverdata;
|
SDL_DisplayData *driverdata = display->driverdata;
|
||||||
rect->x = driverdata->x;
|
rect->x = driverdata->x;
|
||||||
rect->y = driverdata->y;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,70 +53,10 @@ SDL_FORCE_INLINE SDL_bool FloatEqual(float a, float b)
|
||||||
return diff <= largest * SDL_FLT_EPSILON;
|
return diff <= largest * SDL_FLT_EPSILON;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetFullScreenDimensions(SDL_Window *window, int *width, int *height, int *drawable_width, int *drawable_height)
|
static SDL_bool SurfaceScaleIsFractional(SDL_Window *window)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
SDL_WindowData *data = window->driverdata;
|
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);
|
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_WindowData *wind = window->driverdata;
|
||||||
SDL_VideoData *video = wind->waylandData;
|
SDL_VideoData *video = wind->waylandData;
|
||||||
SDL_DisplayData *output = SDL_GetDisplayDriverDataForWindow(window);
|
SDL_DisplayData *output = SDL_GetDisplayDriverDataForWindow(window);
|
||||||
const int output_width = wind->fs_output_width ? wind->fs_output_width : output->screen_width;
|
const int output_width = wind->requested_window_width ? wind->requested_window_width : output->screen_width;
|
||||||
const int output_height = wind->fs_output_height ? wind->fs_output_height : output->screen_height;
|
const int output_height = wind->requested_window_height ? wind->requested_window_height : output->screen_height;
|
||||||
int fs_width, fs_height;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A viewport is only required when scaling is enabled and:
|
* 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 (video->viewporter != NULL) {
|
||||||
if (SurfaceScaleIsFractional(window)) {
|
if (SurfaceScaleIsFractional(window)) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
} else if (FullscreenModeEmulation(window)) {
|
} else if (window->fullscreen_exclusive) {
|
||||||
GetFullScreenDimensions(window, &fs_width, &fs_height, NULL, NULL);
|
if (window->fullscreen_mode.screen_w != output_width || window->fullscreen_mode.screen_h != output_height) {
|
||||||
if (fs_width != output_width || fs_height != output_height) {
|
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,16 +92,13 @@ static void GetBufferSize(SDL_Window *window, int *width, int *height)
|
||||||
int buf_width;
|
int buf_width;
|
||||||
int buf_height;
|
int buf_height;
|
||||||
|
|
||||||
if (FullscreenModeEmulation(window)) {
|
if (window->fullscreen_exclusive) {
|
||||||
GetFullScreenDimensions(window, NULL, NULL, &buf_width, &buf_height);
|
buf_width = window->fullscreen_mode.pixel_w;
|
||||||
} else if (WindowNeedsViewport(window)) {
|
buf_height = window->fullscreen_mode.pixel_h;
|
||||||
/* 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);
|
|
||||||
} else {
|
} else {
|
||||||
/* Integer scaled windowed or fullscreen with no viewport */
|
/* Round fractional backbuffer sizes halfway away from zero. */
|
||||||
buf_width = window->w * (int)data->windowed_scale_factor;
|
buf_width = (int)SDL_lroundf((float)data->requested_window_width * data->windowed_scale_factor);
|
||||||
buf_height = window->h * (int)data->windowed_scale_factor;
|
buf_height = (int)SDL_lroundf((float)data->requested_window_height * data->windowed_scale_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width) {
|
if (width) {
|
||||||
|
@ -204,9 +139,9 @@ static void ConfigureWindowGeometry(SDL_Window *window)
|
||||||
SDL_WindowData *data = window->driverdata;
|
SDL_WindowData *data = window->driverdata;
|
||||||
SDL_VideoData *viddata = data->waylandData;
|
SDL_VideoData *viddata = data->waylandData;
|
||||||
SDL_DisplayData *output = SDL_GetDisplayDriverDataForWindow(window);
|
SDL_DisplayData *output = SDL_GetDisplayDriverDataForWindow(window);
|
||||||
struct wl_region *region;
|
|
||||||
const int old_dw = data->drawable_width;
|
const int old_dw = data->drawable_width;
|
||||||
const int old_dh = data->drawable_height;
|
const int old_dh = data->drawable_height;
|
||||||
|
int window_width, window_height;
|
||||||
SDL_bool window_size_changed;
|
SDL_bool window_size_changed;
|
||||||
SDL_bool drawable_size_changed;
|
SDL_bool drawable_size_changed;
|
||||||
|
|
||||||
|
@ -221,52 +156,56 @@ static void ConfigureWindowGeometry(SDL_Window *window)
|
||||||
0, 0);
|
0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FullscreenModeEmulation(window)) {
|
if (window->fullscreen_exclusive) {
|
||||||
int fs_width, fs_height;
|
/* If the compositor supplied fullscreen dimensions, use them, otherwise fall back to the display dimensions. */
|
||||||
const int output_width = data->fs_output_width ? data->fs_output_width : output->screen_width;
|
const int output_width = data->requested_window_width ? data->requested_window_width : output->screen_width;
|
||||||
const int output_height = data->fs_output_height ? data->fs_output_height : output->screen_height;
|
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) {
|
if (window_size_changed || drawable_size_changed) {
|
||||||
GetFullScreenDimensions(window, &fs_width, &fs_height, NULL, NULL);
|
|
||||||
|
|
||||||
if (WindowNeedsViewport(window)) {
|
if (WindowNeedsViewport(window)) {
|
||||||
/* Set the buffer scale to 1 since a viewport will be used. */
|
/* Set the buffer scale to 1 since a viewport will be used. */
|
||||||
wl_surface_set_buffer_scale(data->surface, 1);
|
wl_surface_set_buffer_scale(data->surface, 1);
|
||||||
SetDrawSurfaceViewport(window, data->drawable_width, data->drawable_height,
|
SetDrawSurfaceViewport(window, data->drawable_width, data->drawable_height,
|
||||||
output_width, output_height);
|
output_width, output_height);
|
||||||
|
|
||||||
data->window_width = output_width;
|
data->wl_window_width = output_width;
|
||||||
data->window_height = output_height;
|
data->wl_window_height = output_height;
|
||||||
|
|
||||||
data->pointer_scale_x = (float)fs_width / (float)output_width;
|
|
||||||
data->pointer_scale_y = (float)fs_height / (float)output_height;
|
|
||||||
} else {
|
} 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);
|
wl_surface_set_buffer_scale(data->surface, (int32_t)window->fullscreen_mode.display_scale);
|
||||||
|
|
||||||
data->window_width = fs_width;
|
data->wl_window_width = window->fullscreen_mode.screen_w;
|
||||||
data->window_height = fs_height;
|
data->wl_window_height = window->fullscreen_mode.screen_h;
|
||||||
|
|
||||||
data->pointer_scale_x = 1.0f;
|
|
||||||
data->pointer_scale_y = 1.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
} 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 (window_size_changed || drawable_size_changed) {
|
||||||
if (WindowNeedsViewport(window)) {
|
if (WindowNeedsViewport(window)) {
|
||||||
wl_surface_set_buffer_scale(data->surface, 1);
|
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 {
|
} else {
|
||||||
UnsetDrawSurfaceViewport(window);
|
UnsetDrawSurfaceViewport(window);
|
||||||
wl_surface_set_buffer_scale(data->surface, (int32_t)data->windowed_scale_factor);
|
wl_surface_set_buffer_scale(data->surface, (int32_t)data->windowed_scale_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clamp the physical window size to the system minimum required size. */
|
/* Clamp the physical window size to the system minimum required size. */
|
||||||
data->window_width = SDL_max(window->w, data->system_min_required_width);
|
data->wl_window_width = SDL_max(window_width, data->system_min_required_width);
|
||||||
data->window_height = SDL_max(window->h, data->system_min_required_height);
|
data->wl_window_height = SDL_max(window_height, data->system_min_required_height);
|
||||||
|
|
||||||
data->pointer_scale_x = 1.0f;
|
data->pointer_scale_x = 1.0f;
|
||||||
data->pointer_scale_y = 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.
|
* need to be recalculated if the output size has changed.
|
||||||
*/
|
*/
|
||||||
if (window_size_changed) {
|
if (window_size_changed) {
|
||||||
|
struct wl_region *region;
|
||||||
|
|
||||||
/* libdecor does this internally on frame commits, so it's only needed for xdg surfaces. */
|
/* libdecor does this internally on frame commits, so it's only needed for xdg surfaces. */
|
||||||
if (data->shell_surface_type != WAYLAND_SURFACE_LIBDECOR &&
|
if (data->shell_surface_type != WAYLAND_SURFACE_LIBDECOR &&
|
||||||
viddata->shell.xdg && data->shell_surface.xdg.surface != NULL) {
|
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) {
|
if (!viddata->egl_transparency_enabled) {
|
||||||
region = wl_compositor_create_region(viddata->compositor);
|
region = wl_compositor_create_region(viddata->compositor);
|
||||||
wl_region_add(region, 0, 0,
|
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_surface_set_opaque_region(data->surface, region);
|
||||||
wl_region_destroy(region);
|
wl_region_destroy(region);
|
||||||
}
|
}
|
||||||
|
@ -296,6 +237,10 @@ static void ConfigureWindowGeometry(SDL_Window *window)
|
||||||
Wayland_input_confine_pointer(viddata->input, 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)
|
static void CommitLibdecorFrame(SDL_Window *window)
|
||||||
|
@ -304,7 +249,7 @@ static void CommitLibdecorFrame(SDL_Window *window)
|
||||||
SDL_WindowData *wind = window->driverdata;
|
SDL_WindowData *wind = window->driverdata;
|
||||||
|
|
||||||
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR && wind->shell_surface.libdecor.frame) {
|
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_frame_commit(wind->shell_surface.libdecor.frame, state, NULL);
|
||||||
libdecor_state_free(state);
|
libdecor_state_free(state);
|
||||||
}
|
}
|
||||||
|
@ -326,7 +271,7 @@ static void SetMinMaxDimensions(SDL_Window *window, SDL_bool commit)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->fullscreen_exclusive) {
|
if (window->flags & SDL_WINDOW_FULLSCREEN) {
|
||||||
min_width = 0;
|
min_width = 0;
|
||||||
min_height = 0;
|
min_height = 0;
|
||||||
max_width = 0;
|
max_width = 0;
|
||||||
|
@ -439,22 +384,23 @@ static void UpdateWindowFullscreen(SDL_Window *window, SDL_bool fullscreen)
|
||||||
SDL_WindowData *wind = window->driverdata;
|
SDL_WindowData *wind = window->driverdata;
|
||||||
|
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
if ((window->flags & SDL_WINDOW_FULLSCREEN) == 0) {
|
if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
|
||||||
wind->is_fullscreen = SDL_TRUE;
|
wind->is_fullscreen = SDL_TRUE;
|
||||||
|
|
||||||
wind->in_fullscreen_transition = SDL_TRUE;
|
wind->in_fullscreen_transition = SDL_TRUE;
|
||||||
SDL_SetWindowFullscreen(window, SDL_TRUE);
|
SDL_SetWindowFullscreen(window, SDL_TRUE);
|
||||||
wind->in_fullscreen_transition = SDL_FALSE;
|
wind->in_fullscreen_transition = SDL_FALSE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Don't change the fullscreen flags if the window is hidden or being hidden. */
|
/* 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) && !window->is_hiding && !(window->flags & SDL_WINDOW_HIDDEN)) {
|
||||||
if ((window->flags & SDL_WINDOW_FULLSCREEN) != 0) {
|
wind->is_fullscreen = SDL_FALSE;
|
||||||
wind->is_fullscreen = SDL_FALSE;
|
|
||||||
wind->in_fullscreen_transition = SDL_TRUE;
|
wind->in_fullscreen_transition = SDL_TRUE;
|
||||||
SDL_SetWindowFullscreen(window, SDL_FALSE);
|
SDL_SetWindowFullscreen(window, SDL_FALSE);
|
||||||
wind->in_fullscreen_transition = SDL_FALSE;
|
wind->in_fullscreen_transition = SDL_FALSE;
|
||||||
SetMinMaxDimensions(window, 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);
|
wind->drawable_width, wind->drawable_height);
|
||||||
} else {
|
} else {
|
||||||
wl_surface_damage(wind->surface, 0, 0,
|
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);
|
wl_callback_destroy(cb);
|
||||||
|
@ -503,14 +449,12 @@ static const struct wl_callback_listener gles_swap_frame_listener = {
|
||||||
gles_swap_frame_done
|
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)
|
static void handle_configure_xdg_shell_surface(void *data, struct xdg_surface *xdg, uint32_t serial)
|
||||||
{
|
{
|
||||||
SDL_WindowData *wind = (SDL_WindowData *)data;
|
SDL_WindowData *wind = (SDL_WindowData *)data;
|
||||||
SDL_Window *window = wind->sdlwindow;
|
SDL_Window *window = wind->sdlwindow;
|
||||||
|
|
||||||
Wayland_HandleResize(window, window->w, window->h);
|
ConfigureWindowGeometry(window);
|
||||||
xdg_surface_ack_configure(xdg, serial);
|
xdg_surface_ack_configure(xdg, serial);
|
||||||
|
|
||||||
wind->shell_surface.xdg.initial_configure_seen = SDL_TRUE;
|
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 fullscreen = SDL_FALSE;
|
||||||
SDL_bool maximized = SDL_FALSE;
|
SDL_bool maximized = SDL_FALSE;
|
||||||
SDL_bool floating = SDL_TRUE;
|
SDL_bool floating = SDL_TRUE;
|
||||||
|
SDL_bool focused = SDL_FALSE;
|
||||||
wl_array_for_each (state, states) {
|
wl_array_for_each (state, states) {
|
||||||
switch (*state) {
|
switch (*state) {
|
||||||
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
||||||
|
@ -543,6 +488,9 @@ static void handle_configure_xdg_toplevel(void *data,
|
||||||
maximized = SDL_TRUE;
|
maximized = SDL_TRUE;
|
||||||
floating = SDL_FALSE;
|
floating = SDL_FALSE;
|
||||||
break;
|
break;
|
||||||
|
case XDG_TOPLEVEL_STATE_ACTIVATED:
|
||||||
|
focused = SDL_TRUE;
|
||||||
|
break;
|
||||||
case XDG_TOPLEVEL_STATE_TILED_LEFT:
|
case XDG_TOPLEVEL_STATE_TILED_LEFT:
|
||||||
case XDG_TOPLEVEL_STATE_TILED_RIGHT:
|
case XDG_TOPLEVEL_STATE_TILED_RIGHT:
|
||||||
case XDG_TOPLEVEL_STATE_TILED_TOP:
|
case XDG_TOPLEVEL_STATE_TILED_TOP:
|
||||||
|
@ -557,18 +505,18 @@ static void handle_configure_xdg_toplevel(void *data,
|
||||||
UpdateWindowFullscreen(window, fullscreen);
|
UpdateWindowFullscreen(window, fullscreen);
|
||||||
|
|
||||||
if (!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.
|
/* 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 ((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) {
|
if (window->max_w > 0) {
|
||||||
width = SDL_min(width, window->max_w);
|
width = SDL_min(width, window->max_w);
|
||||||
}
|
}
|
||||||
|
@ -586,6 +534,12 @@ static void handle_configure_xdg_toplevel(void *data,
|
||||||
height = window->windowed.h;
|
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
|
/* Always send a maximized/restore event; if the event is redundant it will
|
||||||
* automatically be discarded (see src/events/SDL_windowevents.c)
|
* automatically be discarded (see src/events/SDL_windowevents.c)
|
||||||
*
|
*
|
||||||
|
@ -594,45 +548,25 @@ static void handle_configure_xdg_toplevel(void *data,
|
||||||
SDL_SendWindowEvent(window,
|
SDL_SendWindowEvent(window,
|
||||||
maximized ? SDL_EVENT_WINDOW_MAXIMIZED : SDL_EVENT_WINDOW_RESTORED,
|
maximized ? SDL_EVENT_WINDOW_MAXIMIZED : SDL_EVENT_WINDOW_RESTORED,
|
||||||
0, 0);
|
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 {
|
} else {
|
||||||
/* For fullscreen, foolishly do what the compositor says. If it's wrong,
|
/* If an exclusive fullscreen mode was requested, ensure it is placed on the appropriate output. */
|
||||||
* don't blame us, we were explicitly instructed to do this.
|
if (window->fullscreen_exclusive && wind->fullscreen_display != window->fullscreen_mode.displayID) {
|
||||||
*
|
SDL_VideoDisplay *disp = SDL_GetVideoDisplay(window->fullscreen_mode.displayID);
|
||||||
* UPDATE: Nope, sure enough a compositor sends 0,0. This is a known bug:
|
if (disp) {
|
||||||
* https://bugs.kde.org/show_bug.cgi?id=444962
|
wind->fullscreen_display = disp->id;
|
||||||
*/
|
xdg_toplevel_set_fullscreen(xdg_toplevel, disp->driverdata->output);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wind->was_floating = floating;
|
/* Similar to maximized/restore events above, send focus events too! */
|
||||||
|
SDL_SendWindowEvent(window,
|
||||||
|
focused ? SDL_EVENT_WINDOW_FOCUS_GAINED : SDL_EVENT_WINDOW_FOCUS_LOST,
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
wind->requested_window_width = width;
|
||||||
|
wind->requested_window_height = height;
|
||||||
|
wind->floating = floating;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_close_xdg_toplevel(void *data, struct xdg_toplevel *xdg_toplevel)
|
static void handle_close_xdg_toplevel(void *data, struct xdg_toplevel *xdg_toplevel)
|
||||||
|
@ -826,29 +760,27 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
|
||||||
* Always assume the configure is wrong.
|
* Always assume the configure is wrong.
|
||||||
*/
|
*/
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
|
/* 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;
|
||||||
|
libdecor_frame_set_fullscreen(frame, disp->driverdata->output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: We have been explicitly told to respect the fullscreen size
|
/* FIXME: We have been explicitly told to respect the fullscreen size
|
||||||
* parameters here, even though they are known to be wrong on GNOME at
|
* parameters here, even though they are known to be wrong on GNOME at
|
||||||
* bare minimum. If this is wrong, don't blame us, we were explicitly
|
* bare minimum. If this is wrong, don't blame us, we were explicitly
|
||||||
* told to do this.
|
* told to do this.
|
||||||
*/
|
*/
|
||||||
if (libdecor_configuration_get_content_size(configuration, frame,
|
if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) {
|
||||||
&width, &height)) {
|
width = 0;
|
||||||
wind->fs_output_width = width;
|
height = 0;
|
||||||
wind->fs_output_height = height;
|
|
||||||
} else {
|
|
||||||
width = window->w;
|
|
||||||
height = window->h;
|
|
||||||
wind->fs_output_width = 0;
|
|
||||||
wind->fs_output_height = 0;
|
|
||||||
}
|
}
|
||||||
|
} else if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
|
||||||
if (FullscreenModeEmulation(window)) {
|
|
||||||
GetFullScreenDimensions(window, &width, &height, NULL, NULL);
|
|
||||||
}
|
|
||||||
} else if (!(window->flags & SDL_WINDOW_RESIZABLE) || (floating && wind->floating_resize_pending)) {
|
|
||||||
width = window->windowed.w;
|
width = window->windowed.w;
|
||||||
height = window->windowed.h;
|
height = window->windowed.h;
|
||||||
wind->floating_resize_pending = SDL_FALSE;
|
|
||||||
|
|
||||||
OverrideLibdecorLimits(window);
|
OverrideLibdecorLimits(window);
|
||||||
} else {
|
} else {
|
||||||
|
@ -862,7 +794,7 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
|
||||||
*
|
*
|
||||||
* https://gitlab.gnome.org/jadahl/libdecor/-/issues/40
|
* https://gitlab.gnome.org/jadahl/libdecor/-/issues/40
|
||||||
*/
|
*/
|
||||||
const SDL_bool use_cached_size = (floating && !wind->was_floating) ||
|
const SDL_bool use_cached_size = (floating != wind->floating) ||
|
||||||
(window->is_hiding || !!(window->flags & SDL_WINDOW_HIDDEN));
|
(window->is_hiding || !!(window->flags & SDL_WINDOW_HIDDEN));
|
||||||
|
|
||||||
/* This will never set 0 for width/height unless the function returns false */
|
/* This will never set 0 for width/height unless the function returns false */
|
||||||
|
@ -886,13 +818,16 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
|
||||||
wind->floating_height = height;
|
wind->floating_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
wind->was_floating = floating;
|
/* Store the new floating state. */
|
||||||
|
wind->floating = floating;
|
||||||
|
|
||||||
/* Do the resize on the SDL side (this will set window->w/h)... */
|
/* Calculate the new window geometry */
|
||||||
Wayland_HandleResize(window, width, height);
|
wind->requested_window_width = width;
|
||||||
|
wind->requested_window_height = height;
|
||||||
|
ConfigureWindowGeometry(window);
|
||||||
|
|
||||||
/* ... then commit the changes on the libdecor side. */
|
/* ... then commit the changes on the libdecor side. */
|
||||||
state = libdecor_state_new(wind->window_width, wind->window_height);
|
state = libdecor_state_new(wind->wl_window_width, wind->wl_window_height);
|
||||||
libdecor_frame_commit(frame, state, configuration);
|
libdecor_frame_commit(frame, state, configuration);
|
||||||
libdecor_state_free(state);
|
libdecor_state_free(state);
|
||||||
|
|
||||||
|
@ -979,7 +914,7 @@ static void update_scale_factor(SDL_WindowData *window)
|
||||||
|
|
||||||
if (!FloatEqual(new_factor, old_factor)) {
|
if (!FloatEqual(new_factor, old_factor)) {
|
||||||
window->windowed_scale_factor = new_factor;
|
window->windowed_scale_factor = new_factor;
|
||||||
Wayland_HandleResize(window->sdlwindow, window->sdlwindow->w, window->sdlwindow->h);
|
ConfigureWindowGeometry(window->sdlwindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1296,7 +1231,7 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the geometry */
|
/* Set the geometry */
|
||||||
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);
|
||||||
} else {
|
} else {
|
||||||
/* Nothing to see here, just commit. */
|
/* Nothing to see here, just commit. */
|
||||||
wl_surface_commit(data->surface);
|
wl_surface_commit(data->surface);
|
||||||
|
@ -1324,8 +1259,8 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
||||||
"Window dimensions (%i, %i) are smaller than the system enforced minimum (%i, %i); window borders will be larger than the content surface.",
|
"Window dimensions (%i, %i) are smaller than the system enforced minimum (%i, %i); window borders will be larger than the content surface.",
|
||||||
window->windowed.w, window->windowed.h, data->system_min_required_width, data->system_min_required_height);
|
window->windowed.w, window->windowed.h, data->system_min_required_width, data->system_min_required_height);
|
||||||
|
|
||||||
data->window_width = SDL_max(window->windowed.w, data->system_min_required_width);
|
data->wl_window_width = SDL_max(window->windowed.w, data->system_min_required_width);
|
||||||
data->window_height = SDL_max(window->windowed.h, data->system_min_required_height);
|
data->wl_window_height = SDL_max(window->windowed.h, data->system_min_required_height);
|
||||||
CommitLibdecorFrame(window);
|
CommitLibdecorFrame(window);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -1546,7 +1481,7 @@ void handle_preferred_scale_changed(void *data,
|
||||||
|
|
||||||
if (!FloatEqual(new_factor, old_factor)) {
|
if (!FloatEqual(new_factor, old_factor)) {
|
||||||
window->windowed_scale_factor = new_factor;
|
window->windowed_scale_factor = new_factor;
|
||||||
Wayland_HandleResize(window->sdlwindow, window->sdlwindow->w, window->sdlwindow->h);
|
ConfigureWindowGeometry(window->sdlwindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1647,12 +1582,17 @@ void Wayland_SetWindowFullscreen(_THIS, SDL_Window *window,
|
||||||
|
|
||||||
/* Called from within a configure event or the window is a popup, drop it. */
|
/* Called from within a configure event or the window is a popup, drop it. */
|
||||||
if (wind->in_fullscreen_transition || wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
|
if (wind->in_fullscreen_transition || wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
|
||||||
|
if (!fullscreen) {
|
||||||
|
/* Clear the display ID so it will be set next time. */
|
||||||
|
wind->fullscreen_display = 0;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't send redundant fullscreen set/unset events. */
|
/* Don't send redundant fullscreen set/unset events. */
|
||||||
if (wind->is_fullscreen != fullscreen) {
|
if (wind->is_fullscreen != fullscreen) {
|
||||||
wind->is_fullscreen = fullscreen;
|
wind->is_fullscreen = fullscreen;
|
||||||
|
wind->fullscreen_display = fullscreen ? display->id : 0;
|
||||||
SetFullscreen(window, fullscreen ? output : NULL);
|
SetFullscreen(window, fullscreen ? output : NULL);
|
||||||
|
|
||||||
/* Roundtrip required to receive the updated window dimensions */
|
/* Roundtrip required to receive the updated window dimensions */
|
||||||
|
@ -1660,11 +1600,16 @@ void Wayland_SetWindowFullscreen(_THIS, SDL_Window *window,
|
||||||
} else if (wind->is_fullscreen) {
|
} else if (wind->is_fullscreen) {
|
||||||
/*
|
/*
|
||||||
* If the window is already fullscreen, this is likely a request to switch between
|
* If the window is already fullscreen, this is likely a request to switch between
|
||||||
* fullscreen and fullscreen desktop, or to change the video mode. Update the
|
* fullscreen and fullscreen desktop, change outputs, or change the video mode.
|
||||||
* geometry and trigger a commit.
|
* Update the geometry and trigger a commit.
|
||||||
*/
|
*/
|
||||||
ConfigureWindowGeometry(window);
|
if (wind->fullscreen_display != display->id) {
|
||||||
CommitLibdecorFrame(window);
|
wind->fullscreen_display = display->id;
|
||||||
|
SetFullscreen(window, output);
|
||||||
|
} else {
|
||||||
|
ConfigureWindowGeometry(window);
|
||||||
|
CommitLibdecorFrame(window);
|
||||||
|
}
|
||||||
|
|
||||||
/* Roundtrip required to receive the updated window dimensions */
|
/* Roundtrip required to receive the updated window dimensions */
|
||||||
WAYLAND_wl_display_roundtrip(viddata->display);
|
WAYLAND_wl_display_roundtrip(viddata->display);
|
||||||
|
@ -1894,6 +1839,8 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
|
||||||
data->outputs = NULL;
|
data->outputs = NULL;
|
||||||
data->num_outputs = 0;
|
data->num_outputs = 0;
|
||||||
|
|
||||||
|
data->requested_window_width = window->w;
|
||||||
|
data->requested_window_height = window->h;
|
||||||
data->floating_width = window->windowed.w;
|
data->floating_width = window->windowed.w;
|
||||||
data->floating_height = window->windowed.h;
|
data->floating_height = window->windowed.h;
|
||||||
|
|
||||||
|
@ -1989,30 +1936,6 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Wayland_HandleResize(SDL_Window *window, int width, int height)
|
|
||||||
{
|
|
||||||
SDL_WindowData *data = window->driverdata;
|
|
||||||
const int old_w = window->w, old_h = window->h;
|
|
||||||
|
|
||||||
/* Update the window geometry. */
|
|
||||||
window->w = width;
|
|
||||||
window->h = height;
|
|
||||||
ConfigureWindowGeometry(window);
|
|
||||||
|
|
||||||
if (data->needs_resize_event || old_w != width || old_h != height) {
|
|
||||||
/* We have already updated window w/h, so we must override the deduplication logic in the video core */
|
|
||||||
window->w = 0;
|
|
||||||
window->h = 0;
|
|
||||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, width, height);
|
|
||||||
window->w = width;
|
|
||||||
window->h = height;
|
|
||||||
data->needs_resize_event = SDL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED,
|
|
||||||
data->drawable_width, data->drawable_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wayland_SetWindowMinimumSize(_THIS, SDL_Window *window)
|
void Wayland_SetWindowMinimumSize(_THIS, SDL_Window *window)
|
||||||
{
|
{
|
||||||
SetMinMaxDimensions(window, SDL_TRUE);
|
SetMinMaxDimensions(window, SDL_TRUE);
|
||||||
|
@ -2027,27 +1950,21 @@ void Wayland_SetWindowSize(_THIS, SDL_Window *window)
|
||||||
{
|
{
|
||||||
SDL_WindowData *wind = window->driverdata;
|
SDL_WindowData *wind = window->driverdata;
|
||||||
|
|
||||||
#ifdef HAVE_LIBDECOR_H
|
/*
|
||||||
/* we must not resize the window while we have a static (non-floating) size */
|
* Unconditionally store the floating size, as it will need
|
||||||
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
|
* to be applied when returning from a non-floating state.
|
||||||
if (wind->shell_surface.libdecor.frame &&
|
*/
|
||||||
!libdecor_frame_is_floating(wind->shell_surface.libdecor.frame)) {
|
|
||||||
/* Commit the resize when we re-enter floating state */
|
|
||||||
wind->floating_resize_pending = SDL_TRUE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OverrideLibdecorLimits(window);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Update the window geometry. */
|
|
||||||
ConfigureWindowGeometry(window);
|
|
||||||
CommitLibdecorFrame(window);
|
|
||||||
|
|
||||||
/* windowed is unconditionally set, so we can trust it here */
|
|
||||||
wind->floating_width = window->windowed.w;
|
wind->floating_width = window->windowed.w;
|
||||||
wind->floating_height = window->windowed.h;
|
wind->floating_height = window->windowed.h;
|
||||||
|
|
||||||
|
/* Don't change the size of static (non-floating) windows. */
|
||||||
|
if (wind->floating) {
|
||||||
|
wind->requested_window_width = window->windowed.w;
|
||||||
|
wind->requested_window_height = window->windowed.h;
|
||||||
|
|
||||||
|
ConfigureWindowGeometry(window);
|
||||||
|
CommitLibdecorFrame(window);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wayland_GetWindowSizeInPixels(_THIS, SDL_Window *window, int *w, int *h)
|
void Wayland_GetWindowSizeInPixels(_THIS, SDL_Window *window, int *w, int *h)
|
||||||
|
@ -2201,7 +2118,7 @@ static void EGLTransparencyChangedCallback(void *userdata, const char *name, con
|
||||||
|
|
||||||
if (!newval) {
|
if (!newval) {
|
||||||
struct wl_region *region = wl_compositor_create_region(wind->waylandData->compositor);
|
struct wl_region *region = wl_compositor_create_region(wind->waylandData->compositor);
|
||||||
wl_region_add(region, 0, 0, wind->window_width, wind->window_height);
|
wl_region_add(region, 0, 0, wind->wl_window_width, wind->wl_window_height);
|
||||||
wl_surface_set_opaque_region(wind->surface, region);
|
wl_surface_set_opaque_region(wind->surface, region);
|
||||||
wl_region_destroy(region);
|
wl_region_destroy(region);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -106,14 +106,13 @@ struct SDL_WindowData
|
||||||
float windowed_scale_factor;
|
float windowed_scale_factor;
|
||||||
float pointer_scale_x;
|
float pointer_scale_x;
|
||||||
float pointer_scale_y;
|
float pointer_scale_y;
|
||||||
|
int requested_window_width, requested_window_height;
|
||||||
int drawable_width, drawable_height;
|
int drawable_width, drawable_height;
|
||||||
int fs_output_width, fs_output_height;
|
int wl_window_width, wl_window_height;
|
||||||
int window_width, window_height;
|
|
||||||
int system_min_required_width;
|
int system_min_required_width;
|
||||||
int system_min_required_height;
|
int system_min_required_height;
|
||||||
SDL_bool needs_resize_event;
|
SDL_DisplayID fullscreen_display;
|
||||||
SDL_bool floating_resize_pending;
|
SDL_bool floating;
|
||||||
SDL_bool was_floating;
|
|
||||||
SDL_bool is_fullscreen;
|
SDL_bool is_fullscreen;
|
||||||
SDL_bool in_fullscreen_transition;
|
SDL_bool in_fullscreen_transition;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue