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