1 /*
2 * Copyright © 2010-2011 Benjamin Franzke
3 * Copyright © 2013 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 <assert.h>
30 #include <stddef.h>
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <sys/mman.h>
39 #include <linux/input.h>
40
41 #include <drm_fourcc.h>
42 #include <wayland-client.h>
43 #include <wayland-cursor.h>
44
45 #ifdef ENABLE_EGL
46 #include <wayland-egl.h>
47 #endif
48
49 #include <libweston/libweston.h>
50 #include <libweston/backend-wayland.h>
51 #include "renderer-gl/gl-renderer.h"
52 #include "shared/weston-egl-ext.h"
53 #include "pixman-renderer.h"
54 #include "shared/helpers.h"
55 #include "shared/image-loader.h"
56 #include "shared/os-compatibility.h"
57 #include "shared/cairo-util.h"
58 #include "shared/timespec-util.h"
59 #include "fullscreen-shell-unstable-v1-client-protocol.h"
60 #include "xdg-shell-client-protocol.h"
61 #include "presentation-time-server-protocol.h"
62 #include "linux-dmabuf.h"
63 #include <libweston/windowed-output-api.h>
64
65 #define WINDOW_TITLE "Weston Compositor"
66
67 static const uint32_t wayland_formats[] = {
68 DRM_FORMAT_ARGB8888,
69 };
70
71 struct wayland_backend {
72 struct weston_backend base;
73 struct weston_compositor *compositor;
74
75 struct {
76 struct wl_display *wl_display;
77 struct wl_registry *registry;
78 struct wl_compositor *compositor;
79 struct wl_shell *shell;
80 struct xdg_wm_base *xdg_wm_base;
81 struct zwp_fullscreen_shell_v1 *fshell;
82 struct wl_shm *shm;
83
84 struct wl_list output_list;
85
86 struct wl_event_source *wl_source;
87 uint32_t event_mask;
88 } parent;
89
90 bool use_pixman;
91 bool sprawl_across_outputs;
92 bool fullscreen;
93
94 struct theme *theme;
95 cairo_device_t *frame_device;
96 struct wl_cursor_theme *cursor_theme;
97 struct wl_cursor *cursor;
98
99 struct wl_list input_list;
100 };
101
102 struct wayland_output {
103 struct weston_output base;
104
105 struct {
106 bool draw_initial_frame;
107 struct wl_surface *surface;
108
109 struct wl_output *output;
110 uint32_t global_id;
111
112 struct wl_shell_surface *shell_surface;
113 struct xdg_surface *xdg_surface;
114 struct xdg_toplevel *xdg_toplevel;
115 int configure_width, configure_height;
116 bool wait_for_configure;
117 } parent;
118
119 int keyboard_count;
120
121 char *title;
122 struct frame *frame;
123
124 struct {
125 struct wl_egl_window *egl_window;
126 struct {
127 cairo_surface_t *top;
128 cairo_surface_t *left;
129 cairo_surface_t *right;
130 cairo_surface_t *bottom;
131 } border;
132 } gl;
133
134 struct {
135 struct wl_list buffers;
136 struct wl_list free_buffers;
137 } shm;
138
139 struct weston_mode mode;
140
141 struct wl_callback *frame_cb;
142 };
143
144 struct wayland_parent_output {
145 struct wayland_backend *backend; /**< convenience */
146 struct wayland_head *head;
147 struct wl_list link;
148
149 struct wl_output *global;
150 uint32_t id;
151
152 struct {
153 char *make;
154 char *model;
155 int32_t width, height;
156 uint32_t subpixel;
157 } physical;
158
159 int32_t x, y;
160 uint32_t transform;
161 uint32_t scale;
162
163 struct wl_callback *sync_cb; /**< wl_output < 2 done replacement */
164
165 struct wl_list mode_list;
166 struct weston_mode *preferred_mode;
167 struct weston_mode *current_mode;
168 };
169
170 struct wayland_head {
171 struct weston_head base;
172 struct wayland_parent_output *parent_output;
173 };
174
175 struct wayland_shm_buffer {
176 struct wayland_output *output;
177 struct wl_list link;
178 struct wl_list free_link;
179
180 struct wl_buffer *buffer;
181 void *data;
182 size_t size;
183 int width;
184 int height;
185 pixman_region32_t damage; /**< in global coords */
186 int frame_damaged;
187
188 pixman_image_t *pm_image;
189 cairo_surface_t *c_surface;
190 };
191
192 struct wayland_input {
193 struct weston_seat base;
194 struct wayland_backend *backend;
195 struct wl_list link;
196
197 struct {
198 struct wl_seat *seat;
199 struct wl_pointer *pointer;
200 struct wl_keyboard *keyboard;
201 struct wl_touch *touch;
202
203 struct {
204 struct wl_surface *surface;
205 int32_t hx, hy;
206 } cursor;
207 } parent;
208
209 struct weston_touch_device *touch_device;
210
211 enum weston_key_state_update keyboard_state_update;
212 uint32_t key_serial;
213 uint32_t enter_serial;
214 uint32_t touch_points;
215 bool touch_active;
216 bool has_focus;
217 int seat_version;
218
219 struct wayland_output *output;
220 struct wayland_output *touch_focus;
221 struct wayland_output *keyboard_focus;
222
223 struct weston_pointer_axis_event vert, horiz;
224 };
225
226 struct gl_renderer_interface *gl_renderer;
227
228 static inline struct wayland_head *
to_wayland_head(struct weston_head * base)229 to_wayland_head(struct weston_head *base)
230 {
231 return container_of(base, struct wayland_head, base);
232 }
233
234 static inline struct wayland_output *
to_wayland_output(struct weston_output * base)235 to_wayland_output(struct weston_output *base)
236 {
237 return container_of(base, struct wayland_output, base);
238 }
239
240 static inline struct wayland_backend *
to_wayland_backend(struct weston_compositor * base)241 to_wayland_backend(struct weston_compositor *base)
242 {
243 return container_of(base->backend, struct wayland_backend, base);
244 }
245
246 static void
wayland_shm_buffer_destroy(struct wayland_shm_buffer * buffer)247 wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
248 {
249 cairo_surface_destroy(buffer->c_surface);
250 pixman_image_unref(buffer->pm_image);
251
252 wl_buffer_destroy(buffer->buffer);
253 munmap(buffer->data, buffer->size);
254
255 pixman_region32_fini(&buffer->damage);
256
257 wl_list_remove(&buffer->link);
258 wl_list_remove(&buffer->free_link);
259 free(buffer);
260 }
261
262 static void
buffer_release(void * data,struct wl_buffer * buffer)263 buffer_release(void *data, struct wl_buffer *buffer)
264 {
265 struct wayland_shm_buffer *sb = data;
266
267 if (sb->output) {
268 wl_list_insert(&sb->output->shm.free_buffers, &sb->free_link);
269 } else {
270 wayland_shm_buffer_destroy(sb);
271 }
272 }
273
274 static const struct wl_buffer_listener buffer_listener = {
275 buffer_release
276 };
277
278 static struct wayland_shm_buffer *
wayland_output_get_shm_buffer(struct wayland_output * output)279 wayland_output_get_shm_buffer(struct wayland_output *output)
280 {
281 struct wayland_backend *b =
282 to_wayland_backend(output->base.compositor);
283 struct wl_shm *shm = b->parent.shm;
284 struct wayland_shm_buffer *sb;
285
286 struct wl_shm_pool *pool;
287 int width, height, stride;
288 int32_t fx, fy;
289 int fd;
290 unsigned char *data;
291
292 if (!wl_list_empty(&output->shm.free_buffers)) {
293 sb = container_of(output->shm.free_buffers.next,
294 struct wayland_shm_buffer, free_link);
295 wl_list_remove(&sb->free_link);
296 wl_list_init(&sb->free_link);
297
298 return sb;
299 }
300
301 if (output->frame) {
302 width = frame_width(output->frame);
303 height = frame_height(output->frame);
304 } else {
305 width = output->base.current_mode->width;
306 height = output->base.current_mode->height;
307 }
308
309 stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
310
311 fd = os_create_anonymous_file(height * stride);
312 if (fd < 0) {
313 weston_log("could not create an anonymous file buffer: %s\n",
314 strerror(errno));
315 return NULL;
316 }
317
318 data = mmap(NULL, height * stride, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
319 if (data == MAP_FAILED) {
320 weston_log("could not mmap %d memory for data: %s\n", height * stride,
321 strerror(errno));
322 close(fd);
323 return NULL;
324 }
325
326 sb = zalloc(sizeof *sb);
327 if (sb == NULL) {
328 weston_log("could not zalloc %zu memory for sb: %s\n", sizeof *sb,
329 strerror(errno));
330 close(fd);
331 munmap(data, height * stride);
332 return NULL;
333 }
334
335 sb->output = output;
336 wl_list_init(&sb->free_link);
337 wl_list_insert(&output->shm.buffers, &sb->link);
338
339 pixman_region32_init(&sb->damage);
340 pixman_region32_copy(&sb->damage, &output->base.region);
341 sb->frame_damaged = 1;
342
343 sb->data = data;
344 sb->width = width;
345 sb->height = height;
346 sb->size = height * stride;
347
348 pool = wl_shm_create_pool(shm, fd, sb->size);
349
350 sb->buffer = wl_shm_pool_create_buffer(pool, 0,
351 width, height,
352 stride,
353 WL_SHM_FORMAT_ARGB8888);
354 wl_buffer_add_listener(sb->buffer, &buffer_listener, sb);
355 wl_shm_pool_destroy(pool);
356 close(fd);
357
358 memset(data, 0, sb->size);
359
360 sb->c_surface =
361 cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32,
362 width, height, stride);
363
364 fx = 0;
365 fy = 0;
366 if (output->frame)
367 frame_interior(output->frame, &fx, &fy, 0, 0);
368 sb->pm_image =
369 pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height,
370 (uint32_t *)(data + fy * stride) + fx,
371 stride);
372
373 return sb;
374 }
375
376 static void
frame_done(void * data,struct wl_callback * callback,uint32_t time)377 frame_done(void *data, struct wl_callback *callback, uint32_t time)
378 {
379 struct wayland_output *output = data;
380 struct timespec ts;
381
382 assert(callback == output->frame_cb);
383 wl_callback_destroy(callback);
384 output->frame_cb = NULL;
385
386 /* XXX: use the presentation extension for proper timings */
387
388 /*
389 * This is the fallback case, where Presentation extension is not
390 * available from the parent compositor. We do not know the base for
391 * 'time', so we cannot feed it to finish_frame(). Do the only thing
392 * we can, and pretend finish_frame time is when we process this
393 * event.
394 */
395 weston_compositor_read_presentation_clock(output->base.compositor, &ts);
396 weston_output_finish_frame(&output->base, &ts, 0);
397 }
398
399 static const struct wl_callback_listener frame_listener = {
400 frame_done
401 };
402
403 static void
draw_initial_frame(struct wayland_output * output)404 draw_initial_frame(struct wayland_output *output)
405 {
406 struct wayland_shm_buffer *sb;
407
408 sb = wayland_output_get_shm_buffer(output);
409
410 /* If we are rendering with GL, then orphan it so that it gets
411 * destroyed immediately */
412 if (output->gl.egl_window)
413 sb->output = NULL;
414
415 wl_surface_attach(output->parent.surface, sb->buffer, 0, 0);
416 wl_surface_damage(output->parent.surface, 0, 0,
417 sb->width, sb->height);
418 }
419
420 #ifdef ENABLE_EGL
421 static void
wayland_output_update_gl_border(struct wayland_output * output)422 wayland_output_update_gl_border(struct wayland_output *output)
423 {
424 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
425 cairo_t *cr;
426
427 if (!output->frame)
428 return;
429 if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
430 return;
431
432 fwidth = frame_width(output->frame);
433 fheight = frame_height(output->frame);
434 frame_interior(output->frame, &ix, &iy, &iwidth, &iheight);
435
436 if (!output->gl.border.top)
437 output->gl.border.top =
438 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
439 fwidth, iy);
440 cr = cairo_create(output->gl.border.top);
441 frame_repaint(output->frame, cr);
442 cairo_destroy(cr);
443 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_TOP,
444 fwidth, iy,
445 cairo_image_surface_get_stride(output->gl.border.top) / 4,
446 cairo_image_surface_get_data(output->gl.border.top));
447
448
449 if (!output->gl.border.left)
450 output->gl.border.left =
451 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
452 ix, 1);
453 cr = cairo_create(output->gl.border.left);
454 cairo_translate(cr, 0, -iy);
455 frame_repaint(output->frame, cr);
456 cairo_destroy(cr);
457 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_LEFT,
458 ix, 1,
459 cairo_image_surface_get_stride(output->gl.border.left) / 4,
460 cairo_image_surface_get_data(output->gl.border.left));
461
462
463 if (!output->gl.border.right)
464 output->gl.border.right =
465 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
466 fwidth - (ix + iwidth), 1);
467 cr = cairo_create(output->gl.border.right);
468 cairo_translate(cr, -(iwidth + ix), -iy);
469 frame_repaint(output->frame, cr);
470 cairo_destroy(cr);
471 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_RIGHT,
472 fwidth - (ix + iwidth), 1,
473 cairo_image_surface_get_stride(output->gl.border.right) / 4,
474 cairo_image_surface_get_data(output->gl.border.right));
475
476
477 if (!output->gl.border.bottom)
478 output->gl.border.bottom =
479 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
480 fwidth, fheight - (iy + iheight));
481 cr = cairo_create(output->gl.border.bottom);
482 cairo_translate(cr, 0, -(iy + iheight));
483 frame_repaint(output->frame, cr);
484 cairo_destroy(cr);
485 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_BOTTOM,
486 fwidth, fheight - (iy + iheight),
487 cairo_image_surface_get_stride(output->gl.border.bottom) / 4,
488 cairo_image_surface_get_data(output->gl.border.bottom));
489 }
490 #endif
491
492 static int
wayland_output_start_repaint_loop(struct weston_output * output_base)493 wayland_output_start_repaint_loop(struct weston_output *output_base)
494 {
495 struct wayland_output *output = to_wayland_output(output_base);
496 struct wayland_backend *wb =
497 to_wayland_backend(output->base.compositor);
498
499 /* If this is the initial frame, we need to attach a buffer so that
500 * the compositor can map the surface and include it in its render
501 * loop. If the surface doesn't end up in the render loop, the frame
502 * callback won't be invoked. The buffer is transparent and of the
503 * same size as the future real output buffer. */
504 if (output->parent.draw_initial_frame) {
505 output->parent.draw_initial_frame = false;
506
507 draw_initial_frame(output);
508 }
509
510 output->frame_cb = wl_surface_frame(output->parent.surface);
511 wl_callback_add_listener(output->frame_cb, &frame_listener, output);
512 wl_surface_commit(output->parent.surface);
513 wl_display_flush(wb->parent.wl_display);
514
515 return 0;
516 }
517
518 #ifdef ENABLE_EGL
519 static int
wayland_output_repaint_gl(struct weston_output * output_base,pixman_region32_t * damage,void * repaint_data)520 wayland_output_repaint_gl(struct weston_output *output_base,
521 pixman_region32_t *damage,
522 void *repaint_data)
523 {
524 struct wayland_output *output = to_wayland_output(output_base);
525 struct weston_compositor *ec = output->base.compositor;
526
527 output->frame_cb = wl_surface_frame(output->parent.surface);
528 wl_callback_add_listener(output->frame_cb, &frame_listener, output);
529
530 wayland_output_update_gl_border(output);
531
532 ec->renderer->repaint_output(&output->base, damage);
533
534 pixman_region32_subtract(&ec->primary_plane.damage,
535 &ec->primary_plane.damage, damage);
536 return 0;
537 }
538 #endif
539
540 static void
wayland_output_update_shm_border(struct wayland_shm_buffer * buffer)541 wayland_output_update_shm_border(struct wayland_shm_buffer *buffer)
542 {
543 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
544 cairo_t *cr;
545
546 if (!buffer->output->frame || !buffer->frame_damaged)
547 return;
548
549 cr = cairo_create(buffer->c_surface);
550
551 frame_interior(buffer->output->frame, &ix, &iy, &iwidth, &iheight);
552 fwidth = frame_width(buffer->output->frame);
553 fheight = frame_height(buffer->output->frame);
554
555 /* Set the clip so we don't unnecisaraly damage the surface */
556 cairo_move_to(cr, ix, iy);
557 cairo_rel_line_to(cr, iwidth, 0);
558 cairo_rel_line_to(cr, 0, iheight);
559 cairo_rel_line_to(cr, -iwidth, 0);
560 cairo_line_to(cr, ix, iy);
561 cairo_line_to(cr, 0, iy);
562 cairo_line_to(cr, 0, fheight);
563 cairo_line_to(cr, fwidth, fheight);
564 cairo_line_to(cr, fwidth, 0);
565 cairo_line_to(cr, 0, 0);
566 cairo_line_to(cr, 0, iy);
567 cairo_close_path(cr);
568 cairo_clip(cr);
569
570 /* Draw using a pattern so that the final result gets clipped */
571 cairo_push_group(cr);
572 frame_repaint(buffer->output->frame, cr);
573 cairo_pop_group_to_source(cr);
574 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
575 cairo_paint(cr);
576
577 cairo_destroy(cr);
578 }
579
580 static void
wayland_shm_buffer_attach(struct wayland_shm_buffer * sb)581 wayland_shm_buffer_attach(struct wayland_shm_buffer *sb)
582 {
583 pixman_region32_t damage;
584 pixman_box32_t *rects;
585 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
586 int i, n;
587
588 pixman_region32_init(&damage);
589 pixman_region32_copy(&damage, &sb->damage);
590 pixman_region32_translate(&damage, -sb->output->base.x,
591 -sb->output->base.y);
592
593 weston_transformed_region(sb->output->base.width,
594 sb->output->base.height,
595 sb->output->base.transform,
596 sb->output->base.current_scale,
597 &damage, &damage);
598
599 if (sb->output->frame) {
600 frame_interior(sb->output->frame, &ix, &iy, &iwidth, &iheight);
601 fwidth = frame_width(sb->output->frame);
602 fheight = frame_height(sb->output->frame);
603
604 pixman_region32_translate(&damage, ix, iy);
605
606 if (sb->frame_damaged) {
607 pixman_region32_union_rect(&damage, &damage,
608 0, 0, fwidth, iy);
609 pixman_region32_union_rect(&damage, &damage,
610 0, iy, ix, iheight);
611 pixman_region32_union_rect(&damage, &damage,
612 ix + iwidth, iy,
613 fwidth - (ix + iwidth), iheight);
614 pixman_region32_union_rect(&damage, &damage,
615 0, iy + iheight,
616 fwidth, fheight - (iy + iheight));
617 }
618 }
619
620 rects = pixman_region32_rectangles(&damage, &n);
621 wl_surface_attach(sb->output->parent.surface, sb->buffer, 0, 0);
622 for (i = 0; i < n; ++i)
623 wl_surface_damage(sb->output->parent.surface, rects[i].x1,
624 rects[i].y1, rects[i].x2 - rects[i].x1,
625 rects[i].y2 - rects[i].y1);
626
627 if (sb->output->frame)
628 pixman_region32_fini(&damage);
629 }
630
631 static int
wayland_output_repaint_pixman(struct weston_output * output_base,pixman_region32_t * damage,void * repaint_data)632 wayland_output_repaint_pixman(struct weston_output *output_base,
633 pixman_region32_t *damage,
634 void *repaint_data)
635 {
636 struct wayland_output *output = to_wayland_output(output_base);
637 struct wayland_backend *b =
638 to_wayland_backend(output->base.compositor);
639 struct wayland_shm_buffer *sb;
640
641 if (output->frame) {
642 if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
643 wl_list_for_each(sb, &output->shm.buffers, link)
644 sb->frame_damaged = 1;
645 }
646
647 wl_list_for_each(sb, &output->shm.buffers, link)
648 pixman_region32_union(&sb->damage, &sb->damage, damage);
649
650 sb = wayland_output_get_shm_buffer(output);
651
652 wayland_output_update_shm_border(sb);
653 pixman_renderer_output_set_buffer(output_base, sb->pm_image);
654 b->compositor->renderer->repaint_output(output_base, &sb->damage);
655
656 wayland_shm_buffer_attach(sb);
657
658 output->frame_cb = wl_surface_frame(output->parent.surface);
659 wl_callback_add_listener(output->frame_cb, &frame_listener, output);
660 wl_surface_commit(output->parent.surface);
661 wl_display_flush(b->parent.wl_display);
662
663 pixman_region32_fini(&sb->damage);
664 pixman_region32_init(&sb->damage);
665 sb->frame_damaged = 0;
666
667 pixman_region32_subtract(&b->compositor->primary_plane.damage,
668 &b->compositor->primary_plane.damage, damage);
669 return 0;
670 }
671
672 static void
wayland_backend_destroy_output_surface(struct wayland_output * output)673 wayland_backend_destroy_output_surface(struct wayland_output *output)
674 {
675 assert(output->parent.surface);
676
677 if (output->parent.xdg_toplevel) {
678 xdg_toplevel_destroy(output->parent.xdg_toplevel);
679 output->parent.xdg_toplevel = NULL;
680 }
681
682 if (output->parent.xdg_surface) {
683 xdg_surface_destroy(output->parent.xdg_surface);
684 output->parent.xdg_surface = NULL;
685 }
686
687 if (output->parent.shell_surface) {
688 wl_shell_surface_destroy(output->parent.shell_surface);
689 output->parent.shell_surface = NULL;
690 }
691
692 wl_surface_destroy(output->parent.surface);
693 output->parent.surface = NULL;
694 }
695
696 static void
wayland_output_destroy_shm_buffers(struct wayland_output * output)697 wayland_output_destroy_shm_buffers(struct wayland_output *output)
698 {
699 struct wayland_shm_buffer *buffer, *next;
700
701 /* Throw away any remaining SHM buffers */
702 wl_list_for_each_safe(buffer, next, &output->shm.free_buffers, free_link)
703 wayland_shm_buffer_destroy(buffer);
704 /* These will get thrown away when they get released */
705 wl_list_for_each(buffer, &output->shm.buffers, link)
706 buffer->output = NULL;
707 }
708
709 static int
wayland_output_disable(struct weston_output * base)710 wayland_output_disable(struct weston_output *base)
711 {
712 struct wayland_output *output = to_wayland_output(base);
713 struct wayland_backend *b = to_wayland_backend(base->compositor);
714
715 if (!output->base.enabled)
716 return 0;
717
718 if (b->use_pixman) {
719 pixman_renderer_output_destroy(&output->base);
720 #ifdef ENABLE_EGL
721 } else {
722 gl_renderer->output_destroy(&output->base);
723 wl_egl_window_destroy(output->gl.egl_window);
724 #endif
725 }
726
727 wayland_output_destroy_shm_buffers(output);
728
729 wayland_backend_destroy_output_surface(output);
730
731 if (output->frame)
732 frame_destroy(output->frame);
733
734 cairo_surface_destroy(output->gl.border.top);
735 cairo_surface_destroy(output->gl.border.left);
736 cairo_surface_destroy(output->gl.border.right);
737 cairo_surface_destroy(output->gl.border.bottom);
738
739 return 0;
740 }
741
742 static void
wayland_output_destroy(struct weston_output * base)743 wayland_output_destroy(struct weston_output *base)
744 {
745 struct wayland_output *output = to_wayland_output(base);
746
747 wayland_output_disable(&output->base);
748
749 weston_output_release(&output->base);
750
751 if (output->frame_cb)
752 wl_callback_destroy(output->frame_cb);
753
754 free(output->title);
755 free(output);
756 }
757
758 static const struct wl_shell_surface_listener shell_surface_listener;
759
760 #ifdef ENABLE_EGL
761 static int
wayland_output_init_gl_renderer(struct wayland_output * output)762 wayland_output_init_gl_renderer(struct wayland_output *output)
763 {
764 int32_t fwidth = 0, fheight = 0;
765 struct gl_renderer_output_options options = {
766 .drm_formats = wayland_formats,
767 .drm_formats_count = ARRAY_LENGTH(wayland_formats),
768 };
769
770 if (output->frame) {
771 fwidth = frame_width(output->frame);
772 fheight = frame_height(output->frame);
773 } else {
774 fwidth = output->base.current_mode->width;
775 fheight = output->base.current_mode->height;
776 }
777
778 output->gl.egl_window =
779 wl_egl_window_create(output->parent.surface,
780 fwidth, fheight);
781 if (!output->gl.egl_window) {
782 weston_log("failure to create wl_egl_window\n");
783 return -1;
784 }
785 options.window_for_legacy = output->gl.egl_window;
786 options.window_for_platform = output->gl.egl_window;
787
788 if (gl_renderer->output_window_create(&output->base, &options) < 0)
789 goto cleanup_window;
790
791 return 0;
792
793 cleanup_window:
794 wl_egl_window_destroy(output->gl.egl_window);
795 return -1;
796 }
797 #endif
798
799 static int
wayland_output_init_pixman_renderer(struct wayland_output * output)800 wayland_output_init_pixman_renderer(struct wayland_output *output)
801 {
802 const struct pixman_renderer_output_options options = {
803 .use_shadow = true,
804 };
805 return pixman_renderer_output_create(&output->base, &options);
806 }
807
808 static void
wayland_output_resize_surface(struct wayland_output * output)809 wayland_output_resize_surface(struct wayland_output *output)
810 {
811 struct wayland_backend *b =
812 to_wayland_backend(output->base.compositor);
813 int32_t ix, iy, iwidth, iheight;
814 int32_t width, height;
815 struct wl_region *region;
816
817 width = output->base.current_mode->width;
818 height = output->base.current_mode->height;
819
820 if (output->frame) {
821 frame_resize_inside(output->frame, width, height);
822
823 frame_input_rect(output->frame, &ix, &iy, &iwidth, &iheight);
824 region = wl_compositor_create_region(b->parent.compositor);
825 wl_region_add(region, ix, iy, iwidth, iheight);
826 wl_surface_set_input_region(output->parent.surface, region);
827 wl_region_destroy(region);
828
829 if (output->parent.xdg_surface) {
830 xdg_surface_set_window_geometry(output->parent.xdg_surface,
831 ix,
832 iy,
833 iwidth,
834 iheight);
835 }
836
837 frame_opaque_rect(output->frame, &ix, &iy, &iwidth, &iheight);
838 region = wl_compositor_create_region(b->parent.compositor);
839 wl_region_add(region, ix, iy, iwidth, iheight);
840 wl_surface_set_opaque_region(output->parent.surface, region);
841 wl_region_destroy(region);
842
843 width = frame_width(output->frame);
844 height = frame_height(output->frame);
845 } else {
846 region = wl_compositor_create_region(b->parent.compositor);
847 wl_region_add(region, 0, 0, width, height);
848 wl_surface_set_input_region(output->parent.surface, region);
849 wl_region_destroy(region);
850
851 region = wl_compositor_create_region(b->parent.compositor);
852 wl_region_add(region, 0, 0, width, height);
853 wl_surface_set_opaque_region(output->parent.surface, region);
854 wl_region_destroy(region);
855
856 if (output->parent.xdg_surface) {
857 xdg_surface_set_window_geometry(output->parent.xdg_surface,
858 0,
859 0,
860 width,
861 height);
862 }
863 }
864
865 #ifdef ENABLE_EGL
866 if (output->gl.egl_window) {
867 wl_egl_window_resize(output->gl.egl_window,
868 width, height, 0, 0);
869
870 /* These will need to be re-created due to the resize */
871 gl_renderer->output_set_border(&output->base,
872 GL_RENDERER_BORDER_TOP,
873 0, 0, 0, NULL);
874 cairo_surface_destroy(output->gl.border.top);
875 output->gl.border.top = NULL;
876 gl_renderer->output_set_border(&output->base,
877 GL_RENDERER_BORDER_LEFT,
878 0, 0, 0, NULL);
879 cairo_surface_destroy(output->gl.border.left);
880 output->gl.border.left = NULL;
881 gl_renderer->output_set_border(&output->base,
882 GL_RENDERER_BORDER_RIGHT,
883 0, 0, 0, NULL);
884 cairo_surface_destroy(output->gl.border.right);
885 output->gl.border.right = NULL;
886 gl_renderer->output_set_border(&output->base,
887 GL_RENDERER_BORDER_BOTTOM,
888 0, 0, 0, NULL);
889 cairo_surface_destroy(output->gl.border.bottom);
890 output->gl.border.bottom = NULL;
891 }
892 #endif
893
894 wayland_output_destroy_shm_buffers(output);
895 }
896
897 static int
wayland_output_set_windowed(struct wayland_output * output)898 wayland_output_set_windowed(struct wayland_output *output)
899 {
900 struct wayland_backend *b =
901 to_wayland_backend(output->base.compositor);
902
903 if (output->frame)
904 return 0;
905
906 if (!b->theme) {
907 b->theme = theme_create();
908 if (!b->theme)
909 return -1;
910 }
911 output->frame = frame_create(b->theme, 100, 100,
912 FRAME_BUTTON_CLOSE, output->title, NULL);
913 if (!output->frame)
914 return -1;
915
916 if (output->keyboard_count)
917 frame_set_flag(output->frame, FRAME_FLAG_ACTIVE);
918
919 wayland_output_resize_surface(output);
920
921 if (output->parent.xdg_toplevel) {
922 xdg_toplevel_unset_fullscreen(output->parent.xdg_toplevel);
923 } else if (output->parent.shell_surface) {
924 wl_shell_surface_set_toplevel(output->parent.shell_surface);
925 } else {
926 abort();
927 }
928
929 return 0;
930 }
931
932 static void
wayland_output_set_fullscreen(struct wayland_output * output,enum wl_shell_surface_fullscreen_method method,uint32_t framerate,struct wl_output * target)933 wayland_output_set_fullscreen(struct wayland_output *output,
934 enum wl_shell_surface_fullscreen_method method,
935 uint32_t framerate, struct wl_output *target)
936 {
937 if (output->frame) {
938 frame_destroy(output->frame);
939 output->frame = NULL;
940 }
941
942 wayland_output_resize_surface(output);
943
944 if (output->parent.xdg_toplevel) {
945 xdg_toplevel_set_fullscreen(output->parent.xdg_toplevel, target);
946 } else if (output->parent.shell_surface) {
947 wl_shell_surface_set_fullscreen(output->parent.shell_surface,
948 method, framerate, target);
949 } else {
950 abort();
951 }
952 }
953
954 static struct weston_mode *
wayland_output_choose_mode(struct wayland_output * output,struct weston_mode * ref_mode)955 wayland_output_choose_mode(struct wayland_output *output,
956 struct weston_mode *ref_mode)
957 {
958 struct weston_mode *mode;
959
960 /* First look for an exact match */
961 wl_list_for_each(mode, &output->base.mode_list, link)
962 if (mode->width == ref_mode->width &&
963 mode->height == ref_mode->height &&
964 mode->refresh == ref_mode->refresh)
965 return mode;
966
967 /* If we can't find an exact match, ignore refresh and try again */
968 wl_list_for_each(mode, &output->base.mode_list, link)
969 if (mode->width == ref_mode->width &&
970 mode->height == ref_mode->height)
971 return mode;
972
973 /* Yeah, we failed */
974 return NULL;
975 }
976
977 enum mode_status {
978 MODE_STATUS_UNKNOWN,
979 MODE_STATUS_SUCCESS,
980 MODE_STATUS_FAIL,
981 MODE_STATUS_CANCEL,
982 };
983
984 static void
mode_feedback_successful(void * data,struct zwp_fullscreen_shell_mode_feedback_v1 * fb)985 mode_feedback_successful(void *data,
986 struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
987 {
988 enum mode_status *value = data;
989
990 printf("Mode switch successful\n");
991
992 *value = MODE_STATUS_SUCCESS;
993 }
994
995 static void
mode_feedback_failed(void * data,struct zwp_fullscreen_shell_mode_feedback_v1 * fb)996 mode_feedback_failed(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
997 {
998 enum mode_status *value = data;
999
1000 printf("Mode switch failed\n");
1001
1002 *value = MODE_STATUS_FAIL;
1003 }
1004
1005 static void
mode_feedback_cancelled(void * data,struct zwp_fullscreen_shell_mode_feedback_v1 * fb)1006 mode_feedback_cancelled(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
1007 {
1008 enum mode_status *value = data;
1009
1010 printf("Mode switch cancelled\n");
1011
1012 *value = MODE_STATUS_CANCEL;
1013 }
1014
1015 struct zwp_fullscreen_shell_mode_feedback_v1_listener mode_feedback_listener = {
1016 mode_feedback_successful,
1017 mode_feedback_failed,
1018 mode_feedback_cancelled,
1019 };
1020
1021 static enum mode_status
wayland_output_fullscreen_shell_mode_feedback(struct wayland_output * output,struct weston_mode * mode)1022 wayland_output_fullscreen_shell_mode_feedback(struct wayland_output *output,
1023 struct weston_mode *mode)
1024 {
1025 struct wayland_backend *b = to_wayland_backend(output->base.compositor);
1026 struct zwp_fullscreen_shell_mode_feedback_v1 *mode_feedback;
1027 enum mode_status mode_status;
1028 int ret = 0;
1029
1030 mode_feedback =
1031 zwp_fullscreen_shell_v1_present_surface_for_mode(b->parent.fshell,
1032 output->parent.surface,
1033 output->parent.output,
1034 mode->refresh);
1035
1036 zwp_fullscreen_shell_mode_feedback_v1_add_listener(mode_feedback,
1037 &mode_feedback_listener,
1038 &mode_status);
1039
1040 output->parent.draw_initial_frame = false;
1041 draw_initial_frame(output);
1042 wl_surface_commit(output->parent.surface);
1043
1044 mode_status = MODE_STATUS_UNKNOWN;
1045 while (mode_status == MODE_STATUS_UNKNOWN && ret >= 0)
1046 ret = wl_display_dispatch(b->parent.wl_display);
1047
1048 zwp_fullscreen_shell_mode_feedback_v1_destroy(mode_feedback);
1049
1050 return mode_status;
1051 }
1052
1053 static int
wayland_output_switch_mode(struct weston_output * output_base,struct weston_mode * mode)1054 wayland_output_switch_mode(struct weston_output *output_base,
1055 struct weston_mode *mode)
1056 {
1057 struct wayland_output *output = to_wayland_output(output_base);
1058 struct wayland_backend *b;
1059 struct wl_surface *old_surface;
1060 struct weston_mode *old_mode;
1061 enum mode_status mode_status;
1062
1063 if (output_base == NULL) {
1064 weston_log("output is NULL.\n");
1065 return -1;
1066 }
1067
1068 if (mode == NULL) {
1069 weston_log("mode is NULL.\n");
1070 return -1;
1071 }
1072
1073 b = to_wayland_backend(output_base->compositor);
1074
1075 if (output->parent.xdg_surface || output->parent.shell_surface || !b->parent.fshell)
1076 return -1;
1077
1078 mode = wayland_output_choose_mode(output, mode);
1079 if (mode == NULL)
1080 return -1;
1081
1082 if (output->base.current_mode == mode)
1083 return 0;
1084
1085 old_mode = output->base.current_mode;
1086 old_surface = output->parent.surface;
1087 output->base.current_mode = mode;
1088 output->parent.surface =
1089 wl_compositor_create_surface(b->parent.compositor);
1090 wl_surface_set_user_data(output->parent.surface, output);
1091
1092 /* Blow the old buffers because we changed size/surfaces */
1093 wayland_output_resize_surface(output);
1094
1095 mode_status = wayland_output_fullscreen_shell_mode_feedback(output, mode);
1096
1097 /* This should kick-start things again */
1098 wayland_output_start_repaint_loop(&output->base);
1099
1100 if (mode_status == MODE_STATUS_FAIL) {
1101 output->base.current_mode = old_mode;
1102 wl_surface_destroy(output->parent.surface);
1103 output->parent.surface = old_surface;
1104 wayland_output_resize_surface(output);
1105
1106 return -1;
1107 }
1108
1109 old_mode->flags &= ~WL_OUTPUT_MODE_CURRENT;
1110 output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
1111
1112 if (b->use_pixman) {
1113 pixman_renderer_output_destroy(output_base);
1114 if (wayland_output_init_pixman_renderer(output) < 0)
1115 goto err_output;
1116 #ifdef ENABLE_EGL
1117 } else {
1118 gl_renderer->output_destroy(output_base);
1119 wl_egl_window_destroy(output->gl.egl_window);
1120 if (wayland_output_init_gl_renderer(output) < 0)
1121 goto err_output;
1122 #endif
1123 }
1124 wl_surface_destroy(old_surface);
1125
1126 weston_output_schedule_repaint(&output->base);
1127
1128 return 0;
1129
1130 err_output:
1131 /* XXX */
1132 return -1;
1133 }
1134
1135 static void
handle_xdg_surface_configure(void * data,struct xdg_surface * surface,uint32_t serial)1136 handle_xdg_surface_configure(void *data, struct xdg_surface *surface,
1137 uint32_t serial)
1138 {
1139 xdg_surface_ack_configure(surface, serial);
1140 }
1141
1142 static const struct xdg_surface_listener xdg_surface_listener = {
1143 handle_xdg_surface_configure
1144 };
1145
1146 static void
handle_xdg_toplevel_configure(void * data,struct xdg_toplevel * toplevel,int32_t width,int32_t height,struct wl_array * states)1147 handle_xdg_toplevel_configure(void *data, struct xdg_toplevel *toplevel,
1148 int32_t width, int32_t height,
1149 struct wl_array *states)
1150 {
1151 struct wayland_output *output = data;
1152
1153 output->parent.configure_width = width;
1154 output->parent.configure_height = height;
1155
1156 output->parent.wait_for_configure = false;
1157 /* FIXME: implement resizing */
1158 }
1159
1160 static void
handle_xdg_toplevel_close(void * data,struct xdg_toplevel * xdg_toplevel)1161 handle_xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
1162 {
1163 struct wayland_output *output = data;
1164 struct weston_compositor *compositor = output->base.compositor;
1165
1166 wayland_output_destroy(&output->base);
1167
1168 if (wl_list_empty(&compositor->output_list))
1169 weston_compositor_exit(compositor);
1170 }
1171
1172 static const struct xdg_toplevel_listener xdg_toplevel_listener = {
1173 handle_xdg_toplevel_configure,
1174 handle_xdg_toplevel_close,
1175 };
1176
1177 static int
wayland_backend_create_output_surface(struct wayland_output * output)1178 wayland_backend_create_output_surface(struct wayland_output *output)
1179 {
1180 struct wayland_backend *b = to_wayland_backend(output->base.compositor);
1181
1182 assert(!output->parent.surface);
1183
1184 output->parent.surface =
1185 wl_compositor_create_surface(b->parent.compositor);
1186 if (!output->parent.surface)
1187 return -1;
1188
1189 wl_surface_set_user_data(output->parent.surface, output);
1190
1191 output->parent.draw_initial_frame = true;
1192
1193 if (b->parent.xdg_wm_base) {
1194 output->parent.xdg_surface =
1195 xdg_wm_base_get_xdg_surface(b->parent.xdg_wm_base,
1196 output->parent.surface);
1197 xdg_surface_add_listener(output->parent.xdg_surface,
1198 &xdg_surface_listener, output);
1199
1200 output->parent.xdg_toplevel =
1201 xdg_surface_get_toplevel(output->parent.xdg_surface);
1202 xdg_toplevel_add_listener(output->parent.xdg_toplevel,
1203 &xdg_toplevel_listener, output);
1204
1205 xdg_toplevel_set_title(output->parent.xdg_toplevel, output->title);
1206
1207 wl_surface_commit(output->parent.surface);
1208
1209 output->parent.wait_for_configure = true;
1210
1211 while (output->parent.wait_for_configure)
1212 wl_display_dispatch(b->parent.wl_display);
1213
1214 weston_log("wayland-backend: Using xdg_wm_base\n");
1215 }
1216 else if (b->parent.shell) {
1217 output->parent.shell_surface =
1218 wl_shell_get_shell_surface(b->parent.shell,
1219 output->parent.surface);
1220 if (!output->parent.shell_surface) {
1221 wl_surface_destroy(output->parent.surface);
1222 return -1;
1223 }
1224
1225 wl_shell_surface_add_listener(output->parent.shell_surface,
1226 &shell_surface_listener, output);
1227
1228 weston_log("wayland-backend: Using wl_shell\n");
1229 }
1230
1231 return 0;
1232 }
1233
1234 static int
wayland_output_enable(struct weston_output * base)1235 wayland_output_enable(struct weston_output *base)
1236 {
1237 struct wayland_output *output = to_wayland_output(base);
1238 struct wayland_backend *b = to_wayland_backend(base->compositor);
1239 enum mode_status mode_status;
1240 int ret = 0;
1241
1242 weston_log("Creating %dx%d wayland output at (%d, %d)\n",
1243 output->base.current_mode->width,
1244 output->base.current_mode->height,
1245 output->base.x, output->base.y);
1246
1247 if (!output->parent.surface)
1248 ret = wayland_backend_create_output_surface(output);
1249
1250 if (ret < 0)
1251 return -1;
1252
1253 wl_list_init(&output->shm.buffers);
1254 wl_list_init(&output->shm.free_buffers);
1255
1256 if (b->use_pixman) {
1257 if (wayland_output_init_pixman_renderer(output) < 0)
1258 goto err_output;
1259
1260 output->base.repaint = wayland_output_repaint_pixman;
1261 #ifdef ENABLE_EGL
1262 } else {
1263 if (wayland_output_init_gl_renderer(output) < 0)
1264 goto err_output;
1265
1266 output->base.repaint = wayland_output_repaint_gl;
1267 #endif
1268 }
1269
1270 output->base.start_repaint_loop = wayland_output_start_repaint_loop;
1271 output->base.assign_planes = NULL;
1272 output->base.set_backlight = NULL;
1273 output->base.set_dpms = NULL;
1274 output->base.switch_mode = wayland_output_switch_mode;
1275
1276 if (b->sprawl_across_outputs) {
1277 if (b->parent.fshell) {
1278 wayland_output_resize_surface(output);
1279
1280 mode_status = wayland_output_fullscreen_shell_mode_feedback(output, &output->mode);
1281
1282 if (mode_status == MODE_STATUS_FAIL) {
1283 zwp_fullscreen_shell_v1_present_surface(b->parent.fshell,
1284 output->parent.surface,
1285 ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER,
1286 output->parent.output);
1287
1288 output->parent.draw_initial_frame = true;
1289 }
1290 } else {
1291 wayland_output_set_fullscreen(output,
1292 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER,
1293 output->mode.refresh, output->parent.output);
1294 }
1295 } else if (b->fullscreen) {
1296 wayland_output_set_fullscreen(output, 0, 0, NULL);
1297 } else {
1298 wayland_output_set_windowed(output);
1299 }
1300
1301 return 0;
1302
1303 err_output:
1304 wayland_backend_destroy_output_surface(output);
1305
1306 return -1;
1307 }
1308
1309 static int
1310 wayland_output_setup_for_parent_output(struct wayland_output *output,
1311 struct wayland_parent_output *poutput);
1312
1313 static int
1314 wayland_output_setup_fullscreen(struct wayland_output *output,
1315 struct wayland_head *head);
1316
1317 static int
wayland_output_attach_head(struct weston_output * output_base,struct weston_head * head_base)1318 wayland_output_attach_head(struct weston_output *output_base,
1319 struct weston_head *head_base)
1320 {
1321 struct wayland_backend *b = to_wayland_backend(output_base->compositor);
1322 struct wayland_output *output = to_wayland_output(output_base);
1323 struct wayland_head *head = to_wayland_head(head_base);
1324
1325 if (!wl_list_empty(&output->base.head_list))
1326 return -1;
1327
1328 if (head->parent_output) {
1329 if (wayland_output_setup_for_parent_output(output,
1330 head->parent_output) < 0)
1331 return -1;
1332 } else if (b->fullscreen) {
1333 if (wayland_output_setup_fullscreen(output, head) < 0)
1334 return -1;
1335 } else {
1336 /* A floating window, nothing to do. */
1337 }
1338
1339 return 0;
1340 }
1341
1342 static void
wayland_output_detach_head(struct weston_output * output_base,struct weston_head * head)1343 wayland_output_detach_head(struct weston_output *output_base,
1344 struct weston_head *head)
1345 {
1346 struct wayland_output *output = to_wayland_output(output_base);
1347
1348 /* Rely on the disable hook if the output was enabled. We do not
1349 * support cloned heads, so detaching is guaranteed to disable the
1350 * output.
1351 */
1352 if (output->base.enabled)
1353 return;
1354
1355 /* undo setup fullscreen */
1356 if (output->parent.surface)
1357 wayland_backend_destroy_output_surface(output);
1358 }
1359
1360 static struct weston_output *
wayland_output_create(struct weston_compositor * compositor,const char * name)1361 wayland_output_create(struct weston_compositor *compositor, const char *name)
1362 {
1363 struct wayland_output *output;
1364 char *title;
1365
1366 /* name can't be NULL. */
1367 assert(name);
1368
1369 output = zalloc(sizeof *output);
1370 if (output == NULL) {
1371 perror("zalloc");
1372 return NULL;
1373 }
1374
1375 if (asprintf(&title, "%s - %s", WINDOW_TITLE, name) < 0) {
1376 free(output);
1377 return NULL;
1378 }
1379 output->title = title;
1380
1381 weston_output_init(&output->base, compositor, name);
1382
1383 output->base.destroy = wayland_output_destroy;
1384 output->base.disable = wayland_output_disable;
1385 output->base.enable = wayland_output_enable;
1386 output->base.attach_head = wayland_output_attach_head;
1387 output->base.detach_head = wayland_output_detach_head;
1388
1389 weston_compositor_add_pending_output(&output->base, compositor);
1390
1391 return &output->base;
1392 }
1393
1394 static struct wayland_head *
wayland_head_create(struct weston_compositor * compositor,const char * name)1395 wayland_head_create(struct weston_compositor *compositor, const char *name)
1396 {
1397 struct wayland_head *head;
1398
1399 assert(name);
1400
1401 head = zalloc(sizeof *head);
1402 if (!head)
1403 return NULL;
1404
1405 weston_head_init(&head->base, name);
1406 weston_head_set_connection_status(&head->base, true);
1407 weston_compositor_add_head(compositor, &head->base);
1408
1409 return head;
1410 }
1411
1412 static int
wayland_head_create_windowed(struct weston_compositor * compositor,const char * name)1413 wayland_head_create_windowed(struct weston_compositor *compositor,
1414 const char *name)
1415 {
1416 if (!wayland_head_create(compositor, name))
1417 return -1;
1418
1419 return 0;
1420 }
1421
1422 static int
wayland_head_create_for_parent_output(struct weston_compositor * compositor,struct wayland_parent_output * poutput)1423 wayland_head_create_for_parent_output(struct weston_compositor *compositor,
1424 struct wayland_parent_output *poutput)
1425 {
1426 struct wayland_head *head;
1427 char name[100];
1428 int ret;
1429
1430 ret = snprintf(name, sizeof(name), "wlparent-%d", poutput->id);
1431 if (ret < 1 || (unsigned)ret >= sizeof(name))
1432 return -1;
1433
1434 head = wayland_head_create(compositor, name);
1435 if (!head)
1436 return -1;
1437
1438 assert(!poutput->head);
1439 head->parent_output = poutput;
1440 poutput->head = head;
1441
1442 weston_head_set_monitor_strings(&head->base,
1443 poutput->physical.make,
1444 poutput->physical.model, NULL);
1445 weston_head_set_physical_size(&head->base,
1446 poutput->physical.width,
1447 poutput->physical.height);
1448
1449 return 0;
1450 }
1451
1452 static void
wayland_head_destroy(struct wayland_head * head)1453 wayland_head_destroy(struct wayland_head *head)
1454 {
1455 if (head->parent_output)
1456 head->parent_output->head = NULL;
1457
1458 weston_head_release(&head->base);
1459 free(head);
1460 }
1461
1462 static int
wayland_output_set_size(struct weston_output * base,int width,int height)1463 wayland_output_set_size(struct weston_output *base, int width, int height)
1464 {
1465 struct wayland_output *output = to_wayland_output(base);
1466 struct weston_head *head;
1467 int output_width, output_height;
1468
1469 /* We can only be called once. */
1470 assert(!output->base.current_mode);
1471
1472 /* Make sure we have scale set. */
1473 assert(output->base.scale);
1474
1475 if (width < 1) {
1476 weston_log("Invalid width \"%d\" for output %s\n",
1477 width, output->base.name);
1478 return -1;
1479 }
1480
1481 if (height < 1) {
1482 weston_log("Invalid height \"%d\" for output %s\n",
1483 height, output->base.name);
1484 return -1;
1485 }
1486
1487 wl_list_for_each(head, &output->base.head_list, output_link) {
1488 weston_head_set_monitor_strings(head, "wayland", "none", NULL);
1489
1490 /* XXX: Calculate proper size. */
1491 weston_head_set_physical_size(head, width, height);
1492 }
1493
1494 output_width = width * output->base.scale;
1495 output_height = height * output->base.scale;
1496
1497 output->mode.flags =
1498 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
1499
1500 output->mode.width = output_width;
1501 output->mode.height = output_height;
1502 output->mode.refresh = 60000;
1503 wl_list_insert(&output->base.mode_list, &output->mode.link);
1504
1505 output->base.current_mode = &output->mode;
1506
1507 return 0;
1508 }
1509
1510 static int
wayland_output_setup_for_parent_output(struct wayland_output * output,struct wayland_parent_output * poutput)1511 wayland_output_setup_for_parent_output(struct wayland_output *output,
1512 struct wayland_parent_output *poutput)
1513 {
1514 struct weston_mode *mode;
1515
1516 if (poutput->current_mode) {
1517 mode = poutput->current_mode;
1518 } else if (poutput->preferred_mode) {
1519 mode = poutput->preferred_mode;
1520 } else if (!wl_list_empty(&poutput->mode_list)) {
1521 mode = container_of(poutput->mode_list.next,
1522 struct weston_mode, link);
1523 } else {
1524 weston_log("No valid modes found. Skipping output.\n");
1525 return -1;
1526 }
1527
1528 output->base.scale = 1;
1529 output->base.transform = WL_OUTPUT_TRANSFORM_NORMAL;
1530
1531 output->parent.output = poutput->global;
1532
1533 wl_list_insert_list(&output->base.mode_list, &poutput->mode_list);
1534 wl_list_init(&poutput->mode_list);
1535
1536 /* No other mode should have CURRENT already. */
1537 mode->flags |= WL_OUTPUT_MODE_CURRENT;
1538 output->base.current_mode = mode;
1539
1540 /* output->mode is unused in this path. */
1541
1542 return 0;
1543 }
1544
1545 static int
wayland_output_setup_fullscreen(struct wayland_output * output,struct wayland_head * head)1546 wayland_output_setup_fullscreen(struct wayland_output *output,
1547 struct wayland_head *head)
1548 {
1549 struct wayland_backend *b = to_wayland_backend(output->base.compositor);
1550 int width = 0, height = 0;
1551
1552 output->base.scale = 1;
1553 output->base.transform = WL_OUTPUT_TRANSFORM_NORMAL;
1554
1555 if (wayland_backend_create_output_surface(output) < 0)
1556 return -1;
1557
1558 /* What should size be set if conditional is false? */
1559 if (b->parent.xdg_wm_base || b->parent.shell) {
1560 if (output->parent.xdg_toplevel)
1561 xdg_toplevel_set_fullscreen(output->parent.xdg_toplevel,
1562 output->parent.output);
1563 else if (output->parent.shell_surface)
1564 wl_shell_surface_set_fullscreen(output->parent.shell_surface,
1565 0, 0, NULL);
1566
1567 wl_display_roundtrip(b->parent.wl_display);
1568
1569 width = output->parent.configure_width;
1570 height = output->parent.configure_height;
1571 }
1572
1573 if (wayland_output_set_size(&output->base, width, height) < 0)
1574 goto err_set_size;
1575
1576 /* The head is not attached yet, so set_size did not set these. */
1577 weston_head_set_monitor_strings(&head->base, "wayland", "none", NULL);
1578 /* XXX: Calculate proper size. */
1579 weston_head_set_physical_size(&head->base, width, height);
1580
1581 return 0;
1582
1583 err_set_size:
1584 wayland_backend_destroy_output_surface(output);
1585
1586 return -1;
1587 }
1588
1589 static void
shell_surface_ping(void * data,struct wl_shell_surface * shell_surface,uint32_t serial)1590 shell_surface_ping(void *data, struct wl_shell_surface *shell_surface,
1591 uint32_t serial)
1592 {
1593 wl_shell_surface_pong(shell_surface, serial);
1594 }
1595
1596 static void
shell_surface_configure(void * data,struct wl_shell_surface * shell_surface,uint32_t edges,int32_t width,int32_t height)1597 shell_surface_configure(void *data, struct wl_shell_surface *shell_surface,
1598 uint32_t edges, int32_t width, int32_t height)
1599 {
1600 struct wayland_output *output = data;
1601
1602 output->parent.configure_width = width;
1603 output->parent.configure_height = height;
1604
1605 /* FIXME: implement resizing */
1606 }
1607
1608 static void
shell_surface_popup_done(void * data,struct wl_shell_surface * shell_surface)1609 shell_surface_popup_done(void *data, struct wl_shell_surface *shell_surface)
1610 {
1611 }
1612
1613 static const struct wl_shell_surface_listener shell_surface_listener = {
1614 shell_surface_ping,
1615 shell_surface_configure,
1616 shell_surface_popup_done
1617 };
1618
1619 /* Events received from the wayland-server this compositor is client of: */
1620
1621 /* parent input interface */
1622 static void
input_set_cursor(struct wayland_input * input)1623 input_set_cursor(struct wayland_input *input)
1624 {
1625
1626 struct wl_buffer *buffer;
1627 struct wl_cursor_image *image;
1628
1629 if (!input->backend->cursor)
1630 return; /* Couldn't load the cursor. Can't set it */
1631
1632 image = input->backend->cursor->images[0];
1633 buffer = wl_cursor_image_get_buffer(image);
1634 if (!buffer)
1635 return;
1636
1637 wl_pointer_set_cursor(input->parent.pointer, input->enter_serial,
1638 input->parent.cursor.surface,
1639 image->hotspot_x, image->hotspot_y);
1640
1641 wl_surface_attach(input->parent.cursor.surface, buffer, 0, 0);
1642 wl_surface_damage(input->parent.cursor.surface, 0, 0,
1643 image->width, image->height);
1644 wl_surface_commit(input->parent.cursor.surface);
1645 }
1646
1647 static void
input_handle_pointer_enter(void * data,struct wl_pointer * pointer,uint32_t serial,struct wl_surface * surface,wl_fixed_t fixed_x,wl_fixed_t fixed_y)1648 input_handle_pointer_enter(void *data, struct wl_pointer *pointer,
1649 uint32_t serial, struct wl_surface *surface,
1650 wl_fixed_t fixed_x, wl_fixed_t fixed_y)
1651 {
1652 struct wayland_input *input = data;
1653 int32_t fx, fy;
1654 enum theme_location location;
1655 double x, y;
1656
1657 if (!surface) {
1658 input->output = NULL;
1659 input->has_focus = false;
1660 notify_pointer_focus(&input->base, NULL, 0, 0);
1661 return;
1662 }
1663
1664 x = wl_fixed_to_double(fixed_x);
1665 y = wl_fixed_to_double(fixed_y);
1666
1667 /* XXX: If we get a modifier event immediately before the focus,
1668 * we should try to keep the same serial. */
1669 input->enter_serial = serial;
1670 input->output = wl_surface_get_user_data(surface);
1671
1672 if (input->output->frame) {
1673 location = frame_pointer_enter(input->output->frame, input,
1674 x, y);
1675 frame_interior(input->output->frame, &fx, &fy, NULL, NULL);
1676 x -= fx;
1677 y -= fy;
1678
1679 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1680 weston_output_schedule_repaint(&input->output->base);
1681 } else {
1682 location = THEME_LOCATION_CLIENT_AREA;
1683 }
1684
1685 weston_output_transform_coordinate(&input->output->base, x, y, &x, &y);
1686
1687 if (location == THEME_LOCATION_CLIENT_AREA) {
1688 input->has_focus = true;
1689 notify_pointer_focus(&input->base, &input->output->base, x, y);
1690 wl_pointer_set_cursor(input->parent.pointer,
1691 input->enter_serial, NULL, 0, 0);
1692 } else {
1693 input->has_focus = false;
1694 notify_pointer_focus(&input->base, NULL, 0, 0);
1695 input_set_cursor(input);
1696 }
1697 }
1698
1699 static void
input_handle_pointer_leave(void * data,struct wl_pointer * pointer,uint32_t serial,struct wl_surface * surface)1700 input_handle_pointer_leave(void *data, struct wl_pointer *pointer,
1701 uint32_t serial, struct wl_surface *surface)
1702 {
1703 struct wayland_input *input = data;
1704
1705 if (!input->output)
1706 return;
1707
1708 if (input->output->frame) {
1709 frame_pointer_leave(input->output->frame, input);
1710
1711 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1712 weston_output_schedule_repaint(&input->output->base);
1713 }
1714
1715 notify_pointer_focus(&input->base, NULL, 0, 0);
1716 input->output = NULL;
1717 input->has_focus = false;
1718 }
1719
1720 static void
input_handle_motion(void * data,struct wl_pointer * pointer,uint32_t time,wl_fixed_t fixed_x,wl_fixed_t fixed_y)1721 input_handle_motion(void *data, struct wl_pointer *pointer,
1722 uint32_t time, wl_fixed_t fixed_x, wl_fixed_t fixed_y)
1723 {
1724 struct wayland_input *input = data;
1725 int32_t fx, fy;
1726 enum theme_location location;
1727 bool want_frame = false;
1728 double x, y;
1729 struct timespec ts;
1730
1731 if (!input->output)
1732 return;
1733
1734 x = wl_fixed_to_double(fixed_x);
1735 y = wl_fixed_to_double(fixed_y);
1736
1737 if (input->output->frame) {
1738 location = frame_pointer_motion(input->output->frame, input,
1739 x, y);
1740 frame_interior(input->output->frame, &fx, &fy, NULL, NULL);
1741 x -= fx;
1742 y -= fy;
1743
1744 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1745 weston_output_schedule_repaint(&input->output->base);
1746 } else {
1747 location = THEME_LOCATION_CLIENT_AREA;
1748 }
1749
1750 weston_output_transform_coordinate(&input->output->base, x, y, &x, &y);
1751
1752 if (input->has_focus && location != THEME_LOCATION_CLIENT_AREA) {
1753 input_set_cursor(input);
1754 notify_pointer_focus(&input->base, NULL, 0, 0);
1755 input->has_focus = false;
1756 want_frame = true;
1757 } else if (!input->has_focus &&
1758 location == THEME_LOCATION_CLIENT_AREA) {
1759 wl_pointer_set_cursor(input->parent.pointer,
1760 input->enter_serial, NULL, 0, 0);
1761 notify_pointer_focus(&input->base, &input->output->base, x, y);
1762 input->has_focus = true;
1763 want_frame = true;
1764 }
1765
1766 if (location == THEME_LOCATION_CLIENT_AREA) {
1767 timespec_from_msec(&ts, time);
1768 notify_motion_absolute(&input->base, &ts, x, y);
1769 want_frame = true;
1770 }
1771
1772 if (want_frame && input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
1773 notify_pointer_frame(&input->base);
1774 }
1775
1776 static void
input_handle_button(void * data,struct wl_pointer * pointer,uint32_t serial,uint32_t time,uint32_t button,enum wl_pointer_button_state state)1777 input_handle_button(void *data, struct wl_pointer *pointer,
1778 uint32_t serial, uint32_t time, uint32_t button,
1779 enum wl_pointer_button_state state)
1780 {
1781 struct wayland_input *input = data;
1782 enum theme_location location;
1783 struct timespec ts;
1784
1785 if (!input->output)
1786 return;
1787
1788 if (input->output->frame) {
1789 location = frame_pointer_button(input->output->frame, input,
1790 button, state);
1791
1792 if (frame_status(input->output->frame) & FRAME_STATUS_MOVE) {
1793 if (input->output->parent.xdg_toplevel)
1794 xdg_toplevel_move(input->output->parent.xdg_toplevel,
1795 input->parent.seat, serial);
1796 else if (input->output->parent.shell_surface)
1797 wl_shell_surface_move(input->output->parent.shell_surface,
1798 input->parent.seat, serial);
1799 frame_status_clear(input->output->frame,
1800 FRAME_STATUS_MOVE);
1801 return;
1802 }
1803
1804 if (frame_status(input->output->frame) & FRAME_STATUS_CLOSE) {
1805 wayland_output_destroy(&input->output->base);
1806 input->output = NULL;
1807 input->keyboard_focus = NULL;
1808
1809 if (wl_list_empty(&input->backend->compositor->output_list))
1810 weston_compositor_exit(input->backend->compositor);
1811
1812 return;
1813 }
1814
1815 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1816 weston_output_schedule_repaint(&input->output->base);
1817 } else {
1818 location = THEME_LOCATION_CLIENT_AREA;
1819 }
1820
1821 if (location == THEME_LOCATION_CLIENT_AREA) {
1822 timespec_from_msec(&ts, time);
1823 notify_button(&input->base, &ts, button, state);
1824 if (input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
1825 notify_pointer_frame(&input->base);
1826 }
1827 }
1828
1829 static void
input_handle_axis(void * data,struct wl_pointer * pointer,uint32_t time,uint32_t axis,wl_fixed_t value)1830 input_handle_axis(void *data, struct wl_pointer *pointer,
1831 uint32_t time, uint32_t axis, wl_fixed_t value)
1832 {
1833 struct wayland_input *input = data;
1834 struct weston_pointer_axis_event weston_event;
1835 struct timespec ts;
1836
1837 weston_event.axis = axis;
1838 weston_event.value = wl_fixed_to_double(value);
1839 weston_event.has_discrete = false;
1840
1841 if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL &&
1842 input->vert.has_discrete) {
1843 weston_event.has_discrete = true;
1844 weston_event.discrete = input->vert.discrete;
1845 input->vert.has_discrete = false;
1846 } else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL &&
1847 input->horiz.has_discrete) {
1848 weston_event.has_discrete = true;
1849 weston_event.discrete = input->horiz.discrete;
1850 input->horiz.has_discrete = false;
1851 }
1852
1853 timespec_from_msec(&ts, time);
1854
1855 notify_axis(&input->base, &ts, &weston_event);
1856
1857 if (input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
1858 notify_pointer_frame(&input->base);
1859 }
1860
1861 static void
input_handle_frame(void * data,struct wl_pointer * pointer)1862 input_handle_frame(void *data, struct wl_pointer *pointer)
1863 {
1864 struct wayland_input *input = data;
1865
1866 notify_pointer_frame(&input->base);
1867 }
1868
1869 static void
input_handle_axis_source(void * data,struct wl_pointer * pointer,uint32_t source)1870 input_handle_axis_source(void *data, struct wl_pointer *pointer,
1871 uint32_t source)
1872 {
1873 struct wayland_input *input = data;
1874
1875 notify_axis_source(&input->base, source);
1876 }
1877
1878 static void
input_handle_axis_stop(void * data,struct wl_pointer * pointer,uint32_t time,uint32_t axis)1879 input_handle_axis_stop(void *data, struct wl_pointer *pointer,
1880 uint32_t time, uint32_t axis)
1881 {
1882 struct wayland_input *input = data;
1883 struct weston_pointer_axis_event weston_event;
1884 struct timespec ts;
1885
1886 weston_event.axis = axis;
1887 weston_event.value = 0;
1888
1889 timespec_from_msec(&ts, time);
1890
1891 notify_axis(&input->base, &ts, &weston_event);
1892 }
1893
1894 static void
input_handle_axis_discrete(void * data,struct wl_pointer * pointer,uint32_t axis,int32_t discrete)1895 input_handle_axis_discrete(void *data, struct wl_pointer *pointer,
1896 uint32_t axis, int32_t discrete)
1897 {
1898 struct wayland_input *input = data;
1899
1900 if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
1901 input->vert.has_discrete = true;
1902 input->vert.discrete = discrete;
1903 } else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
1904 input->horiz.has_discrete = true;
1905 input->horiz.discrete = discrete;
1906 }
1907 }
1908
1909 static const struct wl_pointer_listener pointer_listener = {
1910 input_handle_pointer_enter,
1911 input_handle_pointer_leave,
1912 input_handle_motion,
1913 input_handle_button,
1914 input_handle_axis,
1915 input_handle_frame,
1916 input_handle_axis_source,
1917 input_handle_axis_stop,
1918 input_handle_axis_discrete,
1919 };
1920
1921 static void
input_handle_keymap(void * data,struct wl_keyboard * keyboard,uint32_t format,int fd,uint32_t size)1922 input_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format,
1923 int fd, uint32_t size)
1924 {
1925 struct wayland_input *input = data;
1926 struct xkb_keymap *keymap;
1927 char *map_str;
1928
1929 if (!data) {
1930 close(fd);
1931 return;
1932 }
1933
1934 if (format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
1935 map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
1936 if (map_str == MAP_FAILED) {
1937 weston_log("mmap failed: %s\n", strerror(errno));
1938 goto error;
1939 }
1940
1941 keymap = xkb_keymap_new_from_string(input->backend->compositor->xkb_context,
1942 map_str,
1943 XKB_KEYMAP_FORMAT_TEXT_V1,
1944 0);
1945 munmap(map_str, size);
1946
1947 if (!keymap) {
1948 weston_log("failed to compile keymap\n");
1949 goto error;
1950 }
1951
1952 input->keyboard_state_update = STATE_UPDATE_NONE;
1953 } else if (format == WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP) {
1954 weston_log("No keymap provided; falling back to default\n");
1955 keymap = NULL;
1956 input->keyboard_state_update = STATE_UPDATE_AUTOMATIC;
1957 } else {
1958 weston_log("Invalid keymap\n");
1959 goto error;
1960 }
1961
1962 close(fd);
1963
1964 if (weston_seat_get_keyboard(&input->base))
1965 weston_seat_update_keymap(&input->base, keymap);
1966 else
1967 weston_seat_init_keyboard(&input->base, keymap);
1968
1969 xkb_keymap_unref(keymap);
1970
1971 return;
1972
1973 error:
1974 wl_keyboard_release(input->parent.keyboard);
1975 close(fd);
1976 }
1977
1978 static void
input_handle_keyboard_enter(void * data,struct wl_keyboard * keyboard,uint32_t serial,struct wl_surface * surface,struct wl_array * keys)1979 input_handle_keyboard_enter(void *data,
1980 struct wl_keyboard *keyboard,
1981 uint32_t serial,
1982 struct wl_surface *surface,
1983 struct wl_array *keys)
1984 {
1985 struct wayland_input *input = data;
1986 struct wayland_output *focus;
1987
1988 focus = input->keyboard_focus;
1989 if (focus) {
1990 /* This shouldn't happen */
1991 focus->keyboard_count--;
1992 if (!focus->keyboard_count && focus->frame)
1993 frame_unset_flag(focus->frame, FRAME_FLAG_ACTIVE);
1994 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
1995 weston_output_schedule_repaint(&focus->base);
1996 }
1997
1998 if (!surface) {
1999 input->keyboard_focus = NULL;
2000 return;
2001 }
2002
2003 input->keyboard_focus = wl_surface_get_user_data(surface);
2004 input->keyboard_focus->keyboard_count++;
2005
2006 focus = input->keyboard_focus;
2007 if (focus->frame) {
2008 frame_set_flag(focus->frame, FRAME_FLAG_ACTIVE);
2009 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
2010 weston_output_schedule_repaint(&focus->base);
2011 }
2012
2013
2014 /* XXX: If we get a modifier event immediately before the focus,
2015 * we should try to keep the same serial. */
2016 notify_keyboard_focus_in(&input->base, keys,
2017 STATE_UPDATE_AUTOMATIC);
2018 }
2019
2020 static void
input_handle_keyboard_leave(void * data,struct wl_keyboard * keyboard,uint32_t serial,struct wl_surface * surface)2021 input_handle_keyboard_leave(void *data,
2022 struct wl_keyboard *keyboard,
2023 uint32_t serial,
2024 struct wl_surface *surface)
2025 {
2026 struct wayland_input *input = data;
2027 struct wayland_output *focus;
2028
2029 notify_keyboard_focus_out(&input->base);
2030
2031 focus = input->keyboard_focus;
2032 if (!focus)
2033 return;
2034
2035 focus->keyboard_count--;
2036 if (!focus->keyboard_count && focus->frame) {
2037 frame_unset_flag(focus->frame, FRAME_FLAG_ACTIVE);
2038 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
2039 weston_output_schedule_repaint(&focus->base);
2040 }
2041
2042 input->keyboard_focus = NULL;
2043 }
2044
2045 static void
input_handle_key(void * data,struct wl_keyboard * keyboard,uint32_t serial,uint32_t time,uint32_t key,uint32_t state)2046 input_handle_key(void *data, struct wl_keyboard *keyboard,
2047 uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
2048 {
2049 struct wayland_input *input = data;
2050 struct timespec ts;
2051
2052 if (!input->keyboard_focus)
2053 return;
2054
2055 timespec_from_msec(&ts, time);
2056
2057 input->key_serial = serial;
2058 notify_key(&input->base, &ts, key,
2059 state ? WL_KEYBOARD_KEY_STATE_PRESSED :
2060 WL_KEYBOARD_KEY_STATE_RELEASED,
2061 input->keyboard_state_update);
2062 }
2063
2064 static void
input_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)2065 input_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
2066 uint32_t serial_in, uint32_t mods_depressed,
2067 uint32_t mods_latched, uint32_t mods_locked,
2068 uint32_t group)
2069 {
2070 struct weston_keyboard *keyboard;
2071 struct wayland_input *input = data;
2072 struct wayland_backend *b = input->backend;
2073 uint32_t serial_out;
2074
2075 /* If we get a key event followed by a modifier event with the
2076 * same serial number, then we try to preserve those semantics by
2077 * reusing the same serial number on the way out too. */
2078 if (serial_in == input->key_serial)
2079 serial_out = wl_display_get_serial(b->compositor->wl_display);
2080 else
2081 serial_out = wl_display_next_serial(b->compositor->wl_display);
2082
2083 keyboard = weston_seat_get_keyboard(&input->base);
2084 xkb_state_update_mask(keyboard->xkb_state.state,
2085 mods_depressed, mods_latched,
2086 mods_locked, 0, 0, group);
2087 notify_modifiers(&input->base, serial_out);
2088 }
2089
2090 static void
input_handle_repeat_info(void * data,struct wl_keyboard * keyboard,int32_t rate,int32_t delay)2091 input_handle_repeat_info(void *data, struct wl_keyboard *keyboard,
2092 int32_t rate, int32_t delay)
2093 {
2094 struct wayland_input *input = data;
2095 struct wayland_backend *b = input->backend;
2096
2097 b->compositor->kb_repeat_rate = rate;
2098 b->compositor->kb_repeat_delay = delay;
2099 }
2100
2101 static const struct wl_keyboard_listener keyboard_listener = {
2102 input_handle_keymap,
2103 input_handle_keyboard_enter,
2104 input_handle_keyboard_leave,
2105 input_handle_key,
2106 input_handle_modifiers,
2107 input_handle_repeat_info,
2108 };
2109
2110 static void
input_handle_touch_down(void * data,struct wl_touch * wl_touch,uint32_t serial,uint32_t time,struct wl_surface * surface,int32_t id,wl_fixed_t fixed_x,wl_fixed_t fixed_y)2111 input_handle_touch_down(void *data, struct wl_touch *wl_touch,
2112 uint32_t serial, uint32_t time,
2113 struct wl_surface *surface, int32_t id,
2114 wl_fixed_t fixed_x, wl_fixed_t fixed_y)
2115 {
2116 struct wayland_input *input = data;
2117 struct wayland_output *output;
2118 enum theme_location location;
2119 bool first_touch;
2120 int32_t fx, fy;
2121 double x, y;
2122 struct timespec ts;
2123
2124 x = wl_fixed_to_double(fixed_x);
2125 y = wl_fixed_to_double(fixed_y);
2126
2127 timespec_from_msec(&ts, time);
2128
2129 first_touch = (input->touch_points == 0);
2130 input->touch_points++;
2131
2132 input->touch_focus = wl_surface_get_user_data(surface);
2133 output = input->touch_focus;
2134 if (!first_touch && !input->touch_active)
2135 return;
2136
2137 if (output->frame) {
2138 location = frame_touch_down(output->frame, input, id, x, y);
2139
2140 frame_interior(output->frame, &fx, &fy, NULL, NULL);
2141 x -= fx;
2142 y -= fy;
2143
2144 if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
2145 weston_output_schedule_repaint(&output->base);
2146
2147 if (first_touch && (frame_status(output->frame) & FRAME_STATUS_MOVE)) {
2148 input->touch_points--;
2149 if (output->parent.xdg_toplevel)
2150 xdg_toplevel_move(output->parent.xdg_toplevel,
2151 input->parent.seat, serial);
2152 else if (output->parent.shell_surface)
2153 wl_shell_surface_move(output->parent.shell_surface,
2154 input->parent.seat, serial);
2155 frame_status_clear(output->frame,
2156 FRAME_STATUS_MOVE);
2157 return;
2158 }
2159
2160 if (first_touch && location != THEME_LOCATION_CLIENT_AREA)
2161 return;
2162 }
2163
2164 weston_output_transform_coordinate(&output->base, x, y, &x, &y);
2165
2166 notify_touch(input->touch_device, &ts, id, x, y, WL_TOUCH_DOWN);
2167 input->touch_active = true;
2168 }
2169
2170 static void
input_handle_touch_up(void * data,struct wl_touch * wl_touch,uint32_t serial,uint32_t time,int32_t id)2171 input_handle_touch_up(void *data, struct wl_touch *wl_touch,
2172 uint32_t serial, uint32_t time, int32_t id)
2173 {
2174 struct wayland_input *input = data;
2175 struct wayland_output *output = input->touch_focus;
2176 bool active = input->touch_active;
2177 struct timespec ts;
2178
2179 timespec_from_msec(&ts, time);
2180
2181 input->touch_points--;
2182 if (input->touch_points == 0) {
2183 input->touch_focus = NULL;
2184 input->touch_active = false;
2185 }
2186
2187 if (!output)
2188 return;
2189
2190 if (output->frame) {
2191 frame_touch_up(output->frame, input, id);
2192
2193 if (frame_status(output->frame) & FRAME_STATUS_CLOSE) {
2194 wayland_output_destroy(&output->base);
2195 input->touch_focus = NULL;
2196 input->keyboard_focus = NULL;
2197 if (wl_list_empty(&input->backend->compositor->output_list))
2198 weston_compositor_exit(input->backend->compositor);
2199
2200 return;
2201 }
2202 if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
2203 weston_output_schedule_repaint(&output->base);
2204 }
2205
2206 if (active)
2207 notify_touch(input->touch_device, &ts, id, 0, 0, WL_TOUCH_UP);
2208 }
2209
2210 static void
input_handle_touch_motion(void * data,struct wl_touch * wl_touch,uint32_t time,int32_t id,wl_fixed_t fixed_x,wl_fixed_t fixed_y)2211 input_handle_touch_motion(void *data, struct wl_touch *wl_touch,
2212 uint32_t time, int32_t id,
2213 wl_fixed_t fixed_x, wl_fixed_t fixed_y)
2214 {
2215 struct wayland_input *input = data;
2216 struct wayland_output *output = input->touch_focus;
2217 int32_t fx, fy;
2218 double x, y;
2219 struct timespec ts;
2220
2221 x = wl_fixed_to_double(fixed_x);
2222 y = wl_fixed_to_double(fixed_y);
2223 timespec_from_msec(&ts, time);
2224
2225 if (!output || !input->touch_active)
2226 return;
2227
2228 if (output->frame) {
2229 frame_interior(output->frame, &fx, &fy, NULL, NULL);
2230 x -= fx;
2231 y -= fy;
2232 }
2233
2234 weston_output_transform_coordinate(&output->base, x, y, &x, &y);
2235
2236 notify_touch(input->touch_device, &ts, id, x, y, WL_TOUCH_MOTION);
2237 }
2238
2239 static void
input_handle_touch_frame(void * data,struct wl_touch * wl_touch)2240 input_handle_touch_frame(void *data, struct wl_touch *wl_touch)
2241 {
2242 struct wayland_input *input = data;
2243
2244 if (!input->touch_focus || !input->touch_active)
2245 return;
2246
2247 notify_touch_frame(input->touch_device);
2248 }
2249
2250 static void
input_handle_touch_cancel(void * data,struct wl_touch * wl_touch)2251 input_handle_touch_cancel(void *data, struct wl_touch *wl_touch)
2252 {
2253 struct wayland_input *input = data;
2254
2255 if (!input->touch_focus || !input->touch_active)
2256 return;
2257
2258 notify_touch_cancel(input->touch_device);
2259 }
2260
2261 static const struct wl_touch_listener touch_listener = {
2262 input_handle_touch_down,
2263 input_handle_touch_up,
2264 input_handle_touch_motion,
2265 input_handle_touch_frame,
2266 input_handle_touch_cancel,
2267 };
2268
2269
2270 static struct weston_touch_device *
create_touch_device(struct wayland_input * input)2271 create_touch_device(struct wayland_input *input)
2272 {
2273 struct weston_touch_device *touch_device;
2274 char str[128];
2275
2276 /* manufacture a unique'ish name */
2277 snprintf(str, sizeof str, "wayland-touch[%u]",
2278 wl_proxy_get_id((struct wl_proxy *)input->parent.seat));
2279
2280 touch_device = weston_touch_create_touch_device(input->base.touch_state,
2281 str, NULL, NULL);
2282
2283 return touch_device;
2284 }
2285
2286 static void
input_handle_capabilities(void * data,struct wl_seat * seat,enum wl_seat_capability caps)2287 input_handle_capabilities(void *data, struct wl_seat *seat,
2288 enum wl_seat_capability caps)
2289 {
2290 struct wayland_input *input = data;
2291
2292 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->parent.pointer) {
2293 input->parent.pointer = wl_seat_get_pointer(seat);
2294 wl_pointer_set_user_data(input->parent.pointer, input);
2295 wl_pointer_add_listener(input->parent.pointer,
2296 &pointer_listener, input);
2297 weston_seat_init_pointer(&input->base);
2298 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->parent.pointer) {
2299 if (input->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION)
2300 wl_pointer_release(input->parent.pointer);
2301 else
2302 wl_pointer_destroy(input->parent.pointer);
2303 input->parent.pointer = NULL;
2304 weston_seat_release_pointer(&input->base);
2305 }
2306
2307 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->parent.keyboard) {
2308 input->parent.keyboard = wl_seat_get_keyboard(seat);
2309 wl_keyboard_set_user_data(input->parent.keyboard, input);
2310 wl_keyboard_add_listener(input->parent.keyboard,
2311 &keyboard_listener, input);
2312 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->parent.keyboard) {
2313 if (input->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
2314 wl_keyboard_release(input->parent.keyboard);
2315 else
2316 wl_keyboard_destroy(input->parent.keyboard);
2317 input->parent.keyboard = NULL;
2318 weston_seat_release_keyboard(&input->base);
2319 }
2320
2321 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->parent.touch) {
2322 input->parent.touch = wl_seat_get_touch(seat);
2323 wl_touch_set_user_data(input->parent.touch, input);
2324 wl_touch_add_listener(input->parent.touch,
2325 &touch_listener, input);
2326 weston_seat_init_touch(&input->base);
2327 input->touch_device = create_touch_device(input);
2328 } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->parent.touch) {
2329 weston_touch_device_destroy(input->touch_device);
2330 input->touch_device = NULL;
2331 if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION)
2332 wl_touch_release(input->parent.touch);
2333 else
2334 wl_touch_destroy(input->parent.touch);
2335 input->parent.touch = NULL;
2336 weston_seat_release_touch(&input->base);
2337 }
2338 }
2339
2340 static void
input_handle_name(void * data,struct wl_seat * seat,const char * name)2341 input_handle_name(void *data, struct wl_seat *seat,
2342 const char *name)
2343 {
2344 }
2345
2346 static const struct wl_seat_listener seat_listener = {
2347 input_handle_capabilities,
2348 input_handle_name,
2349 };
2350
2351 static void
display_add_seat(struct wayland_backend * b,uint32_t id,uint32_t available_version)2352 display_add_seat(struct wayland_backend *b, uint32_t id, uint32_t available_version)
2353 {
2354 struct wayland_input *input;
2355 uint32_t version = MIN(available_version, 4);
2356
2357 input = zalloc(sizeof *input);
2358 if (input == NULL)
2359 return;
2360
2361 weston_seat_init(&input->base, b->compositor, "default");
2362 input->backend = b;
2363 input->parent.seat = wl_registry_bind(b->parent.registry, id,
2364 &wl_seat_interface, version);
2365 input->seat_version = version;
2366 wl_list_insert(b->input_list.prev, &input->link);
2367
2368 wl_seat_add_listener(input->parent.seat, &seat_listener, input);
2369 wl_seat_set_user_data(input->parent.seat, input);
2370
2371 input->parent.cursor.surface =
2372 wl_compositor_create_surface(b->parent.compositor);
2373
2374 input->vert.axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
2375 input->horiz.axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
2376 }
2377
2378 static void
wayland_parent_output_geometry(void * data,struct wl_output * output_proxy,int32_t x,int32_t y,int32_t physical_width,int32_t physical_height,int32_t subpixel,const char * make,const char * model,int32_t transform)2379 wayland_parent_output_geometry(void *data, struct wl_output *output_proxy,
2380 int32_t x, int32_t y,
2381 int32_t physical_width, int32_t physical_height,
2382 int32_t subpixel, const char *make,
2383 const char *model, int32_t transform)
2384 {
2385 struct wayland_parent_output *output = data;
2386
2387 output->x = x;
2388 output->y = y;
2389 output->physical.width = physical_width;
2390 output->physical.height = physical_height;
2391 output->physical.subpixel = subpixel;
2392
2393 free(output->physical.make);
2394 output->physical.make = strdup(make);
2395 free(output->physical.model);
2396 output->physical.model = strdup(model);
2397
2398 output->transform = transform;
2399 }
2400
2401 static struct weston_mode *
find_mode(struct wl_list * list,int32_t width,int32_t height,uint32_t refresh)2402 find_mode(struct wl_list *list, int32_t width, int32_t height, uint32_t refresh)
2403 {
2404 struct weston_mode *mode;
2405
2406 wl_list_for_each(mode, list, link) {
2407 if (mode->width == width && mode->height == height &&
2408 mode->refresh == refresh)
2409 return mode;
2410 }
2411
2412 mode = zalloc(sizeof *mode);
2413 if (!mode)
2414 return NULL;
2415
2416 mode->width = width;
2417 mode->height = height;
2418 mode->refresh = refresh;
2419 wl_list_insert(list, &mode->link);
2420
2421 return mode;
2422 }
2423
2424 static struct weston_output *
wayland_parent_output_get_enabled_output(struct wayland_parent_output * poutput)2425 wayland_parent_output_get_enabled_output(struct wayland_parent_output *poutput)
2426 {
2427 struct wayland_head *head = poutput->head;
2428
2429 if (!head)
2430 return NULL;
2431
2432 if (!weston_head_is_enabled(&head->base))
2433 return NULL;
2434
2435 return weston_head_get_output(&head->base);
2436 }
2437
2438 static void
wayland_parent_output_mode(void * data,struct wl_output * wl_output_proxy,uint32_t flags,int32_t width,int32_t height,int32_t refresh)2439 wayland_parent_output_mode(void *data, struct wl_output *wl_output_proxy,
2440 uint32_t flags, int32_t width, int32_t height,
2441 int32_t refresh)
2442 {
2443 struct wayland_parent_output *output = data;
2444 struct weston_output *enabled_output;
2445 struct weston_mode *mode;
2446
2447 enabled_output = wayland_parent_output_get_enabled_output(output);
2448 if (enabled_output) {
2449 mode = find_mode(&enabled_output->mode_list,
2450 width, height, refresh);
2451 if (!mode)
2452 return;
2453 mode->flags = flags;
2454 /* Do a mode-switch on current mode change? */
2455 } else {
2456 mode = find_mode(&output->mode_list, width, height, refresh);
2457 if (!mode)
2458 return;
2459 mode->flags = flags;
2460 if (flags & WL_OUTPUT_MODE_CURRENT)
2461 output->current_mode = mode;
2462 if (flags & WL_OUTPUT_MODE_PREFERRED)
2463 output->preferred_mode = mode;
2464 }
2465 }
2466
2467 static const struct wl_output_listener output_listener = {
2468 wayland_parent_output_geometry,
2469 wayland_parent_output_mode
2470 };
2471
2472 static void
output_sync_callback(void * data,struct wl_callback * callback,uint32_t unused)2473 output_sync_callback(void *data, struct wl_callback *callback, uint32_t unused)
2474 {
2475 struct wayland_parent_output *output = data;
2476
2477 assert(output->sync_cb == callback);
2478 wl_callback_destroy(callback);
2479 output->sync_cb = NULL;
2480
2481 assert(output->backend->sprawl_across_outputs);
2482
2483 wayland_head_create_for_parent_output(output->backend->compositor, output);
2484 }
2485
2486 static const struct wl_callback_listener output_sync_listener = {
2487 output_sync_callback
2488 };
2489
2490 static void
wayland_backend_register_output(struct wayland_backend * b,uint32_t id)2491 wayland_backend_register_output(struct wayland_backend *b, uint32_t id)
2492 {
2493 struct wayland_parent_output *output;
2494
2495 output = zalloc(sizeof *output);
2496 if (!output)
2497 return;
2498
2499 output->backend = b;
2500 output->id = id;
2501 output->global = wl_registry_bind(b->parent.registry, id,
2502 &wl_output_interface, 1);
2503 if (!output->global) {
2504 free(output);
2505 return;
2506 }
2507
2508 wl_output_add_listener(output->global, &output_listener, output);
2509
2510 output->scale = 0;
2511 output->transform = WL_OUTPUT_TRANSFORM_NORMAL;
2512 output->physical.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
2513 wl_list_init(&output->mode_list);
2514 wl_list_insert(&b->parent.output_list, &output->link);
2515
2516 if (b->sprawl_across_outputs) {
2517 output->sync_cb = wl_display_sync(b->parent.wl_display);
2518 wl_callback_add_listener(output->sync_cb,
2519 &output_sync_listener, output);
2520 }
2521 }
2522
2523 static void
wayland_parent_output_destroy(struct wayland_parent_output * output)2524 wayland_parent_output_destroy(struct wayland_parent_output *output)
2525 {
2526 struct weston_mode *mode, *next;
2527
2528 if (output->sync_cb)
2529 wl_callback_destroy(output->sync_cb);
2530
2531 if (output->head)
2532 wayland_head_destroy(output->head);
2533
2534 wl_output_destroy(output->global);
2535 free(output->physical.make);
2536 free(output->physical.model);
2537
2538 wl_list_for_each_safe(mode, next, &output->mode_list, link) {
2539 wl_list_remove(&mode->link);
2540 free(mode);
2541 }
2542
2543 wl_list_remove(&output->link);
2544 free(output);
2545 }
2546
2547 static void
xdg_wm_base_ping(void * data,struct xdg_wm_base * shell,uint32_t serial)2548 xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
2549 {
2550 xdg_wm_base_pong(shell, serial);
2551 }
2552
2553 static const struct xdg_wm_base_listener wm_base_listener = {
2554 xdg_wm_base_ping,
2555 };
2556
2557 static void
registry_handle_global(void * data,struct wl_registry * registry,uint32_t name,const char * interface,uint32_t version)2558 registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
2559 const char *interface, uint32_t version)
2560 {
2561 struct wayland_backend *b = data;
2562
2563 if (strcmp(interface, "wl_compositor") == 0) {
2564 b->parent.compositor =
2565 wl_registry_bind(registry, name,
2566 &wl_compositor_interface,
2567 MIN(version, 4));
2568 } else if (strcmp(interface, "xdg_wm_base") == 0) {
2569 b->parent.xdg_wm_base =
2570 wl_registry_bind(registry, name,
2571 &xdg_wm_base_interface, 1);
2572 xdg_wm_base_add_listener(b->parent.xdg_wm_base,
2573 &wm_base_listener, b);
2574 } else if (strcmp(interface, "wl_shell") == 0) {
2575 b->parent.shell =
2576 wl_registry_bind(registry, name,
2577 &wl_shell_interface, 1);
2578 } else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
2579 b->parent.fshell =
2580 wl_registry_bind(registry, name,
2581 &zwp_fullscreen_shell_v1_interface, 1);
2582 } else if (strcmp(interface, "wl_seat") == 0) {
2583 display_add_seat(b, name, version);
2584 } else if (strcmp(interface, "wl_output") == 0) {
2585 wayland_backend_register_output(b, name);
2586 } else if (strcmp(interface, "wl_shm") == 0) {
2587 b->parent.shm =
2588 wl_registry_bind(registry, name, &wl_shm_interface, 1);
2589 }
2590 }
2591
2592 static void
registry_handle_global_remove(void * data,struct wl_registry * registry,uint32_t name)2593 registry_handle_global_remove(void *data, struct wl_registry *registry,
2594 uint32_t name)
2595 {
2596 struct wayland_backend *b = data;
2597 struct wayland_parent_output *output, *next;
2598
2599 wl_list_for_each_safe(output, next, &b->parent.output_list, link)
2600 if (output->id == name)
2601 wayland_parent_output_destroy(output);
2602 }
2603
2604 static const struct wl_registry_listener registry_listener = {
2605 registry_handle_global,
2606 registry_handle_global_remove
2607 };
2608
2609 static int
wayland_backend_handle_event(int fd,uint32_t mask,void * data)2610 wayland_backend_handle_event(int fd, uint32_t mask, void *data)
2611 {
2612 struct wayland_backend *b = data;
2613 int count = 0;
2614
2615 if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
2616 weston_compositor_exit(b->compositor);
2617 return 0;
2618 }
2619
2620 if (mask & WL_EVENT_READABLE)
2621 count = wl_display_dispatch(b->parent.wl_display);
2622 if (mask & WL_EVENT_WRITABLE)
2623 wl_display_flush(b->parent.wl_display);
2624
2625 if (mask == 0) {
2626 count = wl_display_dispatch_pending(b->parent.wl_display);
2627 wl_display_flush(b->parent.wl_display);
2628 }
2629
2630 return count;
2631 }
2632
2633 static void
wayland_destroy(struct weston_compositor * ec)2634 wayland_destroy(struct weston_compositor *ec)
2635 {
2636 struct wayland_backend *b = to_wayland_backend(ec);
2637 struct weston_head *base, *next;
2638
2639 wl_event_source_remove(b->parent.wl_source);
2640
2641 weston_compositor_shutdown(ec);
2642
2643 wl_list_for_each_safe(base, next, &ec->head_list, compositor_link)
2644 wayland_head_destroy(to_wayland_head(base));
2645
2646 if (b->parent.shm)
2647 wl_shm_destroy(b->parent.shm);
2648
2649 if (b->parent.xdg_wm_base)
2650 xdg_wm_base_destroy(b->parent.xdg_wm_base);
2651
2652 if (b->parent.shell)
2653 wl_shell_destroy(b->parent.shell);
2654
2655 if (b->parent.fshell)
2656 zwp_fullscreen_shell_v1_release(b->parent.fshell);
2657
2658 if (b->parent.compositor)
2659 wl_compositor_destroy(b->parent.compositor);
2660
2661 if (b->theme)
2662 theme_destroy(b->theme);
2663
2664 if (b->frame_device)
2665 cairo_device_destroy(b->frame_device);
2666
2667 wl_cursor_theme_destroy(b->cursor_theme);
2668
2669 wl_registry_destroy(b->parent.registry);
2670 wl_display_flush(b->parent.wl_display);
2671 wl_display_disconnect(b->parent.wl_display);
2672
2673 free(b);
2674 }
2675
2676 static const char *left_ptrs[] = {
2677 "left_ptr",
2678 "default",
2679 "top_left_arrow",
2680 "left-arrow"
2681 };
2682
2683 static void
create_cursor(struct wayland_backend * b,struct weston_wayland_backend_config * config)2684 create_cursor(struct wayland_backend *b,
2685 struct weston_wayland_backend_config *config)
2686 {
2687 unsigned int i;
2688
2689 b->cursor_theme = wl_cursor_theme_load(config->cursor_theme,
2690 config->cursor_size,
2691 b->parent.shm);
2692 if (!b->cursor_theme) {
2693 fprintf(stderr, "could not load cursor theme\n");
2694 return;
2695 }
2696
2697 b->cursor = NULL;
2698 for (i = 0; !b->cursor && i < ARRAY_LENGTH(left_ptrs); ++i)
2699 b->cursor = wl_cursor_theme_get_cursor(b->cursor_theme,
2700 left_ptrs[i]);
2701 if (!b->cursor) {
2702 fprintf(stderr, "could not load left cursor\n");
2703 return;
2704 }
2705 }
2706
2707 static void
fullscreen_binding(struct weston_keyboard * keyboard,const struct timespec * time,uint32_t key,void * data)2708 fullscreen_binding(struct weston_keyboard *keyboard,
2709 const struct timespec *time, uint32_t key, void *data)
2710 {
2711 struct wayland_backend *b = data;
2712 struct wayland_input *input = NULL;
2713
2714 wl_list_for_each(input, &b->input_list, link)
2715 if (&input->base == keyboard->seat)
2716 break;
2717
2718 if (!input || !input->output)
2719 return;
2720
2721 if (input->output->frame)
2722 wayland_output_set_fullscreen(input->output, 0, 0, NULL);
2723 else
2724 wayland_output_set_windowed(input->output);
2725
2726 weston_output_schedule_repaint(&input->output->base);
2727 }
2728
2729 static struct wayland_backend *
wayland_backend_create(struct weston_compositor * compositor,struct weston_wayland_backend_config * new_config)2730 wayland_backend_create(struct weston_compositor *compositor,
2731 struct weston_wayland_backend_config *new_config)
2732 {
2733 struct wayland_backend *b;
2734 struct wl_event_loop *loop;
2735 int fd;
2736
2737 b = zalloc(sizeof *b);
2738 if (b == NULL)
2739 return NULL;
2740
2741 b->compositor = compositor;
2742 compositor->backend = &b->base;
2743
2744 if (weston_compositor_set_presentation_clock_software(compositor) < 0)
2745 goto err_compositor;
2746
2747 b->parent.wl_display = wl_display_connect(new_config->display_name);
2748 if (b->parent.wl_display == NULL) {
2749 weston_log("Error: Failed to connect to parent Wayland compositor: %s\n",
2750 strerror(errno));
2751 weston_log_continue(STAMP_SPACE "display option: %s, WAYLAND_DISPLAY=%s\n",
2752 new_config->display_name ?: "(none)",
2753 getenv("WAYLAND_DISPLAY") ?: "(not set)");
2754 goto err_compositor;
2755 }
2756
2757 wl_list_init(&b->parent.output_list);
2758 wl_list_init(&b->input_list);
2759 b->parent.registry = wl_display_get_registry(b->parent.wl_display);
2760 wl_registry_add_listener(b->parent.registry, ®istry_listener, b);
2761 wl_display_roundtrip(b->parent.wl_display);
2762
2763 create_cursor(b, new_config);
2764
2765 #ifdef ENABLE_EGL
2766 b->use_pixman = new_config->use_pixman;
2767 #else
2768 b->use_pixman = true;
2769 #endif
2770 b->fullscreen = new_config->fullscreen;
2771
2772 if (!b->use_pixman) {
2773 gl_renderer = weston_load_module("gl-renderer.so",
2774 "gl_renderer_interface");
2775 if (!gl_renderer)
2776 b->use_pixman = true;
2777 }
2778
2779 if (!b->use_pixman) {
2780 const struct gl_renderer_display_options options = {
2781 .egl_platform = EGL_PLATFORM_WAYLAND_KHR,
2782 .egl_native_display = b->parent.wl_display,
2783 .egl_surface_type = EGL_WINDOW_BIT,
2784 .drm_formats = wayland_formats,
2785 .drm_formats_count = ARRAY_LENGTH(wayland_formats),
2786 };
2787 if (gl_renderer->display_create(compositor, &options) < 0) {
2788 weston_log("Failed to initialize the GL renderer; "
2789 "falling back to pixman.\n");
2790 b->use_pixman = true;
2791 }
2792 }
2793
2794 if (b->use_pixman) {
2795 if (pixman_renderer_init(compositor) < 0) {
2796 weston_log("Failed to initialize pixman renderer\n");
2797 goto err_display;
2798 }
2799 }
2800
2801 b->base.destroy = wayland_destroy;
2802 b->base.create_output = wayland_output_create;
2803
2804 loop = wl_display_get_event_loop(compositor->wl_display);
2805
2806 fd = wl_display_get_fd(b->parent.wl_display);
2807 b->parent.wl_source =
2808 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
2809 wayland_backend_handle_event, b);
2810 if (b->parent.wl_source == NULL)
2811 goto err_display;
2812
2813 wl_event_source_check(b->parent.wl_source);
2814
2815 if (compositor->renderer->import_dmabuf) {
2816 if (linux_dmabuf_setup(compositor) < 0)
2817 weston_log("Error: initializing dmabuf "
2818 "support failed.\n");
2819 }
2820
2821 return b;
2822 err_display:
2823 wl_display_disconnect(b->parent.wl_display);
2824 err_compositor:
2825 weston_compositor_shutdown(compositor);
2826 free(b);
2827 return NULL;
2828 }
2829
2830 static void
wayland_backend_destroy(struct wayland_backend * b)2831 wayland_backend_destroy(struct wayland_backend *b)
2832 {
2833 wl_display_disconnect(b->parent.wl_display);
2834
2835 if (b->theme)
2836 theme_destroy(b->theme);
2837 if (b->frame_device)
2838 cairo_device_destroy(b->frame_device);
2839 wl_cursor_theme_destroy(b->cursor_theme);
2840
2841 weston_compositor_shutdown(b->compositor);
2842 free(b);
2843 }
2844
2845 static const struct weston_windowed_output_api windowed_api = {
2846 wayland_output_set_size,
2847 wayland_head_create_windowed,
2848 };
2849
2850 static void
config_init_to_defaults(struct weston_wayland_backend_config * config)2851 config_init_to_defaults(struct weston_wayland_backend_config *config)
2852 {
2853 }
2854
2855 WL_EXPORT int
weston_backend_init(struct weston_compositor * compositor,struct weston_backend_config * config_base)2856 weston_backend_init(struct weston_compositor *compositor,
2857 struct weston_backend_config *config_base)
2858 {
2859 struct wayland_backend *b;
2860 struct wayland_parent_output *poutput;
2861 struct weston_wayland_backend_config new_config;
2862 int ret;
2863
2864 if (config_base == NULL ||
2865 config_base->struct_version != WESTON_WAYLAND_BACKEND_CONFIG_VERSION ||
2866 config_base->struct_size > sizeof(struct weston_wayland_backend_config)) {
2867 weston_log("wayland backend config structure is invalid\n");
2868 return -1;
2869 }
2870
2871 config_init_to_defaults(&new_config);
2872 memcpy(&new_config, config_base, config_base->struct_size);
2873
2874 b = wayland_backend_create(compositor, &new_config);
2875
2876 if (!b)
2877 return -1;
2878
2879 if (new_config.sprawl || b->parent.fshell) {
2880 b->sprawl_across_outputs = true;
2881 wl_display_roundtrip(b->parent.wl_display);
2882
2883 wl_list_for_each(poutput, &b->parent.output_list, link)
2884 wayland_head_create_for_parent_output(compositor, poutput);
2885
2886 return 0;
2887 }
2888
2889 if (new_config.fullscreen) {
2890 if (!wayland_head_create(compositor, "wayland-fullscreen")) {
2891 weston_log("Unable to create a fullscreen head.\n");
2892 goto err_outputs;
2893 }
2894
2895 return 0;
2896 }
2897
2898 ret = weston_plugin_api_register(compositor, WESTON_WINDOWED_OUTPUT_API_NAME,
2899 &windowed_api, sizeof(windowed_api));
2900
2901 if (ret < 0) {
2902 weston_log("Failed to register output API.\n");
2903 wayland_backend_destroy(b);
2904 return -1;
2905 }
2906
2907 weston_compositor_add_key_binding(compositor, KEY_F,
2908 MODIFIER_CTRL | MODIFIER_ALT,
2909 fullscreen_binding, b);
2910 return 0;
2911
2912 err_outputs:
2913 wayland_backend_destroy(b);
2914 return -1;
2915 }
2916