From: Attila Fidan dev@print0.net
This may be used by the compositor to warp the Wayland pointer to where the win32 cursor is upon unlock, if it's within surface bounds. --- dlls/winewayland.drv/wayland_pointer.c | 72 ++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 9 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index c20ba170285..ea449dd3cc9 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -46,6 +46,63 @@ static HWND wayland_pointer_get_focused_hwnd(void) return hwnd; }
+static void reapply_cursor_clipping(void) +{ + RECT rect; + UINT context = NtUserSetThreadDpiAwarenessContext(NTUSER_DPI_PER_MONITOR_AWARE); + if (NtUserGetClipCursor(&rect)) NtUserClipCursor(&rect); + NtUserSetThreadDpiAwarenessContext(context); +} + +static void update_cursor_position_hint(HWND hwnd) +{ + struct wayland_pointer *pointer = &process_wayland.pointer; + struct wayland_win_data *data; + struct wayland_surface *surface; + POINT cursor_pos; + int warp_x, warp_y; + BOOL hint_updated = FALSE; + + NtUserGetCursorPos(&cursor_pos); + + if (!(data = wayland_win_data_get(hwnd))) return; + if (!(surface = data->wayland_surface)) + { + wayland_win_data_release(data); + return; + } + wayland_surface_coords_from_window(surface, + cursor_pos.x - surface->window.rect.left, + cursor_pos.y - surface->window.rect.top, + &warp_x, &warp_y); + wayland_win_data_release(data); + + pthread_mutex_lock(&pointer->mutex); + if (hwnd == pointer->constraint_hwnd && pointer->zwp_locked_pointer_v1) + { + hint_updated = TRUE; + zwp_locked_pointer_v1_set_cursor_position_hint( + pointer->zwp_locked_pointer_v1, + wl_fixed_from_int(warp_x), + wl_fixed_from_int(warp_y)); + } + pthread_mutex_unlock(&pointer->mutex); + + if (hint_updated) + { + if (!(data = wayland_win_data_get(hwnd))) return; + if (!(surface = data->wayland_surface)) + { + wayland_win_data_release(data); + return; + } + wl_surface_commit(surface->wl_surface); + wayland_win_data_release(data); + TRACE("hwnd=%p wayland_xy=%d,%d screen_xy=%d,%d\n", + hwnd, warp_x, warp_y, (int)cursor_pos.x, (int)cursor_pos.y); + } +} + static void pointer_handle_motion_internal(wl_fixed_t sx, wl_fixed_t sy) { INPUT input = {0}; @@ -272,6 +329,7 @@ static void relative_pointer_v1_relative_motion(void *private,
wayland_win_data_release(data);
+ reapply_cursor_clipping();
input.type = INPUT_MOUSE; input.mi.dx = screen.x; @@ -624,14 +682,6 @@ clear_cursor: } }
-static void reapply_cursor_clipping(void) -{ - RECT rect; - UINT context = NtUserSetThreadDpiAwarenessContext(NTUSER_DPI_PER_MONITOR_AWARE); - if (NtUserGetClipCursor(&rect)) NtUserClipCursor(&rect); - NtUserSetThreadDpiAwarenessContext(context); -} - static void wayland_set_cursor(HWND hwnd, HCURSOR hcursor, BOOL use_hcursor) { struct wayland_pointer *pointer = &process_wayland.pointer; @@ -885,6 +935,7 @@ void WAYLAND_SetCursor(HWND hwnd, HCURSOR hcursor) BOOL WAYLAND_ClipCursor(const RECT *clip, BOOL reset) { struct wayland_pointer *pointer = &process_wayland.pointer; + HWND hwnd; struct wl_surface *wl_surface = NULL; struct wayland_surface *surface = NULL; struct wayland_win_data *data; @@ -893,7 +944,8 @@ BOOL WAYLAND_ClipCursor(const RECT *clip, BOOL reset)
TRACE("clip=%s reset=%d\n", wine_dbgstr_rect(clip), reset);
- if (!(data = wayland_win_data_get(NtUserGetForegroundWindow()))) return FALSE; + hwnd = NtUserGetForegroundWindow(); + if (!(data = wayland_win_data_get(hwnd))) return FALSE; if ((surface = data->wayland_surface)) { wl_surface = surface->wl_surface; @@ -902,6 +954,8 @@ BOOL WAYLAND_ClipCursor(const RECT *clip, BOOL reset) } wayland_win_data_release(data);
+ update_cursor_position_hint(hwnd); + /* Since we are running in the context of the foreground thread we know * that the wl_surface of the foreground HWND will not be invalidated, * so we can access it without having the win data lock. */