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 ®istry_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