winewayland.drv: Prepare to handle different coordinate spaces.

Introduce and use functions to convert between the window logical and
Wayland surface coordinate spaces. At the moment the two are the same
but this will change with the introduction of scaling support.
This commit is contained in:
Alexandros Frantzis 2023-10-24 15:40:00 +03:00 committed by Alexandre Julliard
parent 79bb13332f
commit 13578d6045
4 changed files with 86 additions and 29 deletions

View file

@ -50,30 +50,42 @@ 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;
POINT screen;
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_window(surface,
wl_fixed_to_double(sx),
wl_fixed_to_double(sy),
(int *)&screen.x, (int *)&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);
/* Hardware input events are in physical coordinates. */
if (!NtUserLogicalToPerMonitorDPIPhysicalPoint(hwnd, &screen)) return;
input.type = INPUT_MOUSE;
input.mi.dx = screen_x;
input.mi.dy = screen_y;
input.mi.dx = screen.x;
input.mi.dy = screen.y;
input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
TRACE("hwnd=%p wayland_xy=%.2f,%.2f screen_xy=%d,%d\n",
hwnd, wl_fixed_to_double(sx), wl_fixed_to_double(sy),
screen_x, screen_y);
(int)screen.x, (int)screen.y);
__wine_send_input(hwnd, &input, NULL);
}

View file

@ -385,14 +385,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 |
@ -401,6 +398,11 @@ static void wayland_surface_reconfigure_geometry(struct wayland_surface *surface
{
wayland_surface_get_rect_in_monitor(surface, &rect);
wayland_surface_coords_from_window(surface, rect.left, rect.top,
(int *)&rect.left, (int *)&rect.top);
wayland_surface_coords_from_window(surface, rect.right, rect.bottom,
(int *)&rect.right, (int *)&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) &&
@ -441,15 +443,18 @@ 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 win_width, win_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;
win_width = surface->window.rect.right - surface->window.rect.left;
win_height = surface->window.rect.bottom - surface->window.rect.top;
wayland_surface_coords_from_window(surface, win_width, win_height,
&width, &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, win_width, win_height, window->state,
surface->processing.width, surface->processing.height,
surface->processing.state, surface->current.width,
surface->current.height, surface->current.state);
@ -484,7 +489,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;
}
@ -621,3 +626,29 @@ err:
if (shm_buffer) wayland_shm_buffer_unref(shm_buffer);
return NULL;
}
/**********************************************************************
* wayland_surface_coords_from_window
*
* Converts the window (logical) coordinates to wayland surface-local coordinates.
*/
void wayland_surface_coords_from_window(struct wayland_surface *surface,
int window_x, int window_y,
int *surface_x, int *surface_y)
{
*surface_x = window_x;
*surface_y = window_y;
}
/**********************************************************************
* wayland_surface_coords_to_window
*
* Converts the surface-local coordinates to window (logical) coordinates.
*/
void wayland_surface_coords_to_window(struct wayland_surface *surface,
double surface_x, double surface_y,
int *window_x, int *window_y)
{
*window_x = round(surface_x);
*window_y = round(surface_y);
}

View file

@ -214,6 +214,12 @@ 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_window(struct wayland_surface *surface,
int window_x, int window_y,
int *surface_x, int *surface_y) DECLSPEC_HIDDEN;
void wayland_surface_coords_to_window(struct wayland_surface *surface,
double surface_x, double surface_y,
int *window_x, int *window_y) DECLSPEC_HIDDEN;
/**********************************************************************
* Wayland SHM buffer

View file

@ -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, window_width, window_height;
INT window_surf_width, window_surf_height;
UINT flags = 0;
uint32_t state;
DWORD style;
@ -434,21 +435,28 @@ static void wayland_configure_window(HWND hwnd)
flags |= SWP_FRAMECHANGED;
}
wayland_surface_coords_from_window(surface,
surface->window.rect.right -
surface->window.rect.left,
surface->window.rect.bottom -
surface->window.rect.top,
&window_surf_width, &window_surf_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_surf_width, window_surf_height,
surface->window.state))
{
flags |= SWP_NOSIZE;
}
wayland_surface_coords_to_window(surface, width, height,
&window_width, &window_height);
pthread_mutex_unlock(&surface->mutex);
TRACE("processing=%dx%d,%#x\n", width, height, state);
@ -457,7 +465,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 (window_width == 0 || window_height == 0) flags |= SWP_NOSIZE;
style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
if (!(state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) != !(style & WS_MAXIMIZE))
@ -474,7 +482,7 @@ static void wayland_configure_window(HWND hwnd)
flags |= SWP_NOSENDCHANGING;
}
NtUserSetWindowPos(hwnd, 0, 0, 0, width, height, flags);
NtUserSetWindowPos(hwnd, 0, 0, 0, window_width, window_height, flags);
}
/**********************************************************************