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