From: Alexandros Frantzis alexandros.frantzis@collabora.com
Introduce and use functions to convert between the Wine and Wayland surface coordinate spaces. At the moment the two are the same but this will change with the introduction of scaling support. --- dlls/winewayland.drv/wayland_pointer.c | 24 +++++--- dlls/winewayland.drv/wayland_surface.c | 79 ++++++++++++++++++++++---- dlls/winewayland.drv/waylanddrv.h | 4 ++ dlls/winewayland.drv/window.c | 24 +++++--- 4 files changed, 106 insertions(+), 25 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index ff376882d73..bbe61824561 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -50,21 +50,29 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy) { INPUT input = {0}; - RECT window_rect; + RECT *window_rect; HWND hwnd; int screen_x, screen_y; + struct wayland_surface *surface;
if (!(hwnd = wayland_pointer_get_focused_hwnd())) return; - if (!NtUserGetWindowRect(hwnd, &window_rect)) return; + if (!(surface = wayland_surface_lock_hwnd(hwnd))) return;
- screen_x = round(wl_fixed_to_double(sx)) + window_rect.left; - screen_y = round(wl_fixed_to_double(sy)) + window_rect.top; + window_rect = &surface->window.rect; + + wayland_surface_coords_to_wine(surface, 2, + wl_fixed_to_double(sx), &screen_x, + wl_fixed_to_double(sy), &screen_y); + screen_x += window_rect->left; + screen_y += window_rect->top; /* Sometimes, due to rounding, we may end up with pointer coordinates * slightly outside the target window, so bring them within bounds. */ - if (screen_x >= window_rect.right) screen_x = window_rect.right - 1; - else if (screen_x < window_rect.left) screen_x = window_rect.left; - if (screen_y >= window_rect.bottom) screen_y = window_rect.bottom - 1; - else if (screen_y < window_rect.top) screen_y = window_rect.top; + if (screen_x >= window_rect->right) screen_x = window_rect->right - 1; + else if (screen_x < window_rect->left) screen_x = window_rect->left; + if (screen_y >= window_rect->bottom) screen_y = window_rect->bottom - 1; + else if (screen_y < window_rect->top) screen_y = window_rect->top; + + pthread_mutex_unlock(&surface->mutex);
input.type = INPUT_MOUSE; input.mi.dx = screen_x; diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index ae4812ebb08..0ace11e3a0b 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -24,6 +24,7 @@
#include "config.h"
+#include <stdarg.h> #include <stdlib.h> #include <unistd.h>
@@ -380,14 +381,11 @@ static void wayland_surface_get_rect_in_monitor(struct wayland_surface *surface, * * Sets the xdg_surface geometry */ -static void wayland_surface_reconfigure_geometry(struct wayland_surface *surface) +static void wayland_surface_reconfigure_geometry(struct wayland_surface *surface, + int width, int height) { - 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 | @@ -396,6 +394,12 @@ static void wayland_surface_reconfigure_geometry(struct wayland_surface *surface { wayland_surface_get_rect_in_monitor(surface, &rect);
+ wayland_surface_coords_from_wine_rounded(surface, 4, + rect.left, &rect.left, + rect.top, &rect.top, + rect.right, &rect.right, + rect.bottom, &rect.bottom); + /* 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) && @@ -436,15 +440,19 @@ static void wayland_surface_reconfigure_geometry(struct wayland_surface *surface BOOL wayland_surface_reconfigure(struct wayland_surface *surface) { struct wayland_window_config *window = &surface->window; - int width, height; + int wine_width, wine_height, width, height;
if (!surface->xdg_toplevel) return TRUE;
- width = surface->window.rect.right - surface->window.rect.left; - height = surface->window.rect.bottom - surface->window.rect.top; + wine_width = surface->window.rect.right - surface->window.rect.left; + wine_height = surface->window.rect.bottom - surface->window.rect.top; + + wayland_surface_coords_from_wine_rounded(surface, 2, + wine_width, &width, + wine_height, &height);
TRACE("hwnd=%p window=%dx%d,%#x processing=%dx%d,%#x current=%dx%d,%#x\n", - surface->hwnd, width, height, window->state, + surface->hwnd, wine_width, wine_height, window->state, surface->processing.width, surface->processing.height, surface->processing.state, surface->current.width, surface->current.height, surface->current.state); @@ -479,7 +487,7 @@ BOOL wayland_surface_reconfigure(struct wayland_surface *surface) return FALSE; }
- wayland_surface_reconfigure_geometry(surface); + wayland_surface_reconfigure_geometry(surface, width, height);
return TRUE; } @@ -616,3 +624,54 @@ err: if (shm_buffer) wayland_shm_buffer_unref(shm_buffer); return NULL; } + +/********************************************************************** + * wayland_surface_coords_from_wine_rounded + * + * Converts the window-local wine coordinates to wayland surface-local coordinates + * rounding to the closest integer value. + * + * Expects 'count' pairs of (int wine_coord, int *wl_coord) parameters. + */ +void wayland_surface_coords_from_wine_rounded(struct wayland_surface *surface, + int count, ...) +{ + va_list ap; + int i; + + va_start(ap, count); + + for (i = 0; i < count; i++) + { + int wine_coord = va_arg(ap, int); + int *wl_coord = va_arg(ap, int *); + *wl_coord = wine_coord; + } + + va_end(ap); +} + +/********************************************************************** + * wayland_surface_coords_to_wine + * + * Converts the surface-local coordinates to wine windows-local coordinates. + * + * Expects 'count' pairs of (double wl_coord, int *wine_coord) parameters. + */ +void wayland_surface_coords_to_wine(struct wayland_surface *surface, + int count, ...) +{ + va_list ap; + int i; + + va_start(ap, count); + + for (i = 0; i < count; i++) + { + double wl_coord = va_arg(ap, double); + int *wine_coord = va_arg(ap, int *); + *wine_coord = round(wl_coord); + } + + va_end(ap); +} diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 4bcd9e6706e..340b792ba11 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -204,6 +204,10 @@ BOOL wayland_surface_reconfigure(struct wayland_surface *surface) DECLSPEC_HIDDE BOOL wayland_surface_config_is_compatible(struct wayland_surface_config *conf, int width, int height, enum wayland_surface_config_state state) DECLSPEC_HIDDEN; +void wayland_surface_coords_from_wine_rounded(struct wayland_surface *surface, + int count, ...) DECLSPEC_HIDDEN; +void wayland_surface_coords_to_wine(struct wayland_surface *surface, + int count, ...) DECLSPEC_HIDDEN;
/********************************************************************** * Wayland SHM buffer diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 57d2f15a06b..35b9ab258a3 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -384,7 +384,8 @@ static void wayland_resize_desktop(void) static void wayland_configure_window(HWND hwnd) { struct wayland_surface *surface; - INT width, height; + INT width, height, wine_width, wine_height; + INT window_wl_width, window_wl_height; UINT flags = 0; uint32_t state; DWORD style; @@ -434,21 +435,30 @@ static void wayland_configure_window(HWND hwnd) flags |= SWP_FRAMECHANGED; }
+ wayland_surface_coords_from_wine_rounded(surface, 2, + surface->window.rect.right - + surface->window.rect.left, + &window_wl_width, + surface->window.rect.bottom - + surface->window.rect.top, + &window_wl_height); + /* 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, + window_wl_width, window_wl_height, surface->window.state)) { flags |= SWP_NOSIZE; }
+ wayland_surface_coords_to_wine(surface, 2, + (double)width, &wine_width, + (double)height, &wine_height); + pthread_mutex_unlock(&surface->mutex);
TRACE("processing=%dx%d,%#x\n", width, height, state); @@ -457,7 +467,7 @@ static void wayland_configure_window(HWND hwnd) if (needs_exit_size_move) send_message(hwnd, WM_EXITSIZEMOVE, 0, 0);
flags |= SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE; - if (width == 0 || height == 0) flags |= SWP_NOSIZE; + if (wine_width == 0 || wine_height == 0) flags |= SWP_NOSIZE;
style = NtUserGetWindowLongW(hwnd, GWL_STYLE); if (!(state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) != !(style & WS_MAXIMIZE)) @@ -474,7 +484,7 @@ static void wayland_configure_window(HWND hwnd) flags |= SWP_NOSENDCHANGING; }
- NtUserSetWindowPos(hwnd, 0, 0, 0, width, height, flags); + NtUserSetWindowPos(hwnd, 0, 0, 0, wine_width, wine_height, flags); }
/**********************************************************************