1 /*
2  * Copyright 2017-2018 Collabora, Ltd.
3  * Copyright 2017-2018 General Electric Company
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26 
27 #include "config.h"
28 
29 #include <string.h>
30 #include <wayland-server.h>
31 
32 #include "shared/helpers.h"
33 #include "shared/string-helpers.h"
34 #include <libweston/zalloc.h>
35 #include "shared/timespec-util.h"
36 #include <libweston/libweston.h>
37 #include "libweston-internal.h"
38 
39 #include "weston-touch-calibration-server-protocol.h"
40 
41 struct weston_touch_calibrator {
42 	struct wl_resource *resource;
43 
44 	struct weston_compositor *compositor;
45 
46 	struct weston_surface *surface;
47 	struct wl_listener surface_destroy_listener;
48 	struct wl_listener surface_commit_listener;
49 
50 	struct weston_touch_device *device;
51 	struct wl_listener device_destroy_listener;
52 
53 	struct weston_output *output;
54 	struct wl_listener output_destroy_listener;
55 
56 	struct weston_view *view;
57 
58 	/** The calibration procedure has been cancelled. */
59 	bool calibration_cancelled;
60 
61 	/** The current touch sequence has been cancelled. */
62 	bool touch_cancelled;
63 };
64 
65 static struct weston_touch_calibrator *
calibrator_from_device(struct weston_touch_device * device)66 calibrator_from_device(struct weston_touch_device *device)
67 {
68 	return device->aggregate->seat->compositor->touch_calibrator;
69 }
70 
71 static uint32_t
wire_uint_from_double(double c)72 wire_uint_from_double(double c)
73 {
74 	assert(c >= 0.0);
75 	assert(c <= 1.0);
76 
77 	return round(c * 0xffffffff);
78 }
79 
80 static bool
normalized_is_valid(const struct weston_point2d_device_normalized * p)81 normalized_is_valid(const struct weston_point2d_device_normalized *p)
82 {
83 	return p->x >= 0.0 && p->x <= 1.0 &&
84 	       p->y >= 0.0 && p->y <= 1.0;
85 }
86 
87 WL_EXPORT void
notify_touch_calibrator(struct weston_touch_device * device,const struct timespec * time,int32_t slot,const struct weston_point2d_device_normalized * norm,int touch_type)88 notify_touch_calibrator(struct weston_touch_device *device,
89 			const struct timespec *time, int32_t slot,
90 			const struct weston_point2d_device_normalized *norm,
91 			int touch_type)
92 {
93 	struct weston_touch_calibrator *calibrator;
94 	struct wl_resource *res;
95 	uint32_t msecs;
96 	uint32_t x = 0;
97 	uint32_t y = 0;
98 
99 	calibrator = calibrator_from_device(device);
100 	if (!calibrator)
101 		return;
102 
103 	res = calibrator->resource;
104 
105 	/* Ignore any touch events coming from another device */
106 	if (device != calibrator->device) {
107 		if (touch_type == WL_TOUCH_DOWN)
108 			weston_touch_calibrator_send_invalid_touch(res);
109 		return;
110 	}
111 
112 	/* Ignore all events if we have sent 'cancel' event until all
113 	 * touches (on the seat) are up.
114 	 */
115 	if (calibrator->touch_cancelled) {
116 		if (calibrator->device->aggregate->num_tp == 0) {
117 			assert(touch_type == WL_TOUCH_UP);
118 			calibrator->touch_cancelled = false;
119 		}
120 		return;
121 	}
122 
123 	msecs = timespec_to_msec(time);
124 	if (touch_type != WL_TOUCH_UP) {
125 		if (normalized_is_valid(norm)) {
126 			x = wire_uint_from_double(norm->x);
127 			y = wire_uint_from_double(norm->y);
128 		} else {
129 			/* Coordinates are out of bounds */
130 			if (touch_type == WL_TOUCH_MOTION) {
131 				weston_touch_calibrator_send_cancel(res);
132 				calibrator->touch_cancelled = true;
133 			}
134 			weston_touch_calibrator_send_invalid_touch(res);
135 			return;
136 		}
137 	}
138 
139 	switch (touch_type) {
140 	case WL_TOUCH_UP:
141 		weston_touch_calibrator_send_up(res, msecs, slot);
142 		break;
143 	case WL_TOUCH_DOWN:
144 		weston_touch_calibrator_send_down(res, msecs, slot, x, y);
145 		break;
146 	case WL_TOUCH_MOTION:
147 		weston_touch_calibrator_send_motion(res, msecs, slot, x, y);
148 		break;
149 	default:
150 		return;
151 	}
152 }
153 
154 WL_EXPORT void
notify_touch_calibrator_frame(struct weston_touch_device * device)155 notify_touch_calibrator_frame(struct weston_touch_device *device)
156 {
157 	struct weston_touch_calibrator *calibrator;
158 
159 	calibrator = calibrator_from_device(device);
160 	if (!calibrator)
161 		return;
162 
163 	weston_touch_calibrator_send_frame(calibrator->resource);
164 }
165 
166 WL_EXPORT void
notify_touch_calibrator_cancel(struct weston_touch_device * device)167 notify_touch_calibrator_cancel(struct weston_touch_device *device)
168 {
169 	struct weston_touch_calibrator *calibrator;
170 
171 	calibrator = calibrator_from_device(device);
172 	if (!calibrator)
173 		return;
174 
175 	weston_touch_calibrator_send_cancel(calibrator->resource);
176 }
177 
178 static void
map_calibrator(struct weston_touch_calibrator * calibrator)179 map_calibrator(struct weston_touch_calibrator *calibrator)
180 {
181 	struct weston_compositor *c = calibrator->compositor;
182 	struct weston_touch_device *device = calibrator->device;
183 	static const struct weston_touch_device_matrix identity = {
184 		.m = { 1, 0, 0, 0, 1, 0}
185 	};
186 
187 	assert(!calibrator->view);
188 	assert(calibrator->output);
189 	assert(calibrator->surface);
190 	assert(calibrator->surface->resource);
191 
192 	calibrator->view = weston_view_create(calibrator->surface);
193 	if (!calibrator->view) {
194 		wl_resource_post_no_memory(calibrator->surface->resource);
195 		return;
196 	}
197 
198 	weston_layer_entry_insert(&c->calibrator_layer.view_list,
199 				  &calibrator->view->layer_link);
200 
201 	weston_view_set_position(calibrator->view,
202 				 calibrator->output->x,
203 				 calibrator->output->y);
204 	calibrator->view->output = calibrator->surface->output;
205 	calibrator->view->is_mapped = true;
206 
207 	calibrator->surface->output = calibrator->output;
208 	calibrator->surface->is_mapped = true;
209 
210 	weston_output_schedule_repaint(calibrator->output);
211 
212 	device->ops->get_calibration(device, &device->saved_calibration);
213 	device->ops->set_calibration(device, &identity);
214 }
215 
216 static void
unmap_calibrator(struct weston_touch_calibrator * calibrator)217 unmap_calibrator(struct weston_touch_calibrator *calibrator)
218 {
219 	struct weston_touch_device *device = calibrator->device;
220 
221 	wl_list_remove(&calibrator->surface_commit_listener.link);
222 	wl_list_init(&calibrator->surface_commit_listener.link);
223 
224 	if (!calibrator->view)
225 		return;
226 
227 	weston_view_destroy(calibrator->view);
228 	calibrator->view = NULL;
229 	weston_surface_unmap(calibrator->surface);
230 
231 	/* Reload saved calibration */
232 	if (device)
233 		device->ops->set_calibration(device,
234 					     &device->saved_calibration);
235 }
236 
237 void
touch_calibrator_mode_changed(struct weston_compositor * compositor)238 touch_calibrator_mode_changed(struct weston_compositor *compositor)
239 {
240 	struct weston_touch_calibrator *calibrator;
241 
242 	calibrator = compositor->touch_calibrator;
243 	if (!calibrator)
244 		return;
245 
246 	if (calibrator->calibration_cancelled)
247 		return;
248 
249 	if (compositor->touch_mode == WESTON_TOUCH_MODE_CALIB)
250 		map_calibrator(calibrator);
251 }
252 
253 static void
touch_calibrator_surface_committed(struct wl_listener * listener,void * data)254 touch_calibrator_surface_committed(struct wl_listener *listener, void *data)
255 {
256 	struct weston_touch_calibrator *calibrator =
257 		container_of(listener, struct weston_touch_calibrator,
258 			     surface_commit_listener);
259 	struct weston_surface *surface = calibrator->surface;
260 
261 	wl_list_remove(&calibrator->surface_commit_listener.link);
262 	wl_list_init(&calibrator->surface_commit_listener.link);
263 
264 	if (surface->width != calibrator->output->width ||
265 	    surface->height != calibrator->output->height) {
266 		wl_resource_post_error(calibrator->resource,
267 				       WESTON_TOUCH_CALIBRATOR_ERROR_BAD_SIZE,
268 				       "calibrator surface size does not match");
269 		return;
270 	}
271 
272 	weston_compositor_set_touch_mode_calib(calibrator->compositor);
273 	/* results in call to touch_calibrator_mode_changed() */
274 }
275 
276 static void
touch_calibrator_convert(struct wl_client * client,struct wl_resource * resource,int32_t x,int32_t y,uint32_t coordinate_id)277 touch_calibrator_convert(struct wl_client *client,
278 			 struct wl_resource *resource,
279 			 int32_t x,
280 			 int32_t y,
281 			 uint32_t coordinate_id)
282 {
283 	struct weston_touch_calibrator *calibrator;
284 	struct wl_resource *coordinate_resource;
285 	struct weston_output *output;
286 	struct weston_surface *surface;
287 	uint32_t version;
288 	struct weston_vector p = { { 0.0, 0.0, 0.0, 1.0 } };
289 	struct weston_point2d_device_normalized norm;
290 
291 	version = wl_resource_get_version(resource);
292 	calibrator = wl_resource_get_user_data(resource);
293 	surface = calibrator->surface;
294 	output = calibrator->output;
295 
296 	coordinate_resource =
297 		wl_resource_create(client, &weston_touch_coordinate_interface,
298 				   version, coordinate_id);
299 	if (!coordinate_resource) {
300 		wl_client_post_no_memory(client);
301 		return;
302 	}
303 
304 	if (calibrator->calibration_cancelled) {
305 		weston_touch_coordinate_send_result(coordinate_resource, 0, 0);
306 		wl_resource_destroy(coordinate_resource);
307 		return;
308 	}
309 
310 	if (!surface || !surface->is_mapped) {
311 		wl_resource_post_error(resource,
312 				       WESTON_TOUCH_CALIBRATOR_ERROR_NOT_MAPPED,
313 				       "calibrator surface is not mapped");
314 		return;
315 	}
316 	assert(calibrator->view);
317 	assert(output);
318 
319 	if (x < 0 || y < 0 || x >= surface->width || y >= surface->height) {
320 		wl_resource_post_error(resource,
321 				       WESTON_TOUCH_CALIBRATOR_ERROR_BAD_COORDINATES,
322 				       "convert(%d, %d) input is out of bounds",
323 				       x, y);
324 		return;
325 	}
326 
327 	/* Convert from surface-local coordinates into global, from global
328 	 * into output-raw, do perspective division and normalize.
329 	 */
330 	weston_view_to_global_float(calibrator->view, x, y, &p.f[0], &p.f[1]);
331 	weston_matrix_transform(&output->matrix, &p);
332 	norm.x = p.f[0] / (p.f[3] * output->current_mode->width);
333 	norm.y = p.f[1] / (p.f[3] * output->current_mode->height);
334 
335 	if (!normalized_is_valid(&norm)) {
336 		wl_resource_post_error(resource,
337 				       WESTON_TOUCH_CALIBRATOR_ERROR_BAD_COORDINATES,
338 				       "convert(%d, %d) output is out of bounds",
339 				       x, y);
340 		return;
341 	}
342 
343 	weston_touch_coordinate_send_result(coordinate_resource,
344 					    wire_uint_from_double(norm.x),
345 					    wire_uint_from_double(norm.y));
346 	wl_resource_destroy(coordinate_resource);
347 }
348 
349 static void
destroy_touch_calibrator(struct wl_resource * resource)350 destroy_touch_calibrator(struct wl_resource *resource)
351 {
352 	struct weston_touch_calibrator *calibrator;
353 
354 	calibrator = wl_resource_get_user_data(resource);
355 
356 	calibrator->compositor->touch_calibrator = NULL;
357 
358 	weston_compositor_set_touch_mode_normal(calibrator->compositor);
359 
360 	if (calibrator->surface) {
361 		unmap_calibrator(calibrator);
362 		weston_surface_set_role(calibrator->surface, NULL,
363 					calibrator->surface->resource, 0);
364 		wl_list_remove(&calibrator->surface_destroy_listener.link);
365 		wl_list_remove(&calibrator->surface_commit_listener.link);
366 	}
367 
368 	if (calibrator->device)
369 		wl_list_remove(&calibrator->device_destroy_listener.link);
370 
371 	if (calibrator->output)
372 		wl_list_remove(&calibrator->output_destroy_listener.link);
373 
374 	free(calibrator);
375 }
376 
377 static void
touch_calibrator_destroy(struct wl_client * client,struct wl_resource * resource)378 touch_calibrator_destroy(struct wl_client *client,
379 			 struct wl_resource *resource)
380 {
381 	wl_resource_destroy(resource);
382 }
383 
384 static const struct weston_touch_calibrator_interface
385 touch_calibrator_implementation = {
386 	touch_calibrator_destroy,
387 	touch_calibrator_convert
388 };
389 
390 static void
touch_calibrator_cancel_calibration(struct weston_touch_calibrator * calibrator)391 touch_calibrator_cancel_calibration(struct weston_touch_calibrator *calibrator)
392 {
393 	weston_touch_calibrator_send_cancel_calibration(calibrator->resource);
394 	calibrator->calibration_cancelled = true;
395 
396 	if (calibrator->surface)
397 		unmap_calibrator(calibrator);
398 }
399 
400 static void
touch_calibrator_output_destroyed(struct wl_listener * listener,void * data)401 touch_calibrator_output_destroyed(struct wl_listener *listener, void *data)
402 {
403 	struct weston_touch_calibrator *calibrator =
404 		container_of(listener, struct weston_touch_calibrator,
405 			     output_destroy_listener);
406 
407 	assert(calibrator->output == data);
408 	calibrator->output = NULL;
409 
410 	touch_calibrator_cancel_calibration(calibrator);
411 }
412 
413 static void
touch_calibrator_device_destroyed(struct wl_listener * listener,void * data)414 touch_calibrator_device_destroyed(struct wl_listener *listener, void *data)
415 {
416 	struct weston_touch_calibrator *calibrator =
417 		container_of(listener, struct weston_touch_calibrator,
418 			     device_destroy_listener);
419 
420 	assert(calibrator->device == data);
421 	calibrator->device = NULL;
422 
423 	touch_calibrator_cancel_calibration(calibrator);
424 }
425 
426 static void
touch_calibrator_surface_destroyed(struct wl_listener * listener,void * data)427 touch_calibrator_surface_destroyed(struct wl_listener *listener, void *data)
428 {
429 	struct weston_touch_calibrator *calibrator =
430 		container_of(listener, struct weston_touch_calibrator,
431 			     surface_destroy_listener);
432 
433 	assert(calibrator->surface->resource == data);
434 
435 	unmap_calibrator(calibrator);
436 	calibrator->surface = NULL;
437 }
438 
439 static void
touch_calibration_destroy(struct wl_client * client,struct wl_resource * resource)440 touch_calibration_destroy(struct wl_client *client,
441 			  struct wl_resource *resource)
442 {
443 	wl_resource_destroy(resource);
444 }
445 
446 static struct weston_touch_device *
weston_compositor_find_touch_device_by_syspath(struct weston_compositor * compositor,const char * syspath)447 weston_compositor_find_touch_device_by_syspath(
448 	struct weston_compositor *compositor,
449 	const char *syspath)
450 {
451 	struct weston_seat *seat;
452 	struct weston_touch *touch;
453 	struct weston_touch_device *device;
454 
455 	if (!syspath)
456 		return NULL;
457 
458 	wl_list_for_each(seat, &compositor->seat_list, link) {
459 		touch = weston_seat_get_touch(seat);
460 		if (!touch)
461 			continue;
462 
463 		wl_list_for_each(device, &touch->device_list, link) {
464 			if (strcmp(device->syspath, syspath) == 0)
465 				return device;
466 		}
467 	}
468 
469 	return NULL;
470 }
471 
472 static void
touch_calibration_create_calibrator(struct wl_client * client,struct wl_resource * touch_calibration_resource,struct wl_resource * surface_resource,const char * syspath,uint32_t calibrator_id)473 touch_calibration_create_calibrator(
474 	struct wl_client *client,
475 	struct wl_resource *touch_calibration_resource,
476 	struct wl_resource *surface_resource,
477 	const char *syspath,
478 	uint32_t calibrator_id)
479 {
480 	struct weston_compositor *compositor;
481 	struct weston_touch_calibrator *calibrator;
482 	struct weston_touch_device *device;
483 	struct weston_output *output = NULL;
484 	struct weston_surface *surface;
485 	uint32_t version;
486 	int ret;
487 
488 	version = wl_resource_get_version(touch_calibration_resource);
489 	compositor = wl_resource_get_user_data(touch_calibration_resource);
490 
491 	if (compositor->touch_calibrator != NULL) {
492 		wl_resource_post_error(touch_calibration_resource,
493 				WESTON_TOUCH_CALIBRATION_ERROR_ALREADY_EXISTS,
494 				"a calibrator has already been created");
495 		return;
496 	}
497 
498 	calibrator = zalloc(sizeof *calibrator);
499 	if (!calibrator) {
500 		wl_client_post_no_memory(client);
501 		return;
502 	}
503 
504 	calibrator->compositor = compositor;
505 	calibrator->resource = wl_resource_create(client,
506 					&weston_touch_calibrator_interface,
507 					version, calibrator_id);
508 	if (!calibrator->resource) {
509 		wl_client_post_no_memory(client);
510 		goto err_dealloc;
511 	}
512 
513 	surface = wl_resource_get_user_data(surface_resource);
514 	assert(surface);
515 	ret = weston_surface_set_role(surface, "weston_touch_calibrator",
516 		touch_calibration_resource,
517 		WESTON_TOUCH_CALIBRATION_ERROR_INVALID_SURFACE);
518 	if (ret < 0)
519 		goto err_destroy_resource;
520 
521 	calibrator->surface_destroy_listener.notify =
522 		touch_calibrator_surface_destroyed;
523 	wl_resource_add_destroy_listener(surface->resource,
524 					 &calibrator->surface_destroy_listener);
525 	calibrator->surface = surface;
526 
527 	calibrator->surface_commit_listener.notify =
528 		touch_calibrator_surface_committed;
529 	wl_signal_add(&surface->commit_signal,
530 		      &calibrator->surface_commit_listener);
531 
532 	device = weston_compositor_find_touch_device_by_syspath(compositor,
533 								syspath);
534 	if (device) {
535 		output = device->ops->get_output(device);
536 		if (weston_touch_device_can_calibrate(device) && output)
537 			calibrator->device = device;
538 	}
539 
540 	if (!calibrator->device) {
541 		wl_resource_post_error(touch_calibration_resource,
542 				WESTON_TOUCH_CALIBRATION_ERROR_INVALID_DEVICE,
543 				"the given touch device '%s' is not valid",
544 				syspath ?: "");
545 		goto err_unlink_surface;
546 	}
547 
548 	calibrator->device_destroy_listener.notify =
549 		touch_calibrator_device_destroyed;
550 	wl_signal_add(&calibrator->device->destroy_signal,
551 		      &calibrator->device_destroy_listener);
552 
553 	wl_resource_set_implementation(calibrator->resource,
554 				       &touch_calibrator_implementation,
555 				       calibrator, destroy_touch_calibrator);
556 
557 	assert(output);
558 	calibrator->output_destroy_listener.notify =
559 		touch_calibrator_output_destroyed;
560 	wl_signal_add(&output->destroy_signal,
561 		      &calibrator->output_destroy_listener);
562 	calibrator->output = output;
563 
564 	weston_touch_calibrator_send_configure(calibrator->resource,
565 					       output->width,
566 					       output->height);
567 
568 	compositor->touch_calibrator = calibrator;
569 
570 	return;
571 
572 err_unlink_surface:
573 	wl_list_remove(&calibrator->surface_commit_listener.link);
574 	wl_list_remove(&calibrator->surface_destroy_listener.link);
575 
576 err_destroy_resource:
577 	wl_resource_destroy(calibrator->resource);
578 
579 err_dealloc:
580 	free(calibrator);
581 }
582 
583 static void
touch_calibration_save(struct wl_client * client,struct wl_resource * touch_calibration_resource,const char * device_name,struct wl_array * matrix_data)584 touch_calibration_save(struct wl_client *client,
585 		       struct wl_resource *touch_calibration_resource,
586 		       const char *device_name,
587 		       struct wl_array *matrix_data)
588 {
589 	struct weston_touch_device *device;
590 	struct weston_compositor *compositor;
591 	struct weston_touch_device_matrix calibration;
592 	struct weston_touch_calibrator *calibrator;
593 	int i = 0;
594 	float *c;
595 
596 	compositor = wl_resource_get_user_data(touch_calibration_resource);
597 
598 	device = weston_compositor_find_touch_device_by_syspath(compositor,
599 								device_name);
600 	if (!device || !weston_touch_device_can_calibrate(device)) {
601 		wl_resource_post_error(touch_calibration_resource,
602 				WESTON_TOUCH_CALIBRATION_ERROR_INVALID_DEVICE,
603 				"the given device is not valid");
604 		return;
605 	}
606 
607 	wl_array_for_each(c, matrix_data) {
608 		calibration.m[i++] = *c;
609 	}
610 
611 	/* If calibration can't be saved, don't set it as current */
612 	if (compositor->touch_calibration_save &&
613 	    compositor->touch_calibration_save(compositor, device,
614 					       &calibration) < 0)
615 		return;
616 
617 	/* If calibrator is still mapped, the compositor will use
618 	 * saved_calibration when going back to normal touch handling.
619 	 * Continuing calibrating after save request is undefined. */
620 	calibrator = compositor->touch_calibrator;
621 	if (calibrator &&
622 	    calibrator->surface &&
623 	    weston_surface_is_mapped(calibrator->surface))
624 		device->saved_calibration = calibration;
625 	else
626 		device->ops->set_calibration(device, &calibration);
627 }
628 
629 static const struct weston_touch_calibration_interface
630 touch_calibration_implementation = {
631 	touch_calibration_destroy,
632 	touch_calibration_create_calibrator,
633 	touch_calibration_save
634 };
635 
636 static void
bind_touch_calibration(struct wl_client * client,void * data,uint32_t version,uint32_t id)637 bind_touch_calibration(struct wl_client *client,
638 		       void *data, uint32_t version, uint32_t id)
639 {
640 	struct weston_compositor *compositor = data;
641 	struct wl_resource *resource;
642 	struct weston_touch_device *device;
643 	struct weston_seat *seat;
644 	struct weston_touch *touch;
645 	const char *name;
646 
647 	resource = wl_resource_create(client,
648 				      &weston_touch_calibration_interface,
649 				      version, id);
650 	if (resource == NULL) {
651 		wl_client_post_no_memory(client);
652 		return;
653 	}
654 
655 	wl_resource_set_implementation(resource,
656 				       &touch_calibration_implementation,
657 				       compositor, NULL);
658 
659 	wl_list_for_each(seat, &compositor->seat_list, link) {
660 		touch = weston_seat_get_touch(seat);
661 		if (!touch)
662 			continue;
663 
664 		wl_list_for_each(device, &touch->device_list, link) {
665 			if (!weston_touch_device_can_calibrate(device))
666 				continue;
667 
668 			name = device->ops->get_calibration_head_name(device);
669 			if (!name)
670 				continue;
671 
672 			weston_touch_calibration_send_touch_device(resource,
673 							device->syspath, name);
674 		}
675 	}
676 }
677 
678 /** Advertise touch_calibration support
679  *
680  * \param compositor The compositor to init for.
681  * \param save The callback function for saving a new calibration, or NULL.
682  * \return Zero on success, -1 on failure or if already enabled.
683  *
684  * Calling this initializes the weston_touch_calibration protocol support,
685  * so that the interface will be advertised to clients. It is recommended
686  * to use some mechanism, e.g. wl_display_set_global_filter(), to restrict
687  * access to the interface.
688  *
689  * There is no way to disable this once enabled.
690  *
691  * If the save callback is NULL, a new calibration provided by a client will
692  * always be accepted. If the save callback is not NULL, it must return
693  * success for the new calibration to be accepted.
694  */
695 WL_EXPORT int
weston_compositor_enable_touch_calibrator(struct weston_compositor * compositor,weston_touch_calibration_save_func save)696 weston_compositor_enable_touch_calibrator(struct weston_compositor *compositor,
697 				weston_touch_calibration_save_func save)
698 {
699 	if (compositor->touch_calibration)
700 		return -1;
701 
702 	compositor->touch_calibration = wl_global_create(compositor->wl_display,
703 					&weston_touch_calibration_interface, 1,
704 					compositor, bind_touch_calibration);
705 	if (!compositor->touch_calibration)
706 		return -1;
707 
708 	compositor->touch_calibration_save = save;
709 	weston_layer_init(&compositor->calibrator_layer, compositor);
710 
711 	/* needs to be stacked above everything except lock screen and cursor,
712 	 * otherwise the position value is arbitrary */
713 	weston_layer_set_position(&compositor->calibrator_layer,
714 				  WESTON_LAYER_POSITION_TOP_UI + 120);
715 
716 	return 0;
717 }
718