From: Alexandros Frantzis alexandros.frantzis@collabora.com
Since Wayland doesn't allow querying or setting the absolute position of surfaces, the position of a window in the Windows virtual screen space and its actual position in the compositor space are not in sync. This can lead to situations where parts of a window become apparently inaccessible to mouse input, because although those parts are visible from a Wayland perspective they are outside the Windows virtual screen.
As a basic workaround, handling the common case of a single monitor, move windows to the origin of the virtual screen space (0,0), to maximize the window area that is available for user input.
We make an exception for windows that are fullscreen, since in such a state some applications insist on a very particular position and size, and trying to force our preference could lead to infinite repositioning loops. In such cases our xdg_surface geometry logic may kick in to ensure that we don't violate size constraints. --- dlls/winewayland.drv/wayland_surface.c | 6 ++--- dlls/winewayland.drv/waylanddrv.h | 6 ++++- dlls/winewayland.drv/window.c | 37 ++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 4 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..d4cde8bd29c 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -54,7 +54,8 @@ extern struct wayland process_wayland DECLSPEC_HIDDEN; enum wayland_window_message { WM_WAYLAND_INIT_DISPLAY_DEVICES = 0x80001000, - WM_WAYLAND_CONFIGURE = 0x80001001 + WM_WAYLAND_CONFIGURE = 0x80001001, + WM_WAYLAND_SYNC_WINDOW_POSITION = 0x80001002 };
enum wayland_surface_config_state @@ -201,6 +202,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 2a45642f889..95373efadca 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -270,6 +270,17 @@ static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) surface->processing.processed = TRUE; }
+ /* Move the window to the monitor origin to maximize the available window + * area that is available for user input. Don't perform the move if the + * window is fullscreen, since some applications are very insistent on + * a particular fullscreen position (which may not match the monitor + * origin). */ + if (!(surface->window.state & WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN) && + (surface->window.rect.top != 0 || surface->window.rect.left != 0)) + { + NtUserPostMessage(data->hwnd, WM_WAYLAND_SYNC_WINDOW_POSITION, 0, 0); + } + out: pthread_mutex_unlock(&surface->mutex); wl_display_flush(process_wayland.wl_display); @@ -427,6 +438,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); @@ -455,6 +481,14 @@ static void wayland_configure_window(HWND hwnd) NtUserSetWindowPos(hwnd, 0, 0, 0, width, height, flags); }
+static void wayland_sync_window_position(HWND hwnd) +{ + DWORD flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | + SWP_NOSENDCHANGING | SWP_NOSIZE; + + NtUserSetWindowPos(hwnd, 0, 0, 0, 0, 0, flags); +} + /********************************************************************** * WAYLAND_WindowMessage */ @@ -469,6 +503,9 @@ LRESULT WAYLAND_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) case WM_WAYLAND_CONFIGURE: wayland_configure_window(hwnd); return 0; + case WM_WAYLAND_SYNC_WINDOW_POSITION: + wayland_sync_window_position(hwnd); + return 0; default: FIXME("got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, (long)wp, lp); return 0;