1 #define _POSIX_C_SOURCE 200809L
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <time.h>
6 #include <wayland-server-core.h>
7 #include <wlr/types/wlr_input_device.h>
8 #include <wlr/util/log.h>
9 #include "types/wlr_seat.h"
10 #include "util/signal.h"
11 #include "util/array.h"
12 
default_pointer_enter(struct wlr_seat_pointer_grab * grab,struct wlr_surface * surface,double sx,double sy)13 static void default_pointer_enter(struct wlr_seat_pointer_grab *grab,
14 		struct wlr_surface *surface, double sx, double sy) {
15 	wlr_seat_pointer_enter(grab->seat, surface, sx, sy);
16 }
17 
default_pointer_clear_focus(struct wlr_seat_pointer_grab * grab)18 static void default_pointer_clear_focus(struct wlr_seat_pointer_grab *grab) {
19 	wlr_seat_pointer_clear_focus(grab->seat);
20 }
21 
default_pointer_motion(struct wlr_seat_pointer_grab * grab,uint32_t time,double sx,double sy)22 static void default_pointer_motion(struct wlr_seat_pointer_grab *grab,
23 		uint32_t time, double sx, double sy) {
24 	wlr_seat_pointer_send_motion(grab->seat, time, sx, sy);
25 }
26 
default_pointer_button(struct wlr_seat_pointer_grab * grab,uint32_t time,uint32_t button,enum wlr_button_state state)27 static uint32_t default_pointer_button(struct wlr_seat_pointer_grab *grab,
28 		uint32_t time, uint32_t button, enum wlr_button_state state) {
29 	return wlr_seat_pointer_send_button(grab->seat, time, button, state);
30 }
31 
default_pointer_axis(struct wlr_seat_pointer_grab * grab,uint32_t time,enum wlr_axis_orientation orientation,double value,int32_t value_discrete,enum wlr_axis_source source)32 static void default_pointer_axis(struct wlr_seat_pointer_grab *grab,
33 		uint32_t time, enum wlr_axis_orientation orientation, double value,
34 		int32_t value_discrete, enum wlr_axis_source source) {
35 	wlr_seat_pointer_send_axis(grab->seat, time, orientation, value,
36 		value_discrete, source);
37 }
38 
default_pointer_frame(struct wlr_seat_pointer_grab * grab)39 static void default_pointer_frame(struct wlr_seat_pointer_grab *grab) {
40 	wlr_seat_pointer_send_frame(grab->seat);
41 }
42 
default_pointer_cancel(struct wlr_seat_pointer_grab * grab)43 static void default_pointer_cancel(struct wlr_seat_pointer_grab *grab) {
44 	// cannot be cancelled
45 }
46 
47 const struct wlr_pointer_grab_interface default_pointer_grab_impl = {
48 	.enter = default_pointer_enter,
49 	.clear_focus = default_pointer_clear_focus,
50 	.motion = default_pointer_motion,
51 	.button = default_pointer_button,
52 	.axis = default_pointer_axis,
53 	.frame = default_pointer_frame,
54 	.cancel = default_pointer_cancel,
55 };
56 
57 
pointer_send_frame(struct wl_resource * resource)58 static void pointer_send_frame(struct wl_resource *resource) {
59 	if (wl_resource_get_version(resource) >=
60 			WL_POINTER_FRAME_SINCE_VERSION) {
61 		wl_pointer_send_frame(resource);
62 	}
63 }
64 
65 static const struct wl_pointer_interface pointer_impl;
66 
wlr_seat_client_from_pointer_resource(struct wl_resource * resource)67 struct wlr_seat_client *wlr_seat_client_from_pointer_resource(
68 		struct wl_resource *resource) {
69 	assert(wl_resource_instance_of(resource, &wl_pointer_interface,
70 		&pointer_impl));
71 	return wl_resource_get_user_data(resource);
72 }
73 
74 static const struct wlr_surface_role pointer_cursor_surface_role = {
75 	.name = "wl_pointer-cursor",
76 };
77 
pointer_set_cursor(struct wl_client * client,struct wl_resource * pointer_resource,uint32_t serial,struct wl_resource * surface_resource,int32_t hotspot_x,int32_t hotspot_y)78 static void pointer_set_cursor(struct wl_client *client,
79 		struct wl_resource *pointer_resource, uint32_t serial,
80 		struct wl_resource *surface_resource,
81 		int32_t hotspot_x, int32_t hotspot_y) {
82 	struct wlr_seat_client *seat_client =
83 		wlr_seat_client_from_pointer_resource(pointer_resource);
84 	if (seat_client == NULL) {
85 		return;
86 	}
87 
88 	struct wlr_surface *surface = NULL;
89 	if (surface_resource != NULL) {
90 		surface = wlr_surface_from_resource(surface_resource);
91 		if (!wlr_surface_set_role(surface, &pointer_cursor_surface_role, NULL,
92 				surface_resource, WL_POINTER_ERROR_ROLE)) {
93 			return;
94 		}
95 	}
96 
97 	struct wlr_seat_pointer_request_set_cursor_event event = {
98 		.seat_client = seat_client,
99 		.surface = surface,
100 		.serial = serial,
101 		.hotspot_x = hotspot_x,
102 		.hotspot_y = hotspot_y,
103 	};
104 	wlr_signal_emit_safe(&seat_client->seat->events.request_set_cursor, &event);
105 }
106 
pointer_release(struct wl_client * client,struct wl_resource * resource)107 static void pointer_release(struct wl_client *client,
108 		struct wl_resource *resource) {
109 	wl_resource_destroy(resource);
110 }
111 
112 static const struct wl_pointer_interface pointer_impl = {
113 	.set_cursor = pointer_set_cursor,
114 	.release = pointer_release,
115 };
116 
pointer_handle_resource_destroy(struct wl_resource * resource)117 static void pointer_handle_resource_destroy(struct wl_resource *resource) {
118 	wl_list_remove(wl_resource_get_link(resource));
119 	seat_client_destroy_pointer(resource);
120 }
121 
122 
wlr_seat_pointer_surface_has_focus(struct wlr_seat * wlr_seat,struct wlr_surface * surface)123 bool wlr_seat_pointer_surface_has_focus(struct wlr_seat *wlr_seat,
124 		struct wlr_surface *surface) {
125 	return surface == wlr_seat->pointer_state.focused_surface;
126 }
127 
seat_pointer_handle_surface_destroy(struct wl_listener * listener,void * data)128 static void seat_pointer_handle_surface_destroy(struct wl_listener *listener,
129 		void *data) {
130 	struct wlr_seat_pointer_state *state =
131 		wl_container_of(listener, state, surface_destroy);
132 	wl_list_remove(&state->surface_destroy.link);
133 	wl_list_init(&state->surface_destroy.link);
134 	wlr_seat_pointer_clear_focus(state->seat);
135 }
136 
seat_client_send_pointer_leave_raw(struct wlr_seat_client * seat_client,struct wlr_surface * surface)137 void seat_client_send_pointer_leave_raw(struct wlr_seat_client *seat_client,
138 		struct wlr_surface *surface) {
139 	uint32_t serial = wlr_seat_client_next_serial(seat_client);
140 	struct wl_resource *resource;
141 	wl_resource_for_each(resource, &seat_client->pointers) {
142 		if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
143 			continue;
144 		}
145 
146 		wl_pointer_send_leave(resource, serial, surface->resource);
147 		pointer_send_frame(resource);
148 	}
149 }
150 
wlr_seat_pointer_enter(struct wlr_seat * wlr_seat,struct wlr_surface * surface,double sx,double sy)151 void wlr_seat_pointer_enter(struct wlr_seat *wlr_seat,
152 		struct wlr_surface *surface, double sx, double sy) {
153 	if (wlr_seat->pointer_state.focused_surface == surface) {
154 		// this surface already got an enter notify
155 		return;
156 	}
157 
158 	struct wlr_seat_client *client = NULL;
159 	if (surface) {
160 		struct wl_client *wl_client = wl_resource_get_client(surface->resource);
161 		client = wlr_seat_client_for_wl_client(wlr_seat, wl_client);
162 	}
163 
164 	struct wlr_seat_client *focused_client =
165 		wlr_seat->pointer_state.focused_client;
166 	struct wlr_surface *focused_surface =
167 		wlr_seat->pointer_state.focused_surface;
168 
169 	// leave the previously entered surface
170 	if (focused_client != NULL && focused_surface != NULL) {
171 		seat_client_send_pointer_leave_raw(focused_client, focused_surface);
172 	}
173 
174 	// enter the current surface
175 	if (client != NULL && surface != NULL) {
176 		uint32_t serial = wlr_seat_client_next_serial(client);
177 		struct wl_resource *resource;
178 		wl_resource_for_each(resource, &client->pointers) {
179 			if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
180 				continue;
181 			}
182 
183 			wl_pointer_send_enter(resource, serial, surface->resource,
184 				wl_fixed_from_double(sx), wl_fixed_from_double(sy));
185 			pointer_send_frame(resource);
186 		}
187 	}
188 
189 	// reinitialize the focus destroy events
190 	wl_list_remove(&wlr_seat->pointer_state.surface_destroy.link);
191 	wl_list_init(&wlr_seat->pointer_state.surface_destroy.link);
192 	if (surface != NULL) {
193 		wl_signal_add(&surface->events.destroy,
194 			&wlr_seat->pointer_state.surface_destroy);
195 		wlr_seat->pointer_state.surface_destroy.notify =
196 			seat_pointer_handle_surface_destroy;
197 	}
198 
199 	wlr_seat->pointer_state.focused_client = client;
200 	wlr_seat->pointer_state.focused_surface = surface;
201 	if (surface != NULL) {
202 		wlr_seat_pointer_warp(wlr_seat, sx, sy);
203 	} else {
204 		wlr_seat_pointer_warp(wlr_seat, NAN, NAN);
205 	}
206 
207 	struct wlr_seat_pointer_focus_change_event event = {
208 		.seat = wlr_seat,
209 		.new_surface = surface,
210 		.old_surface = focused_surface,
211 		.sx = sx,
212 		.sy = sy,
213 	};
214 	wlr_signal_emit_safe(&wlr_seat->pointer_state.events.focus_change, &event);
215 }
216 
wlr_seat_pointer_clear_focus(struct wlr_seat * wlr_seat)217 void wlr_seat_pointer_clear_focus(struct wlr_seat *wlr_seat) {
218 	wlr_seat_pointer_enter(wlr_seat, NULL, 0, 0);
219 }
220 
wlr_seat_pointer_warp(struct wlr_seat * wlr_seat,double sx,double sy)221 void wlr_seat_pointer_warp(struct wlr_seat *wlr_seat, double sx, double sy) {
222 	wlr_seat->pointer_state.sx = sx;
223 	wlr_seat->pointer_state.sy = sy;
224 }
225 
wlr_seat_pointer_send_motion(struct wlr_seat * wlr_seat,uint32_t time,double sx,double sy)226 void wlr_seat_pointer_send_motion(struct wlr_seat *wlr_seat, uint32_t time,
227 		double sx, double sy) {
228 	struct wlr_seat_client *client = wlr_seat->pointer_state.focused_client;
229 	if (client == NULL) {
230 		return;
231 	}
232 
233 	if (wlr_seat->pointer_state.sx == sx && wlr_seat->pointer_state.sy == sy) {
234 		return;
235 	}
236 
237 	struct wl_resource *resource;
238 	wl_resource_for_each(resource, &client->pointers) {
239 		if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
240 			continue;
241 		}
242 
243 		wl_pointer_send_motion(resource, time, wl_fixed_from_double(sx),
244 			wl_fixed_from_double(sy));
245 	}
246 
247 	wlr_seat_pointer_warp(wlr_seat, sx, sy);
248 }
249 
wlr_seat_pointer_send_button(struct wlr_seat * wlr_seat,uint32_t time,uint32_t button,enum wlr_button_state state)250 uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, uint32_t time,
251 		uint32_t button, enum wlr_button_state state) {
252 	struct wlr_seat_client *client = wlr_seat->pointer_state.focused_client;
253 	if (client == NULL) {
254 		return 0;
255 	}
256 
257 	uint32_t serial = wlr_seat_client_next_serial(client);
258 	struct wl_resource *resource;
259 	wl_resource_for_each(resource, &client->pointers) {
260 		if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
261 			continue;
262 		}
263 
264 		wl_pointer_send_button(resource, serial, time, button, state);
265 	}
266 	return serial;
267 }
268 
wlr_seat_pointer_send_axis(struct wlr_seat * wlr_seat,uint32_t time,enum wlr_axis_orientation orientation,double value,int32_t value_discrete,enum wlr_axis_source source)269 void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time,
270 		enum wlr_axis_orientation orientation, double value,
271 		int32_t value_discrete, enum wlr_axis_source source) {
272 	struct wlr_seat_client *client = wlr_seat->pointer_state.focused_client;
273 	if (client == NULL) {
274 		return;
275 	}
276 
277 	struct wl_resource *resource;
278 	wl_resource_for_each(resource, &client->pointers) {
279 		if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
280 			continue;
281 		}
282 
283 		uint32_t version = wl_resource_get_version(resource);
284 
285 		if (version >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) {
286 			wl_pointer_send_axis_source(resource, source);
287 		}
288 		if (value) {
289 			if (value_discrete &&
290 					version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) {
291 				wl_pointer_send_axis_discrete(resource, orientation,
292 					value_discrete);
293 			}
294 
295 			wl_pointer_send_axis(resource, time, orientation,
296 				wl_fixed_from_double(value));
297 		} else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) {
298 			wl_pointer_send_axis_stop(resource, time, orientation);
299 		}
300 	}
301 }
302 
wlr_seat_pointer_send_frame(struct wlr_seat * wlr_seat)303 void wlr_seat_pointer_send_frame(struct wlr_seat *wlr_seat) {
304 	struct wlr_seat_client *client = wlr_seat->pointer_state.focused_client;
305 	if (client == NULL) {
306 		return;
307 	}
308 
309 	struct wl_resource *resource;
310 	wl_resource_for_each(resource, &client->pointers) {
311 		if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
312 			continue;
313 		}
314 
315 		pointer_send_frame(resource);
316 	}
317 }
318 
wlr_seat_pointer_start_grab(struct wlr_seat * wlr_seat,struct wlr_seat_pointer_grab * grab)319 void wlr_seat_pointer_start_grab(struct wlr_seat *wlr_seat,
320 		struct wlr_seat_pointer_grab *grab) {
321 	assert(wlr_seat);
322 	grab->seat = wlr_seat;
323 	wlr_seat->pointer_state.grab = grab;
324 
325 	wlr_signal_emit_safe(&wlr_seat->events.pointer_grab_begin, grab);
326 }
327 
wlr_seat_pointer_end_grab(struct wlr_seat * wlr_seat)328 void wlr_seat_pointer_end_grab(struct wlr_seat *wlr_seat) {
329 	struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab;
330 	if (grab != wlr_seat->pointer_state.default_grab) {
331 		wlr_seat->pointer_state.grab = wlr_seat->pointer_state.default_grab;
332 		wlr_signal_emit_safe(&wlr_seat->events.pointer_grab_end, grab);
333 		if (grab->interface->cancel) {
334 			grab->interface->cancel(grab);
335 		}
336 	}
337 }
338 
wlr_seat_pointer_notify_enter(struct wlr_seat * wlr_seat,struct wlr_surface * surface,double sx,double sy)339 void wlr_seat_pointer_notify_enter(struct wlr_seat *wlr_seat,
340 		struct wlr_surface *surface, double sx, double sy) {
341 	// NULL surfaces are prohibited in the grab-compatible API. Use
342 	// wlr_seat_pointer_notify_clear_focus() instead.
343 	assert(surface);
344 	struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab;
345 	grab->interface->enter(grab, surface, sx, sy);
346 }
347 
wlr_seat_pointer_notify_clear_focus(struct wlr_seat * wlr_seat)348 void wlr_seat_pointer_notify_clear_focus(struct wlr_seat *wlr_seat) {
349 	struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab;
350 	grab->interface->clear_focus(grab);
351 }
352 
wlr_seat_pointer_notify_motion(struct wlr_seat * wlr_seat,uint32_t time,double sx,double sy)353 void wlr_seat_pointer_notify_motion(struct wlr_seat *wlr_seat, uint32_t time,
354 		double sx, double sy) {
355 	clock_gettime(CLOCK_MONOTONIC, &wlr_seat->last_event);
356 	struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab;
357 	grab->interface->motion(grab, time, sx, sy);
358 }
359 
wlr_seat_pointer_notify_button(struct wlr_seat * wlr_seat,uint32_t time,uint32_t button,enum wlr_button_state state)360 uint32_t wlr_seat_pointer_notify_button(struct wlr_seat *wlr_seat,
361 		uint32_t time, uint32_t button, enum wlr_button_state state) {
362 	clock_gettime(CLOCK_MONOTONIC, &wlr_seat->last_event);
363 
364 	struct wlr_seat_pointer_state* pointer_state = &wlr_seat->pointer_state;
365 
366 	if (state == WLR_BUTTON_PRESSED) {
367 		if (pointer_state->button_count == 0) {
368 			pointer_state->grab_button = button;
369 			pointer_state->grab_time = time;
370 		}
371 		set_add(pointer_state->buttons, &pointer_state->button_count,
372 			WLR_POINTER_BUTTONS_CAP, button);
373 	} else {
374 		set_remove(pointer_state->buttons, &pointer_state->button_count,
375 			WLR_POINTER_BUTTONS_CAP, button);
376 	}
377 
378 
379 	struct wlr_seat_pointer_grab *grab = pointer_state->grab;
380 	uint32_t serial = grab->interface->button(grab, time, button, state);
381 
382 	wlr_log(WLR_DEBUG, "button_count=%zu grab_serial=%"PRIu32" serial=%"PRIu32"",
383 		pointer_state->button_count,
384 		pointer_state->grab_serial, serial);
385 
386 	if (serial && pointer_state->button_count == 1 &&
387 			state == WLR_BUTTON_PRESSED) {
388 		pointer_state->grab_serial = serial;
389 	}
390 
391 	return serial;
392 }
393 
wlr_seat_pointer_notify_axis(struct wlr_seat * wlr_seat,uint32_t time,enum wlr_axis_orientation orientation,double value,int32_t value_discrete,enum wlr_axis_source source)394 void wlr_seat_pointer_notify_axis(struct wlr_seat *wlr_seat, uint32_t time,
395 		enum wlr_axis_orientation orientation, double value,
396 		int32_t value_discrete, enum wlr_axis_source source) {
397 	clock_gettime(CLOCK_MONOTONIC, &wlr_seat->last_event);
398 	struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab;
399 	grab->interface->axis(grab, time, orientation, value, value_discrete,
400 		source);
401 }
402 
wlr_seat_pointer_notify_frame(struct wlr_seat * wlr_seat)403 void wlr_seat_pointer_notify_frame(struct wlr_seat *wlr_seat) {
404 	clock_gettime(CLOCK_MONOTONIC, &wlr_seat->last_event);
405 	struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab;
406 	if (grab->interface->frame) {
407 		grab->interface->frame(grab);
408 	}
409 }
410 
wlr_seat_pointer_has_grab(struct wlr_seat * seat)411 bool wlr_seat_pointer_has_grab(struct wlr_seat *seat) {
412 	return seat->pointer_state.grab->interface != &default_pointer_grab_impl;
413 }
414 
415 
seat_client_create_pointer(struct wlr_seat_client * seat_client,uint32_t version,uint32_t id)416 void seat_client_create_pointer(struct wlr_seat_client *seat_client,
417 		uint32_t version, uint32_t id) {
418 	struct wl_resource *resource = wl_resource_create(seat_client->client,
419 		&wl_pointer_interface, version, id);
420 	if (resource == NULL) {
421 		wl_client_post_no_memory(seat_client->client);
422 		return;
423 	}
424 	wl_resource_set_implementation(resource, &pointer_impl, seat_client,
425 		&pointer_handle_resource_destroy);
426 	wl_list_insert(&seat_client->pointers, wl_resource_get_link(resource));
427 
428 	if ((seat_client->seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) {
429 		wl_resource_set_user_data(resource, NULL);
430 		return;
431 	}
432 
433 	struct wlr_seat_client *focused_client =
434 		seat_client->seat->pointer_state.focused_client;
435 	struct wlr_surface *focused_surface =
436 		seat_client->seat->pointer_state.focused_surface;
437 
438 	// Send an enter event if there is a focused client/surface stored
439 	if (focused_client != NULL && focused_surface != NULL) {
440 		double sx = seat_client->seat->pointer_state.sx;
441 		double sy = seat_client->seat->pointer_state.sy;
442 
443 		uint32_t serial = wlr_seat_client_next_serial(focused_client);
444 		struct wl_resource *resource;
445 		wl_resource_for_each(resource, &focused_client->pointers) {
446 			if (wl_resource_get_id(resource) == id) {
447 				if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
448 					continue;
449 				}
450 
451 				wl_pointer_send_enter(resource, serial, focused_surface->resource,
452 					wl_fixed_from_double(sx), wl_fixed_from_double(sy));
453 				pointer_send_frame(resource);
454 			}
455 		}
456 	}
457 }
458 
seat_client_destroy_pointer(struct wl_resource * resource)459 void seat_client_destroy_pointer(struct wl_resource *resource) {
460 	struct wlr_seat_client *seat_client =
461 		wlr_seat_client_from_pointer_resource(resource);
462 	if (seat_client == NULL) {
463 		return;
464 	}
465 	wl_resource_set_user_data(resource, NULL);
466 }
467 
wlr_seat_validate_pointer_grab_serial(struct wlr_seat * seat,struct wlr_surface * origin,uint32_t serial)468 bool wlr_seat_validate_pointer_grab_serial(struct wlr_seat *seat,
469 		struct wlr_surface *origin, uint32_t serial) {
470 	if (seat->pointer_state.button_count != 1 ||
471 			seat->pointer_state.grab_serial != serial) {
472 		wlr_log(WLR_DEBUG, "Pointer grab serial validation failed: "
473 			"button_count=%zu grab_serial=%"PRIu32" (got %"PRIu32")",
474 			seat->pointer_state.button_count,
475 			seat->pointer_state.grab_serial, serial);
476 		return false;
477 	}
478 
479 	if (origin != NULL && seat->pointer_state.focused_surface != origin) {
480 		wlr_log(WLR_DEBUG, "Pointer grab serial validation failed: "
481 			"invalid origin surface");
482 		return false;
483 	}
484 
485 	return true;
486 }
487