Module: wine
Branch: master
Commit: 89c36c11fd44ec8a4921d05304afb83f907b47ae
URL: https://gitlab.winehq.org/wine/wine/-/commit/89c36c11fd44ec8a4921d05304afb8…
Author: Alexandros Frantzis <alexandros.frantzis(a)collabora.com>
Date: Tue Oct 10 12:04:12 2023 +0300
winewayland.drv: Avoid resizing fullscreen windows.
If the window is already fullscreen and its size is compatible with what
the compositor is requesting, don't force a resize, since some applications
are very insistent on a particular fullscreen size (which may not match
the monitor size).
---
dlls/winewayland.drv/wayland_surface.c | 6 +++---
dlls/winewayland.drv/waylanddrv.h | 3 +++
dlls/winewayland.drv/window.c | 15 +++++++++++++++
3 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c
index 17d1fffc29b..ae4812ebb08 100644
--- a/dlls/winewayland.drv/wayland_surface.c
+++ b/dlls/winewayland.drv/wayland_surface.c
@@ -324,9 +324,9 @@ void wayland_surface_attach_shm(struct wayland_surface *surface,
* Checks whether a wayland_surface_config object is compatible with the
* the provided arguments.
*/
-static BOOL wayland_surface_config_is_compatible(struct wayland_surface_config *conf,
- int width, int height,
- enum wayland_surface_config_state state)
+BOOL wayland_surface_config_is_compatible(struct wayland_surface_config *conf,
+ int width, int height,
+ enum wayland_surface_config_state state)
{
static enum wayland_surface_config_state mask =
WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED;
diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h
index e1dc58bdc80..4bcd9e6706e 100644
--- a/dlls/winewayland.drv/waylanddrv.h
+++ b/dlls/winewayland.drv/waylanddrv.h
@@ -201,6 +201,9 @@ void wayland_surface_attach_shm(struct wayland_surface *surface,
HRGN surface_damage_region) DECLSPEC_HIDDEN;
struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd) DECLSPEC_HIDDEN;
BOOL wayland_surface_reconfigure(struct wayland_surface *surface) DECLSPEC_HIDDEN;
+BOOL wayland_surface_config_is_compatible(struct wayland_surface_config *conf,
+ int width, int height,
+ enum wayland_surface_config_state state) DECLSPEC_HIDDEN;
/**********************************************************************
* Wayland SHM buffer
diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c
index 2854279bd90..57d2f15a06b 100644
--- a/dlls/winewayland.drv/window.c
+++ b/dlls/winewayland.drv/window.c
@@ -434,6 +434,21 @@ static void wayland_configure_window(HWND hwnd)
flags |= SWP_FRAMECHANGED;
}
+ /* If the window is already fullscreen and its size is compatible with what
+ * the compositor is requesting, don't force a resize, since some applications
+ * are very insistent on a particular fullscreen size (which may not match
+ * the monitor size). */
+ if ((surface->window.state & WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN) &&
+ wayland_surface_config_is_compatible(&surface->processing,
+ surface->window.rect.right -
+ surface->window.rect.left,
+ surface->window.rect.bottom -
+ surface->window.rect.top,
+ surface->window.state))
+ {
+ flags |= SWP_NOSIZE;
+ }
+
pthread_mutex_unlock(&surface->mutex);
TRACE("processing=%dx%d,%#x\n", width, height, state);
Module: wine
Branch: master
Commit: dfcd2d8b70dd54aa1f43ecab0d02b63418952c17
URL: https://gitlab.winehq.org/wine/wine/-/commit/dfcd2d8b70dd54aa1f43ecab0d02b6…
Author: Alexandros Frantzis <alexandros.frantzis(a)collabora.com>
Date: Fri Sep 29 16:49:44 2023 +0300
winewayland.drv: Use surface geometry to satisfy state size constraints.
The maximized and fullscreen states disallow surface contents that are
larger than the configured size. However, if we have a larger surface,
and only part of the surface contains useful client data, we can inform
the compositor using xdg_surface_set_geometry, so that only the
specified region is considered for compositor-side positioning and
state constraints.
We use the geometry to support the presentation of windows that insist
on particular positions and sizes which may not match the compositor's
requested size (e.g., fullscreen but may overshoot a few pixels outside
the monitor boundary).
---
dlls/winewayland.drv/wayland_surface.c | 92 +++++++++++++++++++++++++++++++---
1 file changed, 85 insertions(+), 7 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c
index 124d15821bf..b581cec1b46 100644
--- a/dlls/winewayland.drv/wayland_surface.c
+++ b/dlls/winewayland.drv/wayland_surface.c
@@ -334,21 +334,97 @@ static BOOL wayland_surface_configure_is_compatible(struct wayland_surface_confi
/* We require the same state. */
if ((state & mask) != (conf->state & mask)) return FALSE;
- /* The maximized state requires the configured size. */
+ /* The maximized state requires the configured size. During surface
+ * reconfiguration we can use surface geometry to provide smaller areas
+ * from larger sizes, so only smaller sizes are incompatible. */
if ((conf->state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) &&
- (width != conf->width || height != conf->height))
+ (width < conf->width || height < conf->height))
{
return FALSE;
}
- /* The fullscreen state requires at most the configured size. */
- if ((conf->state & WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN) &&
- (width > conf->width || height > conf->height))
+ /* The fullscreen state requires a size smaller or equal to the configured
+ * size. If we have a larger size, we can use surface geometry during
+ * surface reconfiguration to provide the smaller size, so we are always
+ * compatible with a fullscreen state. */
+
+ return TRUE;
+}
+
+/**********************************************************************
+ * wayland_surface_get_rect_in_monitor
+ *
+ * Gets the largest rectangle within a surface's window (in window coordinates)
+ * that is visible in a monitor.
+ */
+static void wayland_surface_get_rect_in_monitor(struct wayland_surface *surface,
+ RECT *rect)
+{
+ HMONITOR hmonitor;
+ MONITORINFO mi;
+
+ mi.cbSize = sizeof(mi);
+ if (!(hmonitor = NtUserMonitorFromRect(&surface->window.rect, 0)) ||
+ !NtUserGetMonitorInfo(hmonitor, (MONITORINFO *)&mi))
{
- return FALSE;
+ SetRectEmpty(rect);
+ return;
}
- return TRUE;
+ intersect_rect(rect, &mi.rcMonitor, &surface->window.rect);
+ OffsetRect(rect, -surface->window.rect.left, -surface->window.rect.top);
+}
+
+/**********************************************************************
+ * wayland_surface_reconfigure_geometry
+ *
+ * Sets the xdg_surface geometry
+ */
+static void wayland_surface_reconfigure_geometry(struct wayland_surface *surface)
+{
+ int width, height;
+ RECT rect;
+
+ width = surface->window.rect.right - surface->window.rect.left;
+ height = surface->window.rect.bottom - surface->window.rect.top;
+
+ /* If the window size is bigger than the current state accepts, use the
+ * largest visible (from Windows' perspective) subregion of the window. */
+ if ((surface->current.state & (WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED |
+ WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN)) &&
+ (width > surface->current.width || height > surface->current.height))
+ {
+ wayland_surface_get_rect_in_monitor(surface, &rect);
+
+ /* If the window rect in the monitor is smaller than required,
+ * fall back to an appropriately sized rect at the top-left. */
+ if ((surface->current.state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) &&
+ (rect.right - rect.left < surface->current.width ||
+ rect.bottom - rect.top < surface->current.height))
+ {
+ SetRect(&rect, 0, 0, surface->current.width, surface->current.height);
+ }
+ else
+ {
+ rect.right = min(rect.right, rect.left + surface->current.width);
+ rect.bottom = min(rect.bottom, rect.top + surface->current.height);
+ }
+ TRACE("Window is too large for Wayland state, using subregion\n");
+ }
+ else
+ {
+ SetRect(&rect, 0, 0, width, height);
+ }
+
+ TRACE("hwnd=%p geometry=%s\n", surface->hwnd, wine_dbgstr_rect(&rect));
+
+ if (!IsRectEmpty(&rect))
+ {
+ xdg_surface_set_window_geometry(surface->xdg_surface,
+ rect.left, rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top);
+ }
}
/**********************************************************************
@@ -403,6 +479,8 @@ BOOL wayland_surface_reconfigure(struct wayland_surface *surface)
return FALSE;
}
+ wayland_surface_reconfigure_geometry(surface);
+
return TRUE;
}