1 /*
2  * Copyright © 2008-2011 Kristian Høgsberg
3  * Copyright © 2014 Jason Ekstrand
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 <stdlib.h>
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <sys/socket.h>
35 #include <sys/mman.h>
36 #include <signal.h>
37 #include <linux/input.h>
38 #include <errno.h>
39 #include <ctype.h>
40 
41 #include <wayland-client.h>
42 
43 #include <libweston/libweston.h>
44 #include "backend.h"
45 #include "libweston-internal.h"
46 #include "weston.h"
47 #include "shared/helpers.h"
48 #include "shared/os-compatibility.h"
49 #include "shared/timespec-util.h"
50 #include "fullscreen-shell-unstable-v1-client-protocol.h"
51 
52 struct shared_output {
53 	struct weston_output *output;
54 	struct wl_listener output_destroyed;
55 	struct wl_list seat_list;
56 
57 	struct {
58 		struct wl_display *display;
59 		struct wl_registry *registry;
60 		struct wl_compositor *compositor;
61 		struct wl_shm *shm;
62 		uint32_t shm_formats;
63 		struct zwp_fullscreen_shell_v1 *fshell;
64 		struct wl_output *output;
65 		struct wl_surface *surface;
66 		struct wl_callback *frame_cb;
67 		struct zwp_fullscreen_shell_mode_feedback_v1 *mode_feedback;
68 	} parent;
69 
70 	struct wl_event_source *event_source;
71 	struct wl_listener frame_listener;
72 
73 	struct {
74 		int32_t width, height;
75 
76 		struct wl_list buffers;
77 		struct wl_list free_buffers;
78 	} shm;
79 
80 	int cache_dirty;
81 	pixman_image_t *cache_image;
82 	uint32_t *tmp_data;
83 	size_t tmp_data_size;
84 };
85 
86 struct ss_seat {
87 	struct weston_seat base;
88 	struct shared_output *output;
89 	struct wl_list link;
90 	uint32_t id;
91 
92 	struct {
93 		struct wl_seat *seat;
94 		struct wl_pointer *pointer;
95 		struct wl_keyboard *keyboard;
96 	} parent;
97 
98 	enum weston_key_state_update keyboard_state_update;
99 	uint32_t key_serial;
100 };
101 
102 struct ss_shm_buffer {
103 	struct shared_output *output;
104 	struct wl_list link;
105 	struct wl_list free_link;
106 
107 	struct wl_buffer *buffer;
108 	void *data;
109 	size_t size;
110 	pixman_region32_t damage;
111 
112 	pixman_image_t *pm_image;
113 };
114 
115 struct screen_share {
116 	struct weston_compositor *compositor;
117 	char *command;
118 };
119 
120 static void
ss_seat_handle_pointer_enter(void * data,struct wl_pointer * pointer,uint32_t serial,struct wl_surface * surface,wl_fixed_t x,wl_fixed_t y)121 ss_seat_handle_pointer_enter(void *data, struct wl_pointer *pointer,
122 			     uint32_t serial, struct wl_surface *surface,
123 			     wl_fixed_t x, wl_fixed_t y)
124 {
125 	struct ss_seat *seat = data;
126 
127 	/* No transformation of input position is required here because we are
128 	 * always receiving the input in the same coordinates as the output. */
129 
130 	notify_pointer_focus(&seat->base, NULL, 0, 0);
131 }
132 
133 static void
ss_seat_handle_pointer_leave(void * data,struct wl_pointer * pointer,uint32_t serial,struct wl_surface * surface)134 ss_seat_handle_pointer_leave(void *data, struct wl_pointer *pointer,
135 			     uint32_t serial, struct wl_surface *surface)
136 {
137 	struct ss_seat *seat = data;
138 
139 	notify_pointer_focus(&seat->base, NULL, 0, 0);
140 }
141 
142 static void
ss_seat_handle_motion(void * data,struct wl_pointer * pointer,uint32_t time,wl_fixed_t x,wl_fixed_t y)143 ss_seat_handle_motion(void *data, struct wl_pointer *pointer,
144 		      uint32_t time, wl_fixed_t x, wl_fixed_t y)
145 {
146 	struct ss_seat *seat = data;
147 	struct timespec ts;
148 
149 	timespec_from_msec(&ts, time);
150 
151 	/* No transformation of input position is required here because we are
152 	 * always receiving the input in the same coordinates as the output. */
153 
154 	notify_motion_absolute(&seat->base, &ts,
155 			       wl_fixed_to_double(x), wl_fixed_to_double(y));
156 	notify_pointer_frame(&seat->base);
157 }
158 
159 static void
ss_seat_handle_button(void * data,struct wl_pointer * pointer,uint32_t serial,uint32_t time,uint32_t button,uint32_t state)160 ss_seat_handle_button(void *data, struct wl_pointer *pointer,
161 		      uint32_t serial, uint32_t time, uint32_t button,
162 		      uint32_t state)
163 {
164 	struct ss_seat *seat = data;
165 	struct timespec ts;
166 
167 	timespec_from_msec(&ts, time);
168 
169 	notify_button(&seat->base, &ts, button, state);
170 	notify_pointer_frame(&seat->base);
171 }
172 
173 static void
ss_seat_handle_axis(void * data,struct wl_pointer * pointer,uint32_t time,uint32_t axis,wl_fixed_t value)174 ss_seat_handle_axis(void *data, struct wl_pointer *pointer,
175 		    uint32_t time, uint32_t axis, wl_fixed_t value)
176 {
177 	struct ss_seat *seat = data;
178 	struct weston_pointer_axis_event weston_event;
179 	struct timespec ts;
180 
181 	weston_event.axis = axis;
182 	weston_event.value = wl_fixed_to_double(value);
183 	weston_event.has_discrete = false;
184 
185 	timespec_from_msec(&ts, time);
186 
187 	notify_axis(&seat->base, &ts, &weston_event);
188 	notify_pointer_frame(&seat->base);
189 }
190 
191 static const struct wl_pointer_listener ss_seat_pointer_listener = {
192 	ss_seat_handle_pointer_enter,
193 	ss_seat_handle_pointer_leave,
194 	ss_seat_handle_motion,
195 	ss_seat_handle_button,
196 	ss_seat_handle_axis,
197 };
198 
199 static void
ss_seat_handle_keymap(void * data,struct wl_keyboard * wl_keyboard,uint32_t format,int fd,uint32_t size)200 ss_seat_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
201 		      uint32_t format, int fd, uint32_t size)
202 {
203 	struct ss_seat *seat = data;
204 	struct xkb_keymap *keymap;
205 	char *map_str;
206 
207 	if (!data)
208 		goto error_no_seat;
209 
210 	if (format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
211 		map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
212 		if (map_str == MAP_FAILED) {
213 			weston_log("mmap failed: %s\n", strerror(errno));
214 			goto error;
215 		}
216 
217 		keymap = xkb_keymap_new_from_string(seat->base.compositor->xkb_context,
218 						    map_str,
219 						    XKB_KEYMAP_FORMAT_TEXT_V1,
220 						    0);
221 		munmap(map_str, size);
222 
223 		if (!keymap) {
224 			weston_log("failed to compile keymap\n");
225 			goto error;
226 		}
227 
228 		seat->keyboard_state_update = STATE_UPDATE_NONE;
229 	} else if (format == WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP) {
230 		weston_log("No keymap provided; falling back to default\n");
231 		keymap = NULL;
232 		seat->keyboard_state_update = STATE_UPDATE_AUTOMATIC;
233 	} else {
234 		weston_log("Invalid keymap\n");
235 		goto error;
236 	}
237 
238 	close(fd);
239 
240 	if (seat->base.keyboard_device_count)
241 		weston_seat_update_keymap(&seat->base, keymap);
242 	else
243 		weston_seat_init_keyboard(&seat->base, keymap);
244 
245 	xkb_keymap_unref(keymap);
246 
247 	return;
248 
249 error:
250 	wl_keyboard_release(seat->parent.keyboard);
251 error_no_seat:
252 	close(fd);
253 }
254 
255 static void
ss_seat_handle_keyboard_enter(void * data,struct wl_keyboard * keyboard,uint32_t serial,struct wl_surface * surface,struct wl_array * keys)256 ss_seat_handle_keyboard_enter(void *data, struct wl_keyboard *keyboard,
257 			      uint32_t serial, struct wl_surface *surface,
258 			      struct wl_array *keys)
259 {
260 	struct ss_seat *seat = data;
261 
262 	/* XXX: If we get a modifier event immediately before the focus,
263 	 *      we should try to keep the same serial. */
264 	notify_keyboard_focus_in(&seat->base, keys,
265 				 STATE_UPDATE_AUTOMATIC);
266 }
267 
268 static void
ss_seat_handle_keyboard_leave(void * data,struct wl_keyboard * keyboard,uint32_t serial,struct wl_surface * surface)269 ss_seat_handle_keyboard_leave(void *data, struct wl_keyboard *keyboard,
270 			      uint32_t serial, struct wl_surface *surface)
271 {
272 	struct ss_seat *seat = data;
273 
274 	notify_keyboard_focus_out(&seat->base);
275 }
276 
277 static void
ss_seat_handle_key(void * data,struct wl_keyboard * keyboard,uint32_t serial,uint32_t time,uint32_t key,uint32_t state)278 ss_seat_handle_key(void *data, struct wl_keyboard *keyboard,
279 		   uint32_t serial, uint32_t time,
280 		   uint32_t key, uint32_t state)
281 {
282 	struct ss_seat *seat = data;
283 	struct timespec ts;
284 
285 	timespec_from_msec(&ts, time);
286 	seat->key_serial = serial;
287 	notify_key(&seat->base, &ts, key,
288 		   state ? WL_KEYBOARD_KEY_STATE_PRESSED :
289 			   WL_KEYBOARD_KEY_STATE_RELEASED,
290 		   seat->keyboard_state_update);
291 }
292 
293 static void
ss_seat_handle_modifiers(void * data,struct wl_keyboard * wl_keyboard,uint32_t serial_in,uint32_t mods_depressed,uint32_t mods_latched,uint32_t mods_locked,uint32_t group)294 ss_seat_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
295 			 uint32_t serial_in, uint32_t mods_depressed,
296 			 uint32_t mods_latched, uint32_t mods_locked,
297 			 uint32_t group)
298 {
299 	struct ss_seat *seat = data;
300 	struct weston_compositor *c = seat->base.compositor;
301 	struct weston_keyboard *keyboard;
302 	uint32_t serial_out;
303 
304 	/* If we get a key event followed by a modifier event with the
305 	 * same serial number, then we try to preserve those semantics by
306 	 * reusing the same serial number on the way out too. */
307 	if (serial_in == seat->key_serial)
308 		serial_out = wl_display_get_serial(c->wl_display);
309 	else
310 		serial_out = wl_display_next_serial(c->wl_display);
311 
312 	keyboard = weston_seat_get_keyboard(&seat->base);
313 	xkb_state_update_mask(keyboard->xkb_state.state,
314 			      mods_depressed, mods_latched,
315 			      mods_locked, 0, 0, group);
316 	notify_modifiers(&seat->base, serial_out);
317 }
318 
319 static const struct wl_keyboard_listener ss_seat_keyboard_listener = {
320 	ss_seat_handle_keymap,
321 	ss_seat_handle_keyboard_enter,
322 	ss_seat_handle_keyboard_leave,
323 	ss_seat_handle_key,
324 	ss_seat_handle_modifiers,
325 };
326 
327 static void
ss_seat_handle_capabilities(void * data,struct wl_seat * seat,enum wl_seat_capability caps)328 ss_seat_handle_capabilities(void *data, struct wl_seat *seat,
329 			    enum wl_seat_capability caps)
330 {
331 	struct ss_seat *ss_seat = data;
332 
333 	if ((caps & WL_SEAT_CAPABILITY_POINTER) && !ss_seat->parent.pointer) {
334 		ss_seat->parent.pointer = wl_seat_get_pointer(seat);
335 		wl_pointer_set_user_data(ss_seat->parent.pointer, ss_seat);
336 		wl_pointer_add_listener(ss_seat->parent.pointer,
337 					&ss_seat_pointer_listener, ss_seat);
338 		weston_seat_init_pointer(&ss_seat->base);
339 	} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && ss_seat->parent.pointer) {
340 		wl_pointer_destroy(ss_seat->parent.pointer);
341 		ss_seat->parent.pointer = NULL;
342 	}
343 
344 	if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !ss_seat->parent.keyboard) {
345 		ss_seat->parent.keyboard = wl_seat_get_keyboard(seat);
346 		wl_keyboard_set_user_data(ss_seat->parent.keyboard, ss_seat);
347 		wl_keyboard_add_listener(ss_seat->parent.keyboard,
348 					 &ss_seat_keyboard_listener, ss_seat);
349 	} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && ss_seat->parent.keyboard) {
350 		wl_keyboard_destroy(ss_seat->parent.keyboard);
351 		ss_seat->parent.keyboard = NULL;
352 	}
353 }
354 
355 static const struct wl_seat_listener ss_seat_listener = {
356 	ss_seat_handle_capabilities,
357 };
358 
359 static struct ss_seat *
ss_seat_create(struct shared_output * so,uint32_t id)360 ss_seat_create(struct shared_output *so, uint32_t id)
361 {
362 	struct ss_seat *seat;
363 
364 	seat = zalloc(sizeof *seat);
365 	if (seat == NULL)
366 		return NULL;
367 
368 	weston_seat_init(&seat->base, so->output->compositor, "default");
369 	seat->output = so;
370 	seat->id = id;
371 	seat->parent.seat = wl_registry_bind(so->parent.registry, id,
372 					     &wl_seat_interface, 1);
373 	wl_list_insert(so->seat_list.prev, &seat->link);
374 
375 	wl_seat_add_listener(seat->parent.seat, &ss_seat_listener, seat);
376 	wl_seat_set_user_data(seat->parent.seat, seat);
377 
378 	return seat;
379 }
380 
381 static void
ss_seat_destroy(struct ss_seat * seat)382 ss_seat_destroy(struct ss_seat *seat)
383 {
384 	if (seat->parent.pointer)
385 		wl_pointer_release(seat->parent.pointer);
386 	if (seat->parent.keyboard)
387 		wl_keyboard_release(seat->parent.keyboard);
388 	wl_seat_destroy(seat->parent.seat);
389 
390 	wl_list_remove(&seat->link);
391 
392 	weston_seat_release(&seat->base);
393 
394 	free(seat);
395 }
396 
397 static void
ss_shm_buffer_destroy(struct ss_shm_buffer * buffer)398 ss_shm_buffer_destroy(struct ss_shm_buffer *buffer)
399 {
400 	pixman_image_unref(buffer->pm_image);
401 
402 	wl_buffer_destroy(buffer->buffer);
403 	munmap(buffer->data, buffer->size);
404 
405 	pixman_region32_fini(&buffer->damage);
406 
407 	wl_list_remove(&buffer->link);
408 	wl_list_remove(&buffer->free_link);
409 	free(buffer);
410 }
411 
412 static void
buffer_release(void * data,struct wl_buffer * buffer)413 buffer_release(void *data, struct wl_buffer *buffer)
414 {
415 	struct ss_shm_buffer *sb = data;
416 
417 	if (sb->output) {
418 		wl_list_insert(&sb->output->shm.free_buffers, &sb->free_link);
419 	} else {
420 		ss_shm_buffer_destroy(sb);
421 	}
422 }
423 
424 static const struct wl_buffer_listener buffer_listener = {
425 	buffer_release
426 };
427 
428 static struct ss_shm_buffer *
shared_output_get_shm_buffer(struct shared_output * so)429 shared_output_get_shm_buffer(struct shared_output *so)
430 {
431 	struct ss_shm_buffer *sb, *bnext;
432 	struct wl_shm_pool *pool;
433 	int width, height, stride;
434 	int fd;
435 	unsigned char *data;
436 
437 	width = so->output->width;
438 	height = so->output->height;
439 	stride = width * 4;
440 
441 	/* If the size of the output changed, we free the old buffers and
442 	 * make new ones. */
443 	if (so->shm.width != width ||
444 	    so->shm.height != height) {
445 
446 		/* Destroy free buffers */
447 		wl_list_for_each_safe(sb, bnext, &so->shm.free_buffers, free_link)
448 			ss_shm_buffer_destroy(sb);
449 
450 		/* Orphan in-use buffers so they get destroyed */
451 		wl_list_for_each(sb, &so->shm.buffers, link)
452 			sb->output = NULL;
453 
454 		so->shm.width = width;
455 		so->shm.height = height;
456 	}
457 
458 	if (!wl_list_empty(&so->shm.free_buffers)) {
459 		sb = container_of(so->shm.free_buffers.next,
460 				  struct ss_shm_buffer, free_link);
461 		wl_list_remove(&sb->free_link);
462 		wl_list_init(&sb->free_link);
463 
464 		return sb;
465 	}
466 
467 	fd = os_create_anonymous_file(height * stride);
468 	if (fd < 0) {
469 		weston_log("os_create_anonymous_file: %s\n", strerror(errno));
470 		return NULL;
471 	}
472 
473 	data = mmap(NULL, height * stride, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
474 	if (data == MAP_FAILED) {
475 		weston_log("mmap: %s\n", strerror(errno));
476 		goto out_close;
477 	}
478 
479 	sb = zalloc(sizeof *sb);
480 	if (!sb)
481 		goto out_unmap;
482 
483 	sb->output = so;
484 	wl_list_init(&sb->free_link);
485 	wl_list_insert(&so->shm.buffers, &sb->link);
486 
487 	pixman_region32_init_rect(&sb->damage, 0, 0, width, height);
488 
489 	sb->data = data;
490 	sb->size = height * stride;
491 
492 	pool = wl_shm_create_pool(so->parent.shm, fd, sb->size);
493 
494 	sb->buffer = wl_shm_pool_create_buffer(pool, 0,
495 					       width, height, stride,
496 					       WL_SHM_FORMAT_ARGB8888);
497 	wl_buffer_add_listener(sb->buffer, &buffer_listener, sb);
498 	wl_shm_pool_destroy(pool);
499 	close(fd);
500 	fd = -1;
501 
502 	memset(data, 0, sb->size);
503 
504 	sb->pm_image =
505 		pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height,
506 					 (uint32_t *)data, stride);
507 	if (!sb->pm_image)
508 		goto out_pixman_error;
509 
510 	return sb;
511 
512 out_pixman_error:
513 	pixman_region32_fini(&sb->damage);
514 out_unmap:
515 	munmap(data, height * stride);
516 out_close:
517 	if (fd != -1)
518 		close(fd);
519 	return NULL;
520 }
521 
522 static void
output_compute_transform(struct weston_output * output,pixman_transform_t * transform)523 output_compute_transform(struct weston_output *output,
524 			 pixman_transform_t *transform)
525 {
526 	pixman_fixed_t fw, fh;
527 
528 	pixman_transform_init_identity(transform);
529 
530 	fw = pixman_int_to_fixed(output->width);
531 	fh = pixman_int_to_fixed(output->height);
532 
533 	switch (output->transform) {
534 	case WL_OUTPUT_TRANSFORM_FLIPPED:
535 	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
536 	case WL_OUTPUT_TRANSFORM_FLIPPED_180:
537 	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
538 		pixman_transform_scale(transform, NULL,
539 				       pixman_int_to_fixed (-1),
540 				       pixman_int_to_fixed (1));
541 		pixman_transform_translate(transform, NULL, fw, 0);
542 	}
543 
544 	switch (output->transform) {
545 	default:
546 	case WL_OUTPUT_TRANSFORM_NORMAL:
547 	case WL_OUTPUT_TRANSFORM_FLIPPED:
548 		break;
549 	case WL_OUTPUT_TRANSFORM_90:
550 	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
551 		pixman_transform_rotate(transform, NULL, 0, pixman_fixed_1);
552 		pixman_transform_translate(transform, NULL, fh, 0);
553 		break;
554 	case WL_OUTPUT_TRANSFORM_180:
555 	case WL_OUTPUT_TRANSFORM_FLIPPED_180:
556 		pixman_transform_rotate(transform, NULL, -pixman_fixed_1, 0);
557 		pixman_transform_translate(transform, NULL, fw, fh);
558 		break;
559 	case WL_OUTPUT_TRANSFORM_270:
560 	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
561 		pixman_transform_rotate(transform, NULL, 0, -pixman_fixed_1);
562 		pixman_transform_translate(transform, NULL, 0, fw);
563 		break;
564 	}
565 
566 	pixman_transform_scale(transform, NULL,
567 			       pixman_fixed_1 * output->current_scale,
568 			       pixman_fixed_1 * output->current_scale);
569 }
570 
571 static void
572 shared_output_destroy(struct shared_output *so);
573 
574 static int
shared_output_ensure_tmp_data(struct shared_output * so,pixman_region32_t * region)575 shared_output_ensure_tmp_data(struct shared_output *so,
576 			      pixman_region32_t *region)
577 {
578 	pixman_box32_t *ext;
579 	size_t size;
580 
581 	if (!pixman_region32_not_empty(region))
582 		return 0;
583 
584 	ext = pixman_region32_extents(region);
585 
586 	/* Damage is in output coordinates.
587 	 *
588 	 * We are multiplying by 4 because the temporary data needs to be able
589 	 * to store an 32 bit-per-pixel buffer.
590 	 */
591 	size = 4 * (ext->x2 - ext->x1) * (ext->y2 - ext->y1)
592 		 * so->output->current_scale * so->output->current_scale;
593 
594 	if (so->tmp_data != NULL && size <= so->tmp_data_size)
595 		return 0;
596 
597 	free(so->tmp_data);
598 	so->tmp_data = malloc(size);
599 	if (so->tmp_data == NULL) {
600 		so->tmp_data_size = 0;
601 		errno = ENOMEM;
602 		return -1;
603 	}
604 
605 	so->tmp_data_size = size;
606 
607 	return 0;
608 }
609 
610 static void
611 shared_output_update(struct shared_output *so);
612 
613 static void
shared_output_frame_callback(void * data,struct wl_callback * cb,uint32_t time)614 shared_output_frame_callback(void *data, struct wl_callback *cb, uint32_t time)
615 {
616 	struct shared_output *so = data;
617 
618 	if (cb != so->parent.frame_cb)
619 		return;
620 
621 	wl_callback_destroy(cb);
622 	so->parent.frame_cb = NULL;
623 
624 	shared_output_update(so);
625 }
626 
627 static const struct wl_callback_listener shared_output_frame_listener = {
628 	shared_output_frame_callback
629 };
630 
631 static void
shared_output_update(struct shared_output * so)632 shared_output_update(struct shared_output *so)
633 {
634 	struct ss_shm_buffer *sb;
635 	pixman_box32_t *r;
636 	int i, nrects;
637 	pixman_transform_t transform;
638 
639 	/* Only update if we need to */
640 	if (!so->cache_dirty || so->parent.frame_cb)
641 		return;
642 
643 	sb = shared_output_get_shm_buffer(so);
644 	if (sb == NULL) {
645 		shared_output_destroy(so);
646 		return;
647 	}
648 
649 	output_compute_transform(so->output, &transform);
650 	pixman_image_set_transform(so->cache_image, &transform);
651 
652 	pixman_image_set_clip_region32(sb->pm_image, &sb->damage);
653 
654 	if (so->output->current_scale == 1) {
655 		pixman_image_set_filter(so->cache_image,
656 					PIXMAN_FILTER_NEAREST, NULL, 0);
657 	} else {
658 		pixman_image_set_filter(so->cache_image,
659 					PIXMAN_FILTER_BILINEAR, NULL, 0);
660 	}
661 
662 	pixman_image_composite32(PIXMAN_OP_SRC,
663 				 so->cache_image, /* src */
664 				 NULL, /* mask */
665 				 sb->pm_image, /* dest */
666 				 0, 0, /* src_x, src_y */
667 				 0, 0, /* mask_x, mask_y */
668 				 0, 0, /* dest_x, dest_y */
669 				 so->output->width, /* width */
670 				 so->output->height /* height */);
671 
672 	pixman_image_set_transform(sb->pm_image, NULL);
673 	pixman_image_set_clip_region32(sb->pm_image, NULL);
674 
675 	r = pixman_region32_rectangles(&sb->damage, &nrects);
676 	for (i = 0; i < nrects; ++i)
677 		wl_surface_damage(so->parent.surface, r[i].x1, r[i].y1,
678 				  r[i].x2 - r[i].x1, r[i].y2 - r[i].y1);
679 
680 	wl_surface_attach(so->parent.surface, sb->buffer, 0, 0);
681 
682 	so->parent.frame_cb = wl_surface_frame(so->parent.surface);
683 	wl_callback_add_listener(so->parent.frame_cb,
684 				 &shared_output_frame_listener, so);
685 
686 	wl_surface_commit(so->parent.surface);
687 	wl_callback_destroy(wl_display_sync(so->parent.display));
688 	wl_display_flush(so->parent.display);
689 
690 	/* Clear the buffer damage */
691 	pixman_region32_fini(&sb->damage);
692 	pixman_region32_init(&sb->damage);
693 }
694 
695 static void
shm_handle_format(void * data,struct wl_shm * wl_shm,uint32_t format)696 shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
697 {
698 	struct shared_output *so = data;
699 
700 	so->parent.shm_formats |= (1 << format);
701 }
702 
703 struct wl_shm_listener shm_listener = {
704 	shm_handle_format
705 };
706 
707 static void
registry_handle_global(void * data,struct wl_registry * registry,uint32_t id,const char * interface,uint32_t version)708 registry_handle_global(void *data, struct wl_registry *registry,
709 		       uint32_t id, const char *interface, uint32_t version)
710 {
711 	struct shared_output *so = data;
712 
713 	if (strcmp(interface, "wl_compositor") == 0) {
714 		so->parent.compositor =
715 			wl_registry_bind(registry,
716 					 id, &wl_compositor_interface, 1);
717 	} else if (strcmp(interface, "wl_output") == 0 && !so->parent.output) {
718 		so->parent.output =
719 			wl_registry_bind(registry,
720 					 id, &wl_output_interface, 1);
721 	} else if (strcmp(interface, "wl_seat") == 0) {
722 		ss_seat_create(so, id);
723 	} else if (strcmp(interface, "wl_shm") == 0) {
724 		so->parent.shm =
725 			wl_registry_bind(registry,
726 					 id, &wl_shm_interface, 1);
727 		wl_shm_add_listener(so->parent.shm, &shm_listener, so);
728 	} else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
729 		so->parent.fshell =
730 			wl_registry_bind(registry,
731 					 id,
732 					 &zwp_fullscreen_shell_v1_interface,
733 					 1);
734 	}
735 }
736 
737 static void
registry_handle_global_remove(void * data,struct wl_registry * registry,uint32_t name)738 registry_handle_global_remove(void *data, struct wl_registry *registry,
739 			      uint32_t name)
740 {
741 	struct shared_output *so = data;
742 	struct ss_seat *seat, *next;
743 
744 	wl_list_for_each_safe(seat, next, &so->seat_list, link)
745 		if (seat->id == name)
746 			ss_seat_destroy(seat);
747 }
748 
749 static const struct wl_registry_listener registry_listener = {
750 	registry_handle_global,
751 	registry_handle_global_remove
752 };
753 
754 static int
shared_output_handle_event(int fd,uint32_t mask,void * data)755 shared_output_handle_event(int fd, uint32_t mask, void *data)
756 {
757 	struct shared_output *so = data;
758 	int count = 0;
759 
760 	if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
761 		shared_output_destroy(so);
762 		return 0;
763 	}
764 
765 	if (mask & WL_EVENT_READABLE)
766 		count = wl_display_dispatch(so->parent.display);
767 	if (mask & WL_EVENT_WRITABLE)
768 		wl_display_flush(so->parent.display);
769 
770 	if (mask == 0) {
771 		count = wl_display_dispatch_pending(so->parent.display);
772 		wl_display_flush(so->parent.display);
773 	}
774 
775 	return count;
776 }
777 
778 static void
output_destroyed(struct wl_listener * l,void * data)779 output_destroyed(struct wl_listener *l, void *data)
780 {
781 	struct shared_output *so;
782 
783 	so = container_of(l, struct shared_output, output_destroyed);
784 
785 	shared_output_destroy(so);
786 }
787 
788 static void
mode_feedback_ok(void * data,struct zwp_fullscreen_shell_mode_feedback_v1 * fb)789 mode_feedback_ok(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
790 {
791 	struct shared_output *so = data;
792 
793 	zwp_fullscreen_shell_mode_feedback_v1_destroy(so->parent.mode_feedback);
794 }
795 
796 static void
mode_feedback_failed(void * data,struct zwp_fullscreen_shell_mode_feedback_v1 * fb)797 mode_feedback_failed(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
798 {
799 	struct shared_output *so = data;
800 
801 	zwp_fullscreen_shell_mode_feedback_v1_destroy(so->parent.mode_feedback);
802 
803 	weston_log("Screen share failed: present_surface_for_mode failed\n");
804 	shared_output_destroy(so);
805 }
806 
807 struct zwp_fullscreen_shell_mode_feedback_v1_listener mode_feedback_listener = {
808 	mode_feedback_ok,
809 	mode_feedback_failed,
810 	mode_feedback_ok,
811 };
812 
813 static void
shared_output_repainted(struct wl_listener * listener,void * data)814 shared_output_repainted(struct wl_listener *listener, void *data)
815 {
816 	struct shared_output *so =
817 		container_of(listener, struct shared_output, frame_listener);
818 	pixman_region32_t damage;
819 	struct ss_shm_buffer *sb;
820 	int32_t x, y, width, height, stride;
821 	int i, nrects, do_yflip;
822 	pixman_box32_t *r;
823 	uint32_t *cache_data;
824 
825 	/* Damage in output coordinates */
826 	pixman_region32_init(&damage);
827 	pixman_region32_intersect(&damage, &so->output->region,
828 				  &so->output->previous_damage);
829 	pixman_region32_translate(&damage, -so->output->x, -so->output->y);
830 
831 	/* Apply damage to all buffers */
832 	wl_list_for_each(sb, &so->shm.buffers, link)
833 		pixman_region32_union(&sb->damage, &sb->damage, &damage);
834 
835 	/* Transform to buffer coordinates */
836 	weston_transformed_region(so->output->width, so->output->height,
837 				  so->output->transform,
838 				  so->output->current_scale,
839 				  &damage, &damage);
840 
841 	width = so->output->current_mode->width;
842 	height = so->output->current_mode->height;
843 	stride = width;
844 
845 	if (!so->cache_image ||
846 	    pixman_image_get_width(so->cache_image) != width ||
847 	    pixman_image_get_height(so->cache_image) != height) {
848 		if (so->cache_image)
849 			pixman_image_unref(so->cache_image);
850 
851 		so->cache_image =
852 			pixman_image_create_bits(PIXMAN_a8r8g8b8,
853 						 width, height, NULL,
854 						 stride);
855 		if (!so->cache_image) {
856 			shared_output_destroy(so);
857 			return;
858 		}
859 
860 		pixman_region32_fini(&damage);
861 		pixman_region32_init_rect(&damage, 0, 0, width, height);
862 	}
863 
864 	if (shared_output_ensure_tmp_data(so, &damage) < 0) {
865 		shared_output_destroy(so);
866 		return;
867 	}
868 
869 	do_yflip = !!(so->output->compositor->capabilities & WESTON_CAP_CAPTURE_YFLIP);
870 
871 	cache_data = pixman_image_get_data(so->cache_image);
872 	r = pixman_region32_rectangles(&damage, &nrects);
873 	for (i = 0; i < nrects; ++i) {
874 		x = r[i].x1;
875 		y = r[i].y1;
876 		width = r[i].x2 - r[i].x1;
877 		height = r[i].y2 - r[i].y1;
878 
879 		if (do_yflip) {
880 			so->output->compositor->renderer->read_pixels(
881 				so->output, PIXMAN_a8r8g8b8, so->tmp_data,
882 				x, so->output->current_mode->height - r[i].y2,
883 				width, height);
884 
885 			pixman_blt(so->tmp_data, cache_data, -width, stride,
886 				   32, 32, 0, 1 - height, x, y, width, height);
887 		} else {
888 			so->output->compositor->renderer->read_pixels(
889 				so->output, PIXMAN_a8r8g8b8, so->tmp_data,
890 				x, y, width, height);
891 
892 			pixman_blt(so->tmp_data, cache_data, width, stride,
893 				   32, 32, 0, 0, x, y, width, height);
894 		}
895 	}
896 
897 	pixman_region32_fini(&damage);
898 
899 	so->cache_dirty = 1;
900 
901 	shared_output_update(so);
902 }
903 
904 static struct shared_output *
shared_output_create(struct weston_output * output,int parent_fd)905 shared_output_create(struct weston_output *output, int parent_fd)
906 {
907 	struct shared_output *so;
908 	struct wl_event_loop *loop;
909 	struct ss_seat *seat, *tmp;
910 	int epoll_fd;
911 
912 	so = zalloc(sizeof *so);
913 	if (so == NULL)
914 		goto err_close;
915 
916 	wl_list_init(&so->seat_list);
917 
918 	so->parent.display = wl_display_connect_to_fd(parent_fd);
919 	if (!so->parent.display)
920 		goto err_alloc;
921 
922 	so->parent.registry = wl_display_get_registry(so->parent.display);
923 	if (!so->parent.registry)
924 		goto err_display;
925 	wl_registry_add_listener(so->parent.registry,
926 				 &registry_listener, so);
927 	wl_display_roundtrip(so->parent.display);
928 	if (so->parent.shm == NULL) {
929 		weston_log("Screen share failed: No wl_shm found\n");
930 		goto err_display;
931 	}
932 	if (so->parent.fshell == NULL) {
933 		weston_log("Screen share failed: "
934 			   "Parent does not support wl_fullscreen_shell\n");
935 		goto err_display;
936 	}
937 	if (so->parent.compositor == NULL) {
938 		weston_log("Screen share failed: No wl_compositor found\n");
939 		goto err_display;
940 	}
941 
942 	/* Get SHM formats */
943 	wl_display_roundtrip(so->parent.display);
944 	if (!(so->parent.shm_formats & (1 << WL_SHM_FORMAT_XRGB8888))) {
945 		weston_log("Screen share failed: "
946 			   "WL_SHM_FORMAT_XRGB8888 not available\n");
947 		goto err_display;
948 	}
949 
950 	so->parent.surface =
951 		wl_compositor_create_surface(so->parent.compositor);
952 	if (!so->parent.surface) {
953 		weston_log("Screen share failed: %s\n", strerror(errno));
954 		goto err_display;
955 	}
956 
957 	so->parent.mode_feedback =
958 		zwp_fullscreen_shell_v1_present_surface_for_mode(so->parent.fshell,
959 								 so->parent.surface,
960 								 so->parent.output,
961 								 output->current_mode->refresh);
962 	if (!so->parent.mode_feedback) {
963 		weston_log("Screen share failed: %s\n", strerror(errno));
964 		goto err_display;
965 	}
966 	zwp_fullscreen_shell_mode_feedback_v1_add_listener(so->parent.mode_feedback,
967 							   &mode_feedback_listener,
968 							   so);
969 
970 	loop = wl_display_get_event_loop(output->compositor->wl_display);
971 
972 	epoll_fd = wl_display_get_fd(so->parent.display);
973 	so->event_source =
974 		wl_event_loop_add_fd(loop, epoll_fd, WL_EVENT_READABLE,
975 				     shared_output_handle_event, so);
976 	if (!so->event_source) {
977 		weston_log("Screen share failed: %s\n", strerror(errno));
978 		goto err_display;
979 	}
980 
981 	/* Ok, everything's created.  We should be good to go */
982 	wl_list_init(&so->shm.buffers);
983 	wl_list_init(&so->shm.free_buffers);
984 
985 	so->output = output;
986 	so->output_destroyed.notify = output_destroyed;
987 	wl_signal_add(&so->output->destroy_signal, &so->output_destroyed);
988 
989 	so->frame_listener.notify = shared_output_repainted;
990 	wl_signal_add(&output->frame_signal, &so->frame_listener);
991 	output->disable_planes++;
992 	weston_output_damage(output);
993 
994 	return so;
995 
996 err_display:
997 	wl_list_for_each_safe(seat, tmp, &so->seat_list, link)
998 		ss_seat_destroy(seat);
999 	wl_display_disconnect(so->parent.display);
1000 err_alloc:
1001 	free(so);
1002 err_close:
1003 	close(parent_fd);
1004 	return NULL;
1005 }
1006 
1007 static void
shared_output_destroy(struct shared_output * so)1008 shared_output_destroy(struct shared_output *so)
1009 {
1010 	struct ss_shm_buffer *buffer, *bnext;
1011 
1012 	so->output->disable_planes--;
1013 
1014 	wl_list_for_each_safe(buffer, bnext, &so->shm.buffers, link)
1015 		ss_shm_buffer_destroy(buffer);
1016 	wl_list_for_each_safe(buffer, bnext, &so->shm.free_buffers, free_link)
1017 		ss_shm_buffer_destroy(buffer);
1018 
1019 	wl_display_disconnect(so->parent.display);
1020 	wl_event_source_remove(so->event_source);
1021 
1022 	wl_list_remove(&so->output_destroyed.link);
1023 	wl_list_remove(&so->frame_listener.link);
1024 
1025 	pixman_image_unref(so->cache_image);
1026 	free(so->tmp_data);
1027 
1028 	free(so);
1029 }
1030 
1031 static struct shared_output *
weston_output_share(struct weston_output * output,const char * command)1032 weston_output_share(struct weston_output *output, const char* command)
1033 {
1034 	int sv[2];
1035 	char str[32];
1036 	pid_t pid;
1037 	sigset_t allsigs;
1038 	char *const argv[] = {
1039 	  "/bin/sh",
1040 	  "-c",
1041 	  (char*)command,
1042 	  NULL
1043 	};
1044 
1045 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
1046 		weston_log("weston_output_share: socketpair failed: %s\n",
1047 			   strerror(errno));
1048 		return NULL;
1049 	}
1050 
1051 	pid = fork();
1052 
1053 	if (pid == -1) {
1054 		close(sv[0]);
1055 		close(sv[1]);
1056 		weston_log("weston_output_share: fork failed: %s\n",
1057 			   strerror(errno));
1058 		return NULL;
1059 	}
1060 
1061 	if (pid == 0) {
1062 		/* do not give our signal mask to the new process */
1063 		sigfillset(&allsigs);
1064 		sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
1065 
1066 		/* Launch clients as the user. Do not launch clients with
1067 		 * wrong euid. */
1068 		if (seteuid(getuid()) == -1) {
1069 			weston_log("weston_output_share: setuid failed: %s\n",
1070 				   strerror(errno));
1071 			abort();
1072 		}
1073 
1074 		sv[1] = dup(sv[1]);
1075 		if (sv[1] == -1) {
1076 			weston_log("weston_output_share: dup failed: %s\n",
1077 				   strerror(errno));
1078 			abort();
1079 		}
1080 
1081 		snprintf(str, sizeof str, "%d", sv[1]);
1082 		setenv("WAYLAND_SERVER_SOCKET", str, 1);
1083 
1084 		execv(argv[0], argv);
1085 		weston_log("weston_output_share: exec failed: %s\n",
1086 			   strerror(errno));
1087 		abort();
1088 	} else {
1089 		close(sv[1]);
1090 		return shared_output_create(output, sv[0]);
1091 	}
1092 
1093 	return NULL;
1094 }
1095 
1096 static struct weston_output *
weston_output_find(struct weston_compositor * c,int32_t x,int32_t y)1097 weston_output_find(struct weston_compositor *c, int32_t x, int32_t y)
1098 {
1099 	struct weston_output *output;
1100 
1101 	wl_list_for_each(output, &c->output_list, link) {
1102 		if (x >= output->x && y >= output->y &&
1103 		    x < output->x + output->width &&
1104 		    y < output->y + output->height)
1105 			return output;
1106 	}
1107 
1108 	return NULL;
1109 }
1110 
1111 static void
share_output_binding(struct weston_keyboard * keyboard,const struct timespec * time,uint32_t key,void * data)1112 share_output_binding(struct weston_keyboard *keyboard,
1113 		     const struct timespec *time, uint32_t key, void *data)
1114 {
1115 	struct weston_output *output;
1116 	struct weston_pointer *pointer;
1117 	struct screen_share *ss = data;
1118 
1119 	pointer = weston_seat_get_pointer(keyboard->seat);
1120 	if (!pointer) {
1121 		weston_log("Cannot pick output: Seat does not have pointer\n");
1122 		return;
1123 	}
1124 
1125 	output = weston_output_find(pointer->seat->compositor,
1126 				    wl_fixed_to_int(pointer->x),
1127 				    wl_fixed_to_int(pointer->y));
1128 	if (!output) {
1129 		weston_log("Cannot pick output: Pointer not on any output\n");
1130 		return;
1131 	}
1132 
1133 	weston_output_share(output, ss->command);
1134 }
1135 
1136 WL_EXPORT int
wet_module_init(struct weston_compositor * compositor,int * argc,char * argv[])1137 wet_module_init(struct weston_compositor *compositor,
1138 		int *argc, char *argv[])
1139 {
1140 	struct screen_share *ss;
1141 	struct weston_config *config = wet_get_config(compositor);
1142 	struct weston_config_section *section;
1143 
1144 	ss = zalloc(sizeof *ss);
1145 	if (ss == NULL)
1146 		return -1;
1147 	ss->compositor = compositor;
1148 
1149 	section = weston_config_get_section(config, "screen-share", NULL, NULL);
1150 
1151 	weston_config_section_get_string(section, "command", &ss->command, "");
1152 
1153 	weston_compositor_add_key_binding(compositor, KEY_S,
1154 				          MODIFIER_CTRL | MODIFIER_ALT,
1155 					  share_output_binding, ss);
1156 	return 0;
1157 }
1158