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