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
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
;
39 pthread_mutex_lock(&pointer
->mutex
);
40 hwnd
= pointer
->focused_hwnd
;
41 pthread_mutex_unlock(&pointer
->mutex
);
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
)
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
),
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
;
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
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
,
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
,
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
);