winewayland.drv: Handle pointer motion events.
[wine.git] / dlls / winewayland.drv / wayland_pointer.c
blobfdae963439a287552a6be1c0fcfe04a2abd303c2
1 /*
2 * Wayland pointer handling
4 * Copyright (c) 2020 Alexandros Frantzis for Collabora Ltd
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
27 #include <math.h>
29 #include "waylanddrv.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
34 static HWND wayland_pointer_get_focused_hwnd(void)
36 struct wayland_pointer *pointer = &process_wayland.pointer;
37 HWND hwnd;
39 pthread_mutex_lock(&pointer->mutex);
40 hwnd = pointer->focused_hwnd;
41 pthread_mutex_unlock(&pointer->mutex);
43 return hwnd;
46 static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
47 uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
49 INPUT input = {0};
50 RECT window_rect;
51 HWND hwnd;
52 int screen_x, screen_y;
54 if (!(hwnd = wayland_pointer_get_focused_hwnd())) return;
55 if (!NtUserGetWindowRect(hwnd, &window_rect)) return;
57 screen_x = round(wl_fixed_to_double(sx)) + window_rect.left;
58 screen_y = round(wl_fixed_to_double(sy)) + window_rect.top;
59 /* Sometimes, due to rounding, we may end up with pointer coordinates
60 * slightly outside the target window, so bring them within bounds. */
61 if (screen_x >= window_rect.right) screen_x = window_rect.right - 1;
62 else if (screen_x < window_rect.left) screen_x = window_rect.left;
63 if (screen_y >= window_rect.bottom) screen_y = window_rect.bottom - 1;
64 else if (screen_y < window_rect.top) screen_y = window_rect.top;
66 input.type = INPUT_MOUSE;
67 input.mi.dx = screen_x;
68 input.mi.dy = screen_y;
69 input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
71 TRACE("hwnd=%p wayland_xy=%.2f,%.2f screen_xy=%d,%d\n",
72 hwnd, wl_fixed_to_double(sx), wl_fixed_to_double(sy),
73 screen_x, screen_y);
75 __wine_send_input(hwnd, &input, NULL);
78 static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
79 uint32_t serial, struct wl_surface *wl_surface,
80 wl_fixed_t sx, wl_fixed_t sy)
82 struct wayland_pointer *pointer = &process_wayland.pointer;
83 HWND hwnd;
85 if (!wl_surface) return;
86 /* The wl_surface user data remains valid and immutable for the whole
87 * lifetime of the object, so it's safe to access without locking. */
88 hwnd = wl_surface_get_user_data(wl_surface);
90 TRACE("hwnd=%p\n", hwnd);
92 pthread_mutex_lock(&pointer->mutex);
93 pointer->focused_hwnd = hwnd;
94 pthread_mutex_unlock(&pointer->mutex);
96 /* Handle the enter as a motion, to account for cases where the
97 * window first appears beneath the pointer and won't get a separate
98 * motion event. */
99 pointer_handle_motion(data, wl_pointer, 0, sx, sy);
102 static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
103 uint32_t serial, struct wl_surface *wl_surface)
105 struct wayland_pointer *pointer = &process_wayland.pointer;
107 if (!wl_surface) return;
109 TRACE("hwnd=%p\n", wl_surface_get_user_data(wl_surface));
111 pthread_mutex_lock(&pointer->mutex);
112 pointer->focused_hwnd = NULL;
113 pthread_mutex_unlock(&pointer->mutex);
116 static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
117 uint32_t serial, uint32_t time, uint32_t button,
118 uint32_t state)
122 static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
123 uint32_t time, uint32_t axis, wl_fixed_t value)
127 static void pointer_handle_frame(void *data, struct wl_pointer *wl_pointer)
131 static void pointer_handle_axis_source(void *data, struct wl_pointer *wl_pointer,
132 uint32_t axis_source)
136 static void pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer,
137 uint32_t time, uint32_t axis)
141 static void pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_pointer,
142 uint32_t axis, int32_t discrete)
146 static const struct wl_pointer_listener pointer_listener =
148 pointer_handle_enter,
149 pointer_handle_leave,
150 pointer_handle_motion,
151 pointer_handle_button,
152 pointer_handle_axis,
153 pointer_handle_frame,
154 pointer_handle_axis_source,
155 pointer_handle_axis_stop,
156 pointer_handle_axis_discrete
159 void wayland_pointer_init(struct wl_pointer *wl_pointer)
161 struct wayland_pointer *pointer = &process_wayland.pointer;
163 pthread_mutex_lock(&pointer->mutex);
164 pointer->wl_pointer = wl_pointer;
165 pointer->focused_hwnd = NULL;
166 pthread_mutex_unlock(&pointer->mutex);
167 wl_pointer_add_listener(pointer->wl_pointer, &pointer_listener, NULL);
170 void wayland_pointer_deinit(void)
172 struct wayland_pointer *pointer = &process_wayland.pointer;
174 pthread_mutex_lock(&pointer->mutex);
175 wl_pointer_release(pointer->wl_pointer);
176 pointer->wl_pointer = NULL;
177 pointer->focused_hwnd = NULL;
178 pthread_mutex_unlock(&pointer->mutex);