blob: 33910316c2bcc08b2f00b325b244978ec205f0ec [file] [log] [blame]
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001/*
Kristian Høgsberg96aa7da2011-09-15 15:43:14 -04002 * Copyright © 2010-2011 Benjamin Franzke
Jason Ekstrandff2fd462013-10-27 22:24:58 -05003 * Copyright © 2013 Jason Ekstrand
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01004 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07005 * 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:
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010012 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070013 * 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.
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010025 */
26
Daniel Stonec228e232013-05-22 18:03:19 +030027#include "config.h"
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010028
Armin Krezović174448a2016-09-30 14:11:09 +020029#include <assert.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010030#include <stddef.h>
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030031#include <stdint.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010032#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <fcntl.h>
36#include <unistd.h>
Daniel Stoneb7452fe2012-06-01 12:14:06 +010037#include <sys/mman.h>
Jason Ekstrand5ea04802013-11-07 20:13:33 -060038#include <linux/input.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010039
Benjamin Franzkebe014562011-02-18 17:04:24 +010040#include <wayland-client.h>
Jason Ekstrand7744f712013-10-27 22:24:55 -050041#include <wayland-cursor.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010042
Armin Krezovićb08e1a52016-12-09 22:58:27 +010043#ifdef ENABLE_EGL
44#include <wayland-egl.h>
45#endif
46
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010047#include "compositor.h"
Benoit Gschwind639322a2016-04-28 20:33:15 +020048#include "compositor-wayland.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010049#include "gl-renderer.h"
Vincent Abriouc9506672016-10-05 16:14:07 +020050#include "weston-egl-ext.h"
Jason Ekstrandff2fd462013-10-27 22:24:58 -050051#include "pixman-renderer.h"
Jon Cruz35b2eaa2015-06-15 15:37:08 -070052#include "shared/helpers.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070053#include "shared/image-loader.h"
54#include "shared/os-compatibility.h"
55#include "shared/cairo-util.h"
Jonas Ådahl496adb32015-11-17 16:00:27 +080056#include "fullscreen-shell-unstable-v1-client-protocol.h"
Armin Krezović34476192016-11-21 18:42:42 +010057#include "xdg-shell-unstable-v6-client-protocol.h"
Pekka Paalanenb00c79b2016-02-18 16:53:27 +020058#include "presentation-time-server-protocol.h"
Emmanuel Gil Peyrotc59f18e2015-09-25 11:58:40 +020059#include "linux-dmabuf.h"
Armin Krezović174448a2016-09-30 14:11:09 +020060#include "windowed-output-api.h"
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010061
Jason Ekstrand48ce4212013-10-27 22:25:02 -050062#define WINDOW_TITLE "Weston Compositor"
63
Giulio Camuffo954f1832014-10-11 18:27:30 +030064struct wayland_backend {
65 struct weston_backend base;
66 struct weston_compositor *compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010067
68 struct {
Kristian Høgsberg362b6722012-06-18 15:13:51 -040069 struct wl_display *wl_display;
Kristian Høgsbergfa80e112012-10-10 21:34:26 -040070 struct wl_registry *registry;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010071 struct wl_compositor *compositor;
72 struct wl_shell *shell;
Armin Krezović34476192016-11-21 18:42:42 +010073 struct zxdg_shell_v6 *xdg_shell;
Jonas Ådahl496adb32015-11-17 16:00:27 +080074 struct zwp_fullscreen_shell_v1 *fshell;
Jonas Ådahle5a12252013-04-05 23:07:11 +020075 struct wl_shm *shm;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010076
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -050077 struct wl_list output_list;
78
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010079 struct wl_event_source *wl_source;
80 uint32_t event_mask;
81 } parent;
82
Armin Krezović7e71b872016-10-09 17:30:22 +020083 bool use_pixman;
Armin Krezović7f1c0b82016-10-09 17:30:23 +020084 bool sprawl_across_outputs;
Armin Krezović20450162016-10-13 12:01:43 +020085 bool fullscreen;
Jason Ekstrandff2fd462013-10-27 22:24:58 -050086
Jason Ekstrand7744f712013-10-27 22:24:55 -050087 struct theme *theme;
88 cairo_device_t *frame_device;
89 struct wl_cursor_theme *cursor_theme;
90 struct wl_cursor *cursor;
Kristian Høgsberg546a8122012-02-01 07:45:51 -050091
Jason Ekstrand06ced802013-11-07 20:13:29 -060092 struct wl_list input_list;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010093};
94
95struct wayland_output {
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -050096 struct weston_output base;
97
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010098 struct {
Armin Krezović2d321e32016-10-09 17:30:25 +020099 bool draw_initial_frame;
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500100 struct wl_surface *surface;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500101
102 struct wl_output *output;
103 uint32_t global_id;
104
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500105 struct wl_shell_surface *shell_surface;
Armin Krezović34476192016-11-21 18:42:42 +0100106 struct zxdg_surface_v6 *xdg_surface;
107 struct zxdg_toplevel_v6 *xdg_toplevel;
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600108 int configure_width, configure_height;
Armin Krezović34476192016-11-21 18:42:42 +0100109 bool wait_for_configure;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100110 } parent;
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500111
Jason Ekstrand7744f712013-10-27 22:24:55 -0500112 int keyboard_count;
113
Sergi Granell2dcbb8d2017-03-24 20:48:01 +0100114 char *title;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500115 struct frame *frame;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500116
Jason Ekstrand7744f712013-10-27 22:24:55 -0500117 struct {
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500118 struct wl_egl_window *egl_window;
119 struct {
120 cairo_surface_t *top;
121 cairo_surface_t *left;
122 cairo_surface_t *right;
123 cairo_surface_t *bottom;
124 } border;
125 } gl;
126
127 struct {
128 struct wl_list buffers;
129 struct wl_list free_buffers;
130 } shm;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500131
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500132 struct weston_mode mode;
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500133 uint32_t scale;
Dima Ryazanov89c2f632016-11-24 05:13:12 -0800134
135 struct wl_callback *frame_cb;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100136};
137
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500138struct wayland_parent_output {
Pekka Paalanenb07de932017-10-19 12:03:06 +0300139 struct wayland_backend *backend; /**< convenience */
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500140 struct wayland_output *output;
141 struct wl_list link;
142
143 struct wl_output *global;
144 uint32_t id;
145
146 struct {
147 char *make;
148 char *model;
149 int32_t width, height;
150 uint32_t subpixel;
151 } physical;
152
153 int32_t x, y;
154 uint32_t transform;
155 uint32_t scale;
156
Pekka Paalanenb07de932017-10-19 12:03:06 +0300157 struct wl_callback *sync_cb; /**< wl_output < 2 done replacement */
158
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500159 struct wl_list mode_list;
160 struct weston_mode *preferred_mode;
161 struct weston_mode *current_mode;
162};
163
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500164struct wayland_shm_buffer {
165 struct wayland_output *output;
166 struct wl_list link;
167 struct wl_list free_link;
168
169 struct wl_buffer *buffer;
170 void *data;
171 size_t size;
172 pixman_region32_t damage;
173 int frame_damaged;
174
175 pixman_image_t *pm_image;
176 cairo_surface_t *c_surface;
177};
178
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100179struct wayland_input {
Kristian Høgsberg7af7ced2012-08-10 10:01:33 -0400180 struct weston_seat base;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300181 struct wayland_backend *backend;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100182 struct wl_list link;
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500183
184 struct {
185 struct wl_seat *seat;
186 struct wl_pointer *pointer;
187 struct wl_keyboard *keyboard;
188 struct wl_touch *touch;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500189
190 struct {
191 struct wl_surface *surface;
192 int32_t hx, hy;
193 } cursor;
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500194 } parent;
195
Jason Ekstrandb7d9f2e2014-04-02 19:53:57 -0500196 enum weston_key_state_update keyboard_state_update;
Daniel Stone50692802012-06-22 13:21:41 +0100197 uint32_t key_serial;
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400198 uint32_t enter_serial;
Derek Foreman748c6952015-11-06 15:56:10 -0600199 uint32_t touch_points;
200 bool touch_active;
Derek Foreman4bcc54d2015-11-06 15:56:06 -0600201 bool has_focus;
Derek Foremancfce7d02015-11-06 15:56:08 -0600202 int seat_version;
Derek Foreman4bcc54d2015-11-06 15:56:06 -0600203
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400204 struct wayland_output *output;
Derek Foreman748c6952015-11-06 15:56:10 -0600205 struct wayland_output *touch_focus;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500206 struct wayland_output *keyboard_focus;
Peter Hutterer87743e92016-01-18 16:38:22 +1000207
208 struct weston_pointer_axis_event vert, horiz;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100209};
210
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300211struct gl_renderer_interface *gl_renderer;
212
Armin Krezović938dc522016-08-01 19:17:57 +0200213static inline struct wayland_output *
214to_wayland_output(struct weston_output *base)
215{
216 return container_of(base, struct wayland_output, base);
217}
218
219static inline struct wayland_backend *
220to_wayland_backend(struct weston_compositor *base)
221{
222 return container_of(base->backend, struct wayland_backend, base);
223}
224
Kristian Høgsberg546a8122012-02-01 07:45:51 -0500225static void
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500226wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
227{
228 cairo_surface_destroy(buffer->c_surface);
229 pixman_image_unref(buffer->pm_image);
230
231 wl_buffer_destroy(buffer->buffer);
232 munmap(buffer->data, buffer->size);
233
234 pixman_region32_fini(&buffer->damage);
235
236 wl_list_remove(&buffer->link);
237 wl_list_remove(&buffer->free_link);
238 free(buffer);
239}
240
241static void
242buffer_release(void *data, struct wl_buffer *buffer)
243{
244 struct wayland_shm_buffer *sb = data;
245
246 if (sb->output) {
247 wl_list_insert(&sb->output->shm.free_buffers, &sb->free_link);
248 } else {
249 wayland_shm_buffer_destroy(sb);
250 }
251}
252
253static const struct wl_buffer_listener buffer_listener = {
254 buffer_release
255};
256
257static struct wayland_shm_buffer *
258wayland_output_get_shm_buffer(struct wayland_output *output)
259{
Giulio Camuffo954f1832014-10-11 18:27:30 +0300260 struct wayland_backend *b =
Armin Krezović938dc522016-08-01 19:17:57 +0200261 to_wayland_backend(output->base.compositor);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300262 struct wl_shm *shm = b->parent.shm;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500263 struct wayland_shm_buffer *sb;
264
265 struct wl_shm_pool *pool;
266 int width, height, stride;
267 int32_t fx, fy;
268 int fd;
269 unsigned char *data;
270
271 if (!wl_list_empty(&output->shm.free_buffers)) {
272 sb = container_of(output->shm.free_buffers.next,
273 struct wayland_shm_buffer, free_link);
274 wl_list_remove(&sb->free_link);
275 wl_list_init(&sb->free_link);
276
277 return sb;
278 }
279
280 if (output->frame) {
281 width = frame_width(output->frame);
282 height = frame_height(output->frame);
283 } else {
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500284 width = output->base.current_mode->width;
285 height = output->base.current_mode->height;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500286 }
287
288 stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
289
290 fd = os_create_anonymous_file(height * stride);
291 if (fd < 0) {
Bryce W. Harringtona0935022014-03-21 05:54:02 +0000292 weston_log("could not create an anonymous file buffer: %m\n");
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500293 return NULL;
294 }
295
296 data = mmap(NULL, height * stride, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
297 if (data == MAP_FAILED) {
Bryce W. Harringtona0935022014-03-21 05:54:02 +0000298 weston_log("could not mmap %d memory for data: %m\n", height * stride);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500299 close(fd);
300 return NULL;
301 }
302
303 sb = zalloc(sizeof *sb);
Bryce W. Harringtonbfd74f42014-04-21 23:51:02 +0000304 if (sb == NULL) {
Thierry Reding6ac60c12014-05-27 09:08:29 +0200305 weston_log("could not zalloc %zu memory for sb: %m\n", sizeof *sb);
Bryce W. Harringtonbfd74f42014-04-21 23:51:02 +0000306 close(fd);
Raúl Peñacobafec723e2017-03-29 22:23:07 +0200307 munmap(data, height * stride);
Bryce W. Harringtonbfd74f42014-04-21 23:51:02 +0000308 return NULL;
309 }
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500310
311 sb->output = output;
312 wl_list_init(&sb->free_link);
313 wl_list_insert(&output->shm.buffers, &sb->link);
314
315 pixman_region32_init_rect(&sb->damage, 0, 0,
316 output->base.width, output->base.height);
317 sb->frame_damaged = 1;
318
319 sb->data = data;
320 sb->size = height * stride;
321
322 pool = wl_shm_create_pool(shm, fd, sb->size);
323
324 sb->buffer = wl_shm_pool_create_buffer(pool, 0,
325 width, height,
326 stride,
327 WL_SHM_FORMAT_ARGB8888);
328 wl_buffer_add_listener(sb->buffer, &buffer_listener, sb);
329 wl_shm_pool_destroy(pool);
330 close(fd);
331
332 memset(data, 0, sb->size);
333
334 sb->c_surface =
335 cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32,
336 width, height, stride);
337
338 fx = 0;
339 fy = 0;
340 if (output->frame)
341 frame_interior(output->frame, &fx, &fy, 0, 0);
342 sb->pm_image =
343 pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height,
344 (uint32_t *)(data + fy * stride) + fx,
345 stride);
346
347 return sb;
348}
349
350static void
Kristian Høgsbergcdd61d02012-02-07 09:56:15 -0500351frame_done(void *data, struct wl_callback *callback, uint32_t time)
Kristian Høgsberg33418202011-08-16 23:01:28 -0400352{
Dima Ryazanov89c2f632016-11-24 05:13:12 -0800353 struct wayland_output *output = data;
Pekka Paalanenb5eedad2014-09-23 22:08:45 -0400354 struct timespec ts;
Kristian Høgsberg33418202011-08-16 23:01:28 -0400355
Dima Ryazanov89c2f632016-11-24 05:13:12 -0800356 assert(callback == output->frame_cb);
Kristian Høgsbergcdd61d02012-02-07 09:56:15 -0500357 wl_callback_destroy(callback);
Dima Ryazanov89c2f632016-11-24 05:13:12 -0800358 output->frame_cb = NULL;
Pekka Paalanenb5eedad2014-09-23 22:08:45 -0400359
360 /* XXX: use the presentation extension for proper timings */
Pekka Paalanen04f8a9b2015-04-02 16:26:06 +0300361
362 /*
363 * This is the fallback case, where Presentation extension is not
364 * available from the parent compositor. We do not know the base for
365 * 'time', so we cannot feed it to finish_frame(). Do the only thing
366 * we can, and pretend finish_frame time is when we process this
367 * event.
368 */
Dima Ryazanov89c2f632016-11-24 05:13:12 -0800369 weston_compositor_read_presentation_clock(output->base.compositor, &ts);
370 weston_output_finish_frame(&output->base, &ts, 0);
Kristian Høgsberg33418202011-08-16 23:01:28 -0400371}
372
373static const struct wl_callback_listener frame_listener = {
374 frame_done
375};
376
Kristian Høgsberg06cf6b02012-01-25 23:47:45 -0500377static void
Jonas Ådahle5a12252013-04-05 23:07:11 +0200378draw_initial_frame(struct wayland_output *output)
379{
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500380 struct wayland_shm_buffer *sb;
Jonas Ådahle5a12252013-04-05 23:07:11 +0200381
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500382 sb = wayland_output_get_shm_buffer(output);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200383
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500384 /* If we are rendering with GL, then orphan it so that it gets
385 * destroyed immediately */
386 if (output->gl.egl_window)
387 sb->output = NULL;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500388
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500389 wl_surface_attach(output->parent.surface, sb->buffer, 0, 0);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500390 wl_surface_damage(output->parent.surface, 0, 0,
391 output->base.current_mode->width,
392 output->base.current_mode->height);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200393}
394
Armin Krezovićb08e1a52016-12-09 22:58:27 +0100395#ifdef ENABLE_EGL
Jonas Ådahle5a12252013-04-05 23:07:11 +0200396static void
Jason Ekstrand7744f712013-10-27 22:24:55 -0500397wayland_output_update_gl_border(struct wayland_output *output)
398{
399 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
400 cairo_t *cr;
401
402 if (!output->frame)
403 return;
404 if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
405 return;
406
407 fwidth = frame_width(output->frame);
408 fheight = frame_height(output->frame);
409 frame_interior(output->frame, &ix, &iy, &iwidth, &iheight);
410
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500411 if (!output->gl.border.top)
412 output->gl.border.top =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500413 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
414 fwidth, iy);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500415 cr = cairo_create(output->gl.border.top);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500416 frame_repaint(output->frame, cr);
417 cairo_destroy(cr);
418 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_TOP,
419 fwidth, iy,
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500420 cairo_image_surface_get_stride(output->gl.border.top) / 4,
421 cairo_image_surface_get_data(output->gl.border.top));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500422
423
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500424 if (!output->gl.border.left)
425 output->gl.border.left =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500426 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
427 ix, 1);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500428 cr = cairo_create(output->gl.border.left);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500429 cairo_translate(cr, 0, -iy);
430 frame_repaint(output->frame, cr);
431 cairo_destroy(cr);
432 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_LEFT,
433 ix, 1,
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500434 cairo_image_surface_get_stride(output->gl.border.left) / 4,
435 cairo_image_surface_get_data(output->gl.border.left));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500436
437
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500438 if (!output->gl.border.right)
439 output->gl.border.right =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500440 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
441 fwidth - (ix + iwidth), 1);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500442 cr = cairo_create(output->gl.border.right);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500443 cairo_translate(cr, -(iwidth + ix), -iy);
444 frame_repaint(output->frame, cr);
445 cairo_destroy(cr);
446 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_RIGHT,
447 fwidth - (ix + iwidth), 1,
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500448 cairo_image_surface_get_stride(output->gl.border.right) / 4,
449 cairo_image_surface_get_data(output->gl.border.right));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500450
451
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500452 if (!output->gl.border.bottom)
453 output->gl.border.bottom =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500454 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
455 fwidth, fheight - (iy + iheight));
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500456 cr = cairo_create(output->gl.border.bottom);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500457 cairo_translate(cr, 0, -(iy + iheight));
458 frame_repaint(output->frame, cr);
459 cairo_destroy(cr);
460 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_BOTTOM,
461 fwidth, fheight - (iy + iheight),
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500462 cairo_image_surface_get_stride(output->gl.border.bottom) / 4,
463 cairo_image_surface_get_data(output->gl.border.bottom));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500464}
Armin Krezovićb08e1a52016-12-09 22:58:27 +0100465#endif
Jason Ekstrand7744f712013-10-27 22:24:55 -0500466
467static void
Jonas Ådahle5a12252013-04-05 23:07:11 +0200468wayland_output_start_repaint_loop(struct weston_output *output_base)
469{
Armin Krezović938dc522016-08-01 19:17:57 +0200470 struct wayland_output *output = to_wayland_output(output_base);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300471 struct wayland_backend *wb =
Armin Krezović938dc522016-08-01 19:17:57 +0200472 to_wayland_backend(output->base.compositor);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200473
474 /* If this is the initial frame, we need to attach a buffer so that
475 * the compositor can map the surface and include it in its render
476 * loop. If the surface doesn't end up in the render loop, the frame
477 * callback won't be invoked. The buffer is transparent and of the
478 * same size as the future real output buffer. */
479 if (output->parent.draw_initial_frame) {
Armin Krezović2d321e32016-10-09 17:30:25 +0200480 output->parent.draw_initial_frame = false;
Jonas Ådahle5a12252013-04-05 23:07:11 +0200481
482 draw_initial_frame(output);
483 }
484
Dima Ryazanov89c2f632016-11-24 05:13:12 -0800485 output->frame_cb = wl_surface_frame(output->parent.surface);
486 wl_callback_add_listener(output->frame_cb, &frame_listener, output);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200487 wl_surface_commit(output->parent.surface);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300488 wl_display_flush(wb->parent.wl_display);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200489}
490
Armin Krezovićb08e1a52016-12-09 22:58:27 +0100491#ifdef ENABLE_EGL
David Herrmann1edf44c2013-10-22 17:11:26 +0200492static int
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500493wayland_output_repaint_gl(struct weston_output *output_base,
Daniel Stoneb1f166d2017-03-01 11:34:10 +0000494 pixman_region32_t *damage,
495 void *repaint_data)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400496{
Armin Krezović938dc522016-08-01 19:17:57 +0200497 struct wayland_output *output = to_wayland_output(output_base);
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400498 struct weston_compositor *ec = output->base.compositor;
Scott Moreau062be7e2012-04-20 13:37:33 -0600499
Dima Ryazanov89c2f632016-11-24 05:13:12 -0800500 output->frame_cb = wl_surface_frame(output->parent.surface);
501 wl_callback_add_listener(output->frame_cb, &frame_listener, output);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100502
Jason Ekstrand7744f712013-10-27 22:24:55 -0500503 wayland_output_update_gl_border(output);
504
Pekka Paalanenbc106382012-10-10 12:49:31 +0300505 ec->renderer->repaint_output(&output->base, damage);
Ander Conselvan de Oliveira0a887722012-11-22 15:57:00 +0200506
507 pixman_region32_subtract(&ec->primary_plane.damage,
508 &ec->primary_plane.damage, damage);
David Herrmann1edf44c2013-10-22 17:11:26 +0200509 return 0;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100510}
Armin Krezovićb08e1a52016-12-09 22:58:27 +0100511#endif
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100512
Matt Roper361d2ad2011-08-29 13:52:23 -0700513static void
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500514wayland_output_update_shm_border(struct wayland_shm_buffer *buffer)
515{
516 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
517 cairo_t *cr;
518
519 if (!buffer->output->frame || !buffer->frame_damaged)
520 return;
521
522 cr = cairo_create(buffer->c_surface);
523
524 frame_interior(buffer->output->frame, &ix, &iy, &iwidth, &iheight);
525 fwidth = frame_width(buffer->output->frame);
526 fheight = frame_height(buffer->output->frame);
527
528 /* Set the clip so we don't unnecisaraly damage the surface */
529 cairo_move_to(cr, ix, iy);
530 cairo_rel_line_to(cr, iwidth, 0);
531 cairo_rel_line_to(cr, 0, iheight);
532 cairo_rel_line_to(cr, -iwidth, 0);
533 cairo_line_to(cr, ix, iy);
534 cairo_line_to(cr, 0, iy);
535 cairo_line_to(cr, 0, fheight);
536 cairo_line_to(cr, fwidth, fheight);
537 cairo_line_to(cr, fwidth, 0);
538 cairo_line_to(cr, 0, 0);
539 cairo_line_to(cr, 0, iy);
540 cairo_close_path(cr);
541 cairo_clip(cr);
542
543 /* Draw using a pattern so that the final result gets clipped */
544 cairo_push_group(cr);
545 frame_repaint(buffer->output->frame, cr);
546 cairo_pop_group_to_source(cr);
547 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
548 cairo_paint(cr);
549
550 cairo_destroy(cr);
551}
552
553static void
554wayland_shm_buffer_attach(struct wayland_shm_buffer *sb)
555{
556 pixman_region32_t damage;
557 pixman_box32_t *rects;
558 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
559 int i, n;
560
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500561 pixman_region32_init(&damage);
562 weston_transformed_region(sb->output->base.width,
563 sb->output->base.height,
564 sb->output->base.transform,
565 sb->output->base.current_scale,
566 &sb->damage, &damage);
567
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500568 if (sb->output->frame) {
569 frame_interior(sb->output->frame, &ix, &iy, &iwidth, &iheight);
570 fwidth = frame_width(sb->output->frame);
571 fheight = frame_height(sb->output->frame);
572
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500573 pixman_region32_translate(&damage, ix, iy);
574
575 if (sb->frame_damaged) {
576 pixman_region32_union_rect(&damage, &damage,
577 0, 0, fwidth, iy);
578 pixman_region32_union_rect(&damage, &damage,
579 0, iy, ix, iheight);
580 pixman_region32_union_rect(&damage, &damage,
581 ix + iwidth, iy,
582 fwidth - (ix + iwidth), iheight);
583 pixman_region32_union_rect(&damage, &damage,
584 0, iy + iheight,
585 fwidth, fheight - (iy + iheight));
586 }
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500587 }
588
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500589 rects = pixman_region32_rectangles(&damage, &n);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500590 wl_surface_attach(sb->output->parent.surface, sb->buffer, 0, 0);
591 for (i = 0; i < n; ++i)
592 wl_surface_damage(sb->output->parent.surface, rects[i].x1,
593 rects[i].y1, rects[i].x2 - rects[i].x1,
594 rects[i].y2 - rects[i].y1);
595
596 if (sb->output->frame)
597 pixman_region32_fini(&damage);
598}
599
600static int
601wayland_output_repaint_pixman(struct weston_output *output_base,
Daniel Stoneb1f166d2017-03-01 11:34:10 +0000602 pixman_region32_t *damage,
603 void *repaint_data)
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500604{
Armin Krezović938dc522016-08-01 19:17:57 +0200605 struct wayland_output *output = to_wayland_output(output_base);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300606 struct wayland_backend *b =
Armin Krezović938dc522016-08-01 19:17:57 +0200607 to_wayland_backend(output->base.compositor);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500608 struct wayland_shm_buffer *sb;
609
610 if (output->frame) {
611 if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
612 wl_list_for_each(sb, &output->shm.buffers, link)
613 sb->frame_damaged = 1;
614 }
615
616 wl_list_for_each(sb, &output->shm.buffers, link)
617 pixman_region32_union(&sb->damage, &sb->damage, damage);
618
619 sb = wayland_output_get_shm_buffer(output);
620
621 wayland_output_update_shm_border(sb);
622 pixman_renderer_output_set_buffer(output_base, sb->pm_image);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300623 b->compositor->renderer->repaint_output(output_base, &sb->damage);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500624
625 wayland_shm_buffer_attach(sb);
626
Daniel Stone21fac602016-11-28 16:05:35 +0000627 output->frame_cb = wl_surface_frame(output->parent.surface);
628 wl_callback_add_listener(output->frame_cb, &frame_listener, output);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500629 wl_surface_commit(output->parent.surface);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300630 wl_display_flush(b->parent.wl_display);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500631
632 pixman_region32_fini(&sb->damage);
633 pixman_region32_init(&sb->damage);
634 sb->frame_damaged = 0;
635
Giulio Camuffo954f1832014-10-11 18:27:30 +0300636 pixman_region32_subtract(&b->compositor->primary_plane.damage,
637 &b->compositor->primary_plane.damage, damage);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500638 return 0;
639}
640
641static void
Armin Krezović174448a2016-09-30 14:11:09 +0200642wayland_backend_destroy_output_surface(struct wayland_output *output)
Matt Roper361d2ad2011-08-29 13:52:23 -0700643{
Armin Krezović34476192016-11-21 18:42:42 +0100644 if (output->parent.xdg_toplevel)
645 zxdg_toplevel_v6_destroy(output->parent.xdg_toplevel);
646
647 if (output->parent.xdg_surface)
648 zxdg_surface_v6_destroy(output->parent.xdg_surface);
649
Armin Krezović174448a2016-09-30 14:11:09 +0200650 if (output->parent.shell_surface)
651 wl_shell_surface_destroy(output->parent.shell_surface);
652
653 wl_surface_destroy(output->parent.surface);
654}
655
Armin Krezović2e662522016-10-09 17:30:29 +0200656static void
657wayland_output_destroy_shm_buffers(struct wayland_output *output)
658{
659 struct wayland_shm_buffer *buffer, *next;
660
661 /* Throw away any remaining SHM buffers */
662 wl_list_for_each_safe(buffer, next, &output->shm.free_buffers, free_link)
663 wayland_shm_buffer_destroy(buffer);
664 /* These will get thrown away when they get released */
665 wl_list_for_each(buffer, &output->shm.buffers, link)
666 buffer->output = NULL;
667}
668
Armin Krezović174448a2016-09-30 14:11:09 +0200669static int
670wayland_output_disable(struct weston_output *base)
671{
672 struct wayland_output *output = to_wayland_output(base);
673 struct wayland_backend *b = to_wayland_backend(base->compositor);
674
675 if (!output->base.enabled)
676 return 0;
Matt Roper361d2ad2011-08-29 13:52:23 -0700677
Giulio Camuffo954f1832014-10-11 18:27:30 +0300678 if (b->use_pixman) {
Armin Krezović174448a2016-09-30 14:11:09 +0200679 pixman_renderer_output_destroy(&output->base);
Armin Krezovićb08e1a52016-12-09 22:58:27 +0100680#ifdef ENABLE_EGL
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500681 } else {
Armin Krezović174448a2016-09-30 14:11:09 +0200682 gl_renderer->output_destroy(&output->base);
Emmanuel Gil Peyrot85571a32016-09-01 15:19:46 +0100683 wl_egl_window_destroy(output->gl.egl_window);
Armin Krezovićb08e1a52016-12-09 22:58:27 +0100684#endif
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500685 }
John Kåre Alsaker94659272012-11-13 19:10:18 +0100686
Armin Krezović2e662522016-10-09 17:30:29 +0200687 wayland_output_destroy_shm_buffers(output);
688
Armin Krezovićf054d352016-10-09 17:30:27 +0200689 wayland_backend_destroy_output_surface(output);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500690
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600691 if (output->frame)
Jason Ekstrand7744f712013-10-27 22:24:55 -0500692 frame_destroy(output->frame);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600693
694 cairo_surface_destroy(output->gl.border.top);
695 cairo_surface_destroy(output->gl.border.left);
696 cairo_surface_destroy(output->gl.border.right);
697 cairo_surface_destroy(output->gl.border.bottom);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500698
Armin Krezović174448a2016-09-30 14:11:09 +0200699 return 0;
700}
Matt Roper361d2ad2011-08-29 13:52:23 -0700701
Armin Krezović174448a2016-09-30 14:11:09 +0200702static void
703wayland_output_destroy(struct weston_output *base)
704{
705 struct wayland_output *output = to_wayland_output(base);
Armin Krezović174448a2016-09-30 14:11:09 +0200706
707 wayland_output_disable(&output->base);
708
Pekka Paalanenae6d35d2017-08-16 12:07:14 +0300709 weston_output_release(&output->base);
Armin Krezović174448a2016-09-30 14:11:09 +0200710
Dima Ryazanov89c2f632016-11-24 05:13:12 -0800711 if (output->frame_cb)
712 wl_callback_destroy(output->frame_cb);
713
Sergi Granell2dcbb8d2017-03-24 20:48:01 +0100714 free(output->title);
Armin Krezović174448a2016-09-30 14:11:09 +0200715 free(output);
Matt Roper361d2ad2011-08-29 13:52:23 -0700716}
717
Ander Conselvan de Oliveira563c5b82012-06-18 17:36:21 +0300718static const struct wl_shell_surface_listener shell_surface_listener;
719
Armin Krezovićb08e1a52016-12-09 22:58:27 +0100720#ifdef ENABLE_EGL
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200721static int
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500722wayland_output_init_gl_renderer(struct wayland_output *output)
723{
Jason Ekstrand00b84282013-10-27 22:24:59 -0500724 int32_t fwidth = 0, fheight = 0;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500725
726 if (output->frame) {
727 fwidth = frame_width(output->frame);
728 fheight = frame_height(output->frame);
729 } else {
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500730 fwidth = output->base.current_mode->width;
731 fheight = output->base.current_mode->height;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500732 }
733
734 output->gl.egl_window =
735 wl_egl_window_create(output->parent.surface,
736 fwidth, fheight);
737 if (!output->gl.egl_window) {
738 weston_log("failure to create wl_egl_window\n");
739 return -1;
740 }
741
Miguel A. Vicoc095cde2016-05-18 17:43:00 +0200742 if (gl_renderer->output_window_create(&output->base,
743 output->gl.egl_window,
744 output->gl.egl_window,
745 gl_renderer->alpha_attribs,
746 NULL,
747 0) < 0)
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500748 goto cleanup_window;
749
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500750 return 0;
751
752cleanup_window:
753 wl_egl_window_destroy(output->gl.egl_window);
754 return -1;
755}
Armin Krezovićb08e1a52016-12-09 22:58:27 +0100756#endif
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500757
758static int
759wayland_output_init_pixman_renderer(struct wayland_output *output)
760{
761 return pixman_renderer_output_create(&output->base);
762}
763
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600764static void
765wayland_output_resize_surface(struct wayland_output *output)
766{
Giulio Camuffo954f1832014-10-11 18:27:30 +0300767 struct wayland_backend *b =
Armin Krezović938dc522016-08-01 19:17:57 +0200768 to_wayland_backend(output->base.compositor);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600769 int32_t ix, iy, iwidth, iheight;
770 int32_t width, height;
771 struct wl_region *region;
772
773 width = output->base.current_mode->width;
774 height = output->base.current_mode->height;
775
776 if (output->frame) {
777 frame_resize_inside(output->frame, width, height);
778
779 frame_input_rect(output->frame, &ix, &iy, &iwidth, &iheight);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300780 region = wl_compositor_create_region(b->parent.compositor);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600781 wl_region_add(region, ix, iy, iwidth, iheight);
782 wl_surface_set_input_region(output->parent.surface, region);
783 wl_region_destroy(region);
784
Sergi Granelled016bf2017-03-24 23:45:13 +0100785 if (output->parent.xdg_surface) {
786 zxdg_surface_v6_set_window_geometry(output->parent.xdg_surface,
787 ix,
788 iy,
789 iwidth,
790 iheight);
791 }
792
Sergi Granellcafc6522017-09-25 11:57:37 +0200793 frame_opaque_rect(output->frame, &ix, &iy, &iwidth, &iheight);
794 region = wl_compositor_create_region(b->parent.compositor);
795 wl_region_add(region, ix, iy, iwidth, iheight);
796 wl_surface_set_opaque_region(output->parent.surface, region);
797 wl_region_destroy(region);
798
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600799 width = frame_width(output->frame);
800 height = frame_height(output->frame);
801 } else {
Giulio Camuffo954f1832014-10-11 18:27:30 +0300802 region = wl_compositor_create_region(b->parent.compositor);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600803 wl_region_add(region, 0, 0, width, height);
804 wl_surface_set_input_region(output->parent.surface, region);
805 wl_region_destroy(region);
806
Giulio Camuffo954f1832014-10-11 18:27:30 +0300807 region = wl_compositor_create_region(b->parent.compositor);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600808 wl_region_add(region, 0, 0, width, height);
809 wl_surface_set_opaque_region(output->parent.surface, region);
810 wl_region_destroy(region);
Sergi Granelled016bf2017-03-24 23:45:13 +0100811
812 if (output->parent.xdg_surface) {
813 zxdg_surface_v6_set_window_geometry(output->parent.xdg_surface,
814 0,
815 0,
816 width,
817 height);
818 }
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600819 }
820
Armin Krezovićb08e1a52016-12-09 22:58:27 +0100821#ifdef ENABLE_EGL
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600822 if (output->gl.egl_window) {
823 wl_egl_window_resize(output->gl.egl_window,
824 width, height, 0, 0);
825
826 /* These will need to be re-created due to the resize */
827 gl_renderer->output_set_border(&output->base,
828 GL_RENDERER_BORDER_TOP,
829 0, 0, 0, NULL);
830 cairo_surface_destroy(output->gl.border.top);
831 output->gl.border.top = NULL;
832 gl_renderer->output_set_border(&output->base,
833 GL_RENDERER_BORDER_LEFT,
834 0, 0, 0, NULL);
835 cairo_surface_destroy(output->gl.border.left);
836 output->gl.border.left = NULL;
837 gl_renderer->output_set_border(&output->base,
838 GL_RENDERER_BORDER_RIGHT,
839 0, 0, 0, NULL);
840 cairo_surface_destroy(output->gl.border.right);
841 output->gl.border.right = NULL;
842 gl_renderer->output_set_border(&output->base,
843 GL_RENDERER_BORDER_BOTTOM,
844 0, 0, 0, NULL);
845 cairo_surface_destroy(output->gl.border.bottom);
846 output->gl.border.bottom = NULL;
847 }
Armin Krezovićb08e1a52016-12-09 22:58:27 +0100848#endif
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600849
Armin Krezović2e662522016-10-09 17:30:29 +0200850 wayland_output_destroy_shm_buffers(output);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600851}
852
853static int
854wayland_output_set_windowed(struct wayland_output *output)
855{
Giulio Camuffo954f1832014-10-11 18:27:30 +0300856 struct wayland_backend *b =
Armin Krezović938dc522016-08-01 19:17:57 +0200857 to_wayland_backend(output->base.compositor);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600858
859 if (output->frame)
860 return 0;
861
Giulio Camuffo954f1832014-10-11 18:27:30 +0300862 if (!b->theme) {
863 b->theme = theme_create();
Sergi Granell2dcbb8d2017-03-24 20:48:01 +0100864 if (!b->theme)
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600865 return -1;
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600866 }
Giulio Camuffo954f1832014-10-11 18:27:30 +0300867 output->frame = frame_create(b->theme, 100, 100,
Sergi Granell2dcbb8d2017-03-24 20:48:01 +0100868 FRAME_BUTTON_CLOSE, output->title);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600869 if (!output->frame)
870 return -1;
871
872 if (output->keyboard_count)
873 frame_set_flag(output->frame, FRAME_FLAG_ACTIVE);
874
875 wayland_output_resize_surface(output);
876
Armin Krezović34476192016-11-21 18:42:42 +0100877 if (output->parent.shell_surface)
878 wl_shell_surface_set_toplevel(output->parent.shell_surface);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600879
880 return 0;
881}
882
883static void
884wayland_output_set_fullscreen(struct wayland_output *output,
885 enum wl_shell_surface_fullscreen_method method,
886 uint32_t framerate, struct wl_output *target)
887{
Giulio Camuffo954f1832014-10-11 18:27:30 +0300888 struct wayland_backend *b =
Armin Krezović938dc522016-08-01 19:17:57 +0200889 to_wayland_backend(output->base.compositor);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500890
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600891 if (output->frame) {
892 frame_destroy(output->frame);
893 output->frame = NULL;
894 }
895
896 wayland_output_resize_surface(output);
897
Armin Krezović34476192016-11-21 18:42:42 +0100898 if (output->parent.xdg_toplevel) {
899 zxdg_toplevel_v6_set_fullscreen(output->parent.xdg_toplevel, target);
900 } else if (output->parent.shell_surface) {
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500901 wl_shell_surface_set_fullscreen(output->parent.shell_surface,
902 method, framerate, target);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300903 } else if (b->parent.fshell) {
Jonas Ådahl496adb32015-11-17 16:00:27 +0800904 zwp_fullscreen_shell_v1_present_surface(b->parent.fshell,
905 output->parent.surface,
906 method, target);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500907 }
908}
909
910static struct weston_mode *
911wayland_output_choose_mode(struct wayland_output *output,
912 struct weston_mode *ref_mode)
913{
914 struct weston_mode *mode;
915
916 /* First look for an exact match */
917 wl_list_for_each(mode, &output->base.mode_list, link)
918 if (mode->width == ref_mode->width &&
919 mode->height == ref_mode->height &&
920 mode->refresh == ref_mode->refresh)
921 return mode;
922
923 /* If we can't find an exact match, ignore refresh and try again */
924 wl_list_for_each(mode, &output->base.mode_list, link)
925 if (mode->width == ref_mode->width &&
926 mode->height == ref_mode->height)
927 return mode;
928
929 /* Yeah, we failed */
930 return NULL;
931}
932
933enum mode_status {
934 MODE_STATUS_UNKNOWN,
935 MODE_STATUS_SUCCESS,
936 MODE_STATUS_FAIL,
937 MODE_STATUS_CANCEL,
938};
939
940static void
941mode_feedback_successful(void *data,
Jonas Ådahl496adb32015-11-17 16:00:27 +0800942 struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500943{
944 enum mode_status *value = data;
945
946 printf("Mode switch successful\n");
947
948 *value = MODE_STATUS_SUCCESS;
949}
950
951static void
Jonas Ådahl496adb32015-11-17 16:00:27 +0800952mode_feedback_failed(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500953{
954 enum mode_status *value = data;
955
956 printf("Mode switch failed\n");
957
958 *value = MODE_STATUS_FAIL;
959}
960
961static void
Jonas Ådahl496adb32015-11-17 16:00:27 +0800962mode_feedback_cancelled(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500963{
964 enum mode_status *value = data;
965
966 printf("Mode switch cancelled\n");
967
968 *value = MODE_STATUS_CANCEL;
969}
970
Jonas Ådahl496adb32015-11-17 16:00:27 +0800971struct zwp_fullscreen_shell_mode_feedback_v1_listener mode_feedback_listener = {
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500972 mode_feedback_successful,
973 mode_feedback_failed,
974 mode_feedback_cancelled,
975};
976
Armin Krezović71ebc052017-02-07 21:03:40 +0100977static enum mode_status
978wayland_output_fullscreen_shell_mode_feedback(struct wayland_output *output,
979 struct weston_mode *mode)
980{
981 struct wayland_backend *b = to_wayland_backend(output->base.compositor);
982 struct zwp_fullscreen_shell_mode_feedback_v1 *mode_feedback;
983 enum mode_status mode_status;
984 int ret = 0;
985
986 mode_feedback =
987 zwp_fullscreen_shell_v1_present_surface_for_mode(b->parent.fshell,
988 output->parent.surface,
989 output->parent.output,
990 mode->refresh);
991
992 zwp_fullscreen_shell_mode_feedback_v1_add_listener(mode_feedback,
993 &mode_feedback_listener,
994 &mode_status);
995
996 output->parent.draw_initial_frame = false;
997 draw_initial_frame(output);
998 wl_surface_commit(output->parent.surface);
999
1000 mode_status = MODE_STATUS_UNKNOWN;
1001 while (mode_status == MODE_STATUS_UNKNOWN && ret >= 0)
1002 ret = wl_display_dispatch(b->parent.wl_display);
1003
1004 zwp_fullscreen_shell_mode_feedback_v1_destroy(mode_feedback);
1005
1006 return mode_status;
1007}
1008
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001009static int
1010wayland_output_switch_mode(struct weston_output *output_base,
1011 struct weston_mode *mode)
1012{
Armin Krezović938dc522016-08-01 19:17:57 +02001013 struct wayland_output *output = to_wayland_output(output_base);
Giulio Camuffo954f1832014-10-11 18:27:30 +03001014 struct wayland_backend *b;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001015 struct wl_surface *old_surface;
1016 struct weston_mode *old_mode;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001017 enum mode_status mode_status;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001018
1019 if (output_base == NULL) {
1020 weston_log("output is NULL.\n");
1021 return -1;
1022 }
1023
1024 if (mode == NULL) {
1025 weston_log("mode is NULL.\n");
1026 return -1;
1027 }
1028
Armin Krezović938dc522016-08-01 19:17:57 +02001029 b = to_wayland_backend(output_base->compositor);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001030
Armin Krezović34476192016-11-21 18:42:42 +01001031 if (output->parent.xdg_surface || output->parent.shell_surface || !b->parent.fshell)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001032 return -1;
1033
1034 mode = wayland_output_choose_mode(output, mode);
1035 if (mode == NULL)
1036 return -1;
1037
1038 if (output->base.current_mode == mode)
1039 return 0;
1040
1041 old_mode = output->base.current_mode;
1042 old_surface = output->parent.surface;
1043 output->base.current_mode = mode;
1044 output->parent.surface =
Giulio Camuffo954f1832014-10-11 18:27:30 +03001045 wl_compositor_create_surface(b->parent.compositor);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001046 wl_surface_set_user_data(output->parent.surface, output);
1047
1048 /* Blow the old buffers because we changed size/surfaces */
1049 wayland_output_resize_surface(output);
1050
Armin Krezović71ebc052017-02-07 21:03:40 +01001051 mode_status = wayland_output_fullscreen_shell_mode_feedback(output, mode);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001052
1053 /* This should kick-start things again */
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001054 wayland_output_start_repaint_loop(&output->base);
1055
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001056 if (mode_status == MODE_STATUS_FAIL) {
1057 output->base.current_mode = old_mode;
1058 wl_surface_destroy(output->parent.surface);
1059 output->parent.surface = old_surface;
1060 wayland_output_resize_surface(output);
1061
1062 return -1;
1063 }
1064
1065 old_mode->flags &= ~WL_OUTPUT_MODE_CURRENT;
1066 output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
1067
Giulio Camuffo954f1832014-10-11 18:27:30 +03001068 if (b->use_pixman) {
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001069 pixman_renderer_output_destroy(output_base);
1070 if (wayland_output_init_pixman_renderer(output) < 0)
1071 goto err_output;
Armin Krezovićb08e1a52016-12-09 22:58:27 +01001072#ifdef ENABLE_EGL
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001073 } else {
1074 gl_renderer->output_destroy(output_base);
1075 wl_egl_window_destroy(output->gl.egl_window);
1076 if (wayland_output_init_gl_renderer(output) < 0)
1077 goto err_output;
Armin Krezovićb08e1a52016-12-09 22:58:27 +01001078#endif
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001079 }
1080 wl_surface_destroy(old_surface);
1081
1082 weston_output_schedule_repaint(&output->base);
1083
1084 return 0;
1085
1086err_output:
1087 /* XXX */
1088 return -1;
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001089}
1090
Armin Krezović34476192016-11-21 18:42:42 +01001091static void
1092handle_xdg_surface_configure(void *data, struct zxdg_surface_v6 *surface,
1093 uint32_t serial)
1094{
1095 zxdg_surface_v6_ack_configure(surface, serial);
1096}
1097
1098static const struct zxdg_surface_v6_listener xdg_surface_listener = {
1099 handle_xdg_surface_configure
1100};
1101
1102static void
1103handle_xdg_toplevel_configure(void *data, struct zxdg_toplevel_v6 *toplevel,
1104 int32_t width, int32_t height,
1105 struct wl_array *states)
1106{
1107 struct wayland_output *output = data;
1108
1109 output->parent.configure_width = width;
1110 output->parent.configure_height = height;
1111
1112 output->parent.wait_for_configure = false;
1113 /* FIXME: implement resizing */
1114}
1115
1116static void
1117handle_xdg_toplevel_close(void *data, struct zxdg_toplevel_v6 *xdg_toplevel)
1118{
Sergi Granelleaa73582017-03-25 17:19:36 +01001119 struct wayland_output *output = data;
Sergi Granellb4e239f2017-09-27 16:06:37 +02001120 struct weston_compositor *compositor = output->base.compositor;
Sergi Granelleaa73582017-03-25 17:19:36 +01001121
Sergi Granellb4e239f2017-09-27 16:06:37 +02001122 wayland_output_destroy(&output->base);
1123
1124 if (wl_list_empty(&compositor->output_list))
1125 weston_compositor_exit(compositor);
Armin Krezović34476192016-11-21 18:42:42 +01001126}
1127
1128static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
1129 handle_xdg_toplevel_configure,
1130 handle_xdg_toplevel_close,
1131};
1132
Armin Krezović174448a2016-09-30 14:11:09 +02001133static int
1134wayland_backend_create_output_surface(struct wayland_output *output)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001135{
Armin Krezović174448a2016-09-30 14:11:09 +02001136 struct wayland_backend *b = to_wayland_backend(output->base.compositor);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001137
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001138 output->parent.surface =
Giulio Camuffo954f1832014-10-11 18:27:30 +03001139 wl_compositor_create_surface(b->parent.compositor);
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001140 if (!output->parent.surface)
Armin Krezović174448a2016-09-30 14:11:09 +02001141 return -1;
1142
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001143 wl_surface_set_user_data(output->parent.surface, output);
1144
Armin Krezović2d321e32016-10-09 17:30:25 +02001145 output->parent.draw_initial_frame = true;
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001146
Armin Krezović34476192016-11-21 18:42:42 +01001147 if (b->parent.xdg_shell) {
1148 output->parent.xdg_surface =
1149 zxdg_shell_v6_get_xdg_surface(b->parent.xdg_shell,
1150 output->parent.surface);
1151 zxdg_surface_v6_add_listener(output->parent.xdg_surface,
1152 &xdg_surface_listener, output);
1153
1154 output->parent.xdg_toplevel =
1155 zxdg_surface_v6_get_toplevel(output->parent.xdg_surface);
1156 zxdg_toplevel_v6_add_listener(output->parent.xdg_toplevel,
1157 &xdg_toplevel_listener, output);
1158
Sergi Granell2dcbb8d2017-03-24 20:48:01 +01001159 zxdg_toplevel_v6_set_title(output->parent.xdg_toplevel, output->title);
1160
Armin Krezović34476192016-11-21 18:42:42 +01001161 wl_surface_commit(output->parent.surface);
1162
1163 output->parent.wait_for_configure = true;
1164
1165 while (output->parent.wait_for_configure)
1166 wl_display_dispatch(b->parent.wl_display);
1167
1168 weston_log("wayland-backend: Using xdg_shell_v6\n");
1169 }
1170 else if (b->parent.shell) {
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001171 output->parent.shell_surface =
Giulio Camuffo954f1832014-10-11 18:27:30 +03001172 wl_shell_get_shell_surface(b->parent.shell,
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001173 output->parent.surface);
Armin Krezović174448a2016-09-30 14:11:09 +02001174 if (!output->parent.shell_surface) {
1175 wl_surface_destroy(output->parent.surface);
1176 return -1;
1177 }
1178
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001179 wl_shell_surface_add_listener(output->parent.shell_surface,
1180 &shell_surface_listener, output);
Armin Krezović34476192016-11-21 18:42:42 +01001181
1182 weston_log("wayland-backend: Using wl_shell\n");
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001183 }
1184
Armin Krezović174448a2016-09-30 14:11:09 +02001185 return 0;
1186}
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001187
Armin Krezović174448a2016-09-30 14:11:09 +02001188static int
1189wayland_output_enable(struct weston_output *base)
1190{
1191 struct wayland_output *output = to_wayland_output(base);
1192 struct wayland_backend *b = to_wayland_backend(base->compositor);
Armin Krezović71ebc052017-02-07 21:03:40 +01001193 enum mode_status mode_status;
Armin Krezović174448a2016-09-30 14:11:09 +02001194 int ret = 0;
1195
Armin Krezović174448a2016-09-30 14:11:09 +02001196 weston_log("Creating %dx%d wayland output at (%d, %d)\n",
1197 output->base.current_mode->width,
1198 output->base.current_mode->height,
1199 output->base.x, output->base.y);
1200
Armin Krezovićf054d352016-10-09 17:30:27 +02001201 if (!output->parent.surface)
Armin Krezović174448a2016-09-30 14:11:09 +02001202 ret = wayland_backend_create_output_surface(output);
1203
1204 if (ret < 0)
1205 return -1;
Kristian Høgsberg546a8122012-02-01 07:45:51 -05001206
Jason Ekstrandff2fd462013-10-27 22:24:58 -05001207 wl_list_init(&output->shm.buffers);
1208 wl_list_init(&output->shm.free_buffers);
1209
Giulio Camuffo954f1832014-10-11 18:27:30 +03001210 if (b->use_pixman) {
Jason Ekstrandff2fd462013-10-27 22:24:58 -05001211 if (wayland_output_init_pixman_renderer(output) < 0)
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001212 goto err_output;
Armin Krezovićf16de172016-10-09 17:30:26 +02001213
1214 output->base.repaint = wayland_output_repaint_pixman;
Armin Krezovićb08e1a52016-12-09 22:58:27 +01001215#ifdef ENABLE_EGL
Jason Ekstrandff2fd462013-10-27 22:24:58 -05001216 } else {
1217 if (wayland_output_init_gl_renderer(output) < 0)
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001218 goto err_output;
Armin Krezovićf16de172016-10-09 17:30:26 +02001219
1220 output->base.repaint = wayland_output_repaint_gl;
Armin Krezovićb08e1a52016-12-09 22:58:27 +01001221#endif
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001222 }
1223
Armin Krezovićf16de172016-10-09 17:30:26 +02001224 output->base.start_repaint_loop = wayland_output_start_repaint_loop;
1225 output->base.assign_planes = NULL;
1226 output->base.set_backlight = NULL;
1227 output->base.set_dpms = NULL;
1228 output->base.switch_mode = wayland_output_switch_mode;
1229
Armin Krezović174448a2016-09-30 14:11:09 +02001230 if (b->sprawl_across_outputs) {
Armin Krezović71ebc052017-02-07 21:03:40 +01001231 if (b->parent.fshell) {
1232 wayland_output_resize_surface(output);
Armin Krezović174448a2016-09-30 14:11:09 +02001233
Armin Krezović71ebc052017-02-07 21:03:40 +01001234 mode_status = wayland_output_fullscreen_shell_mode_feedback(output, &output->mode);
1235
1236 if (mode_status == MODE_STATUS_FAIL) {
1237 zwp_fullscreen_shell_v1_present_surface(b->parent.fshell,
1238 output->parent.surface,
1239 ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER,
1240 output->parent.output);
1241
1242 output->parent.draw_initial_frame = true;
1243 }
1244 } else {
1245 wayland_output_set_fullscreen(output,
1246 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER,
1247 output->mode.refresh, output->parent.output);
Armin Krezović174448a2016-09-30 14:11:09 +02001248 }
1249 } else if (b->fullscreen) {
1250 wayland_output_set_fullscreen(output, 0, 0, NULL);
1251 } else {
1252 wayland_output_set_windowed(output);
1253 }
1254
1255 return 0;
1256
1257err_output:
Armin Krezovićf054d352016-10-09 17:30:27 +02001258 wayland_backend_destroy_output_surface(output);
Armin Krezović174448a2016-09-30 14:11:09 +02001259
1260 return -1;
1261}
1262
1263static struct wayland_output *
Pekka Paalanen1580be62017-08-11 16:05:41 +03001264wayland_output_create_common(struct weston_compositor *compositor,
1265 const char *name)
Armin Krezović174448a2016-09-30 14:11:09 +02001266{
1267 struct wayland_output *output;
Pekka Paalanenffa42ff2017-08-11 15:55:32 +03001268 char *title;
Sergi Granell2dcbb8d2017-03-24 20:48:01 +01001269
1270 /* name can't be NULL. */
1271 assert(name);
Armin Krezović174448a2016-09-30 14:11:09 +02001272
1273 output = zalloc(sizeof *output);
1274 if (output == NULL) {
1275 perror("zalloc");
1276 return NULL;
1277 }
1278
Pekka Paalanenffa42ff2017-08-11 15:55:32 +03001279 if (asprintf(&title, "%s - %s", WINDOW_TITLE, name) < 0) {
1280 free(output);
1281 return NULL;
1282 }
1283 output->title = title;
1284
Pekka Paalanen1580be62017-08-11 16:05:41 +03001285 weston_output_init(&output->base, compositor, name);
1286
Matt Roper361d2ad2011-08-29 13:52:23 -07001287 output->base.destroy = wayland_output_destroy;
Armin Krezović174448a2016-09-30 14:11:09 +02001288 output->base.disable = wayland_output_disable;
1289 output->base.enable = wayland_output_enable;
Sergi Granell2dcbb8d2017-03-24 20:48:01 +01001290
Armin Krezović174448a2016-09-30 14:11:09 +02001291 return output;
1292}
1293
1294static int
1295wayland_output_create(struct weston_compositor *compositor, const char *name)
1296{
Pekka Paalanen1580be62017-08-11 16:05:41 +03001297 struct wayland_output *output;
Armin Krezović174448a2016-09-30 14:11:09 +02001298
Pekka Paalanen1580be62017-08-11 16:05:41 +03001299 output = wayland_output_create_common(compositor, name);
Sergi Granell7fecb432017-03-24 20:48:02 +01001300 if (!output)
1301 return -1;
1302
Armin Krezović174448a2016-09-30 14:11:09 +02001303 weston_compositor_add_pending_output(&output->base, compositor);
1304
1305 return 0;
1306}
1307
1308static int
1309wayland_output_set_size(struct weston_output *base, int width, int height)
1310{
1311 struct wayland_output *output = to_wayland_output(base);
Armin Krezović174448a2016-09-30 14:11:09 +02001312 int output_width, output_height;
1313
1314 /* We can only be called once. */
1315 assert(!output->base.current_mode);
1316
1317 /* Make sure we have scale set. */
1318 assert(output->base.scale);
1319
1320 if (width < 1) {
1321 weston_log("Invalid width \"%d\" for output %s\n",
1322 width, output->base.name);
1323 return -1;
1324 }
1325
1326 if (height < 1) {
1327 weston_log("Invalid height \"%d\" for output %s\n",
1328 height, output->base.name);
1329 return -1;
1330 }
1331
1332 output_width = width * output->base.scale;
1333 output_height = height * output->base.scale;
1334
1335 output->mode.flags =
1336 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
1337
1338 output->mode.width = output_width;
1339 output->mode.height = output_height;
1340 output->mode.refresh = 60000;
1341 output->scale = output->base.scale;
Armin Krezović174448a2016-09-30 14:11:09 +02001342 wl_list_insert(&output->base.mode_list, &output->mode.link);
1343
1344 output->base.current_mode = &output->mode;
1345 output->base.make = "wayland";
1346 output->base.model = "none";
1347
1348 /* XXX: Calculate proper size. */
1349 output->base.mm_width = width;
1350 output->base.mm_height = height;
1351
Armin Krezović174448a2016-09-30 14:11:09 +02001352 return 0;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001353}
1354
Armin Krezović174448a2016-09-30 14:11:09 +02001355static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03001356wayland_output_create_for_parent_output(struct wayland_backend *b,
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001357 struct wayland_parent_output *poutput)
1358{
Sergi Granell7fecb432017-03-24 20:48:02 +01001359 struct wayland_output *output;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001360 struct weston_mode *mode;
Armin Krezović174448a2016-09-30 14:11:09 +02001361
Pekka Paalanen1580be62017-08-11 16:05:41 +03001362 output = wayland_output_create_common(b->compositor, "wlparent");
Sergi Granell7fecb432017-03-24 20:48:02 +01001363 if (!output)
1364 return -1;
1365
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001366 if (poutput->current_mode) {
1367 mode = poutput->current_mode;
1368 } else if (poutput->preferred_mode) {
U. Artie Eoff67072d02014-05-06 14:50:02 -07001369 mode = poutput->preferred_mode;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001370 } else if (!wl_list_empty(&poutput->mode_list)) {
1371 mode = container_of(poutput->mode_list.next,
1372 struct weston_mode, link);
1373 } else {
Armin Krezović174448a2016-09-30 14:11:09 +02001374 weston_log("No valid modes found. Skipping output.\n");
1375 goto out;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001376 }
1377
Armin Krezović174448a2016-09-30 14:11:09 +02001378 output->base.scale = 1;
1379 output->base.transform = WL_OUTPUT_TRANSFORM_NORMAL;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001380
Armin Krezović174448a2016-09-30 14:11:09 +02001381 if (wayland_output_set_size(&output->base, mode->width, mode->height) < 0)
1382 goto out;
1383
1384 output->mode = *mode;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001385 output->parent.output = poutput->global;
1386
1387 output->base.make = poutput->physical.make;
1388 output->base.model = poutput->physical.model;
Armin Krezović174448a2016-09-30 14:11:09 +02001389
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001390 wl_list_insert_list(&output->base.mode_list, &poutput->mode_list);
1391 wl_list_init(&poutput->mode_list);
1392
Armin Krezović174448a2016-09-30 14:11:09 +02001393 weston_compositor_add_pending_output(&output->base, b->compositor);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001394
Armin Krezović174448a2016-09-30 14:11:09 +02001395 return 0;
1396
1397out:
Pekka Paalanenae6d35d2017-08-16 12:07:14 +03001398 weston_output_release(&output->base);
Sergi Granell2dcbb8d2017-03-24 20:48:01 +01001399 free(output->title);
Armin Krezović174448a2016-09-30 14:11:09 +02001400 free(output);
1401
1402 return -1;
1403}
1404
1405static int
1406wayland_output_create_fullscreen(struct wayland_backend *b)
1407{
Sergi Granell7fecb432017-03-24 20:48:02 +01001408 struct wayland_output *output;
Armin Krezović174448a2016-09-30 14:11:09 +02001409 int width = 0, height = 0;
1410
Pekka Paalanen1580be62017-08-11 16:05:41 +03001411 output = wayland_output_create_common(b->compositor, "wayland-fullscreen");
Sergi Granell7fecb432017-03-24 20:48:02 +01001412 if (!output)
1413 return -1;
1414
Armin Krezović174448a2016-09-30 14:11:09 +02001415 output->base.scale = 1;
1416 output->base.transform = WL_OUTPUT_TRANSFORM_NORMAL;
1417
1418 if (wayland_backend_create_output_surface(output) < 0)
1419 goto err_surface;
1420
1421 /* What should size be set if conditional is false? */
Armin Krezović34476192016-11-21 18:42:42 +01001422 if (b->parent.xdg_shell || b->parent.shell) {
1423 if (output->parent.xdg_toplevel)
1424 zxdg_toplevel_v6_set_fullscreen(output->parent.xdg_toplevel,
1425 output->parent.output);
1426 else if (output->parent.shell_surface)
1427 wl_shell_surface_set_fullscreen(output->parent.shell_surface,
1428 0, 0, NULL);
1429
Armin Krezović174448a2016-09-30 14:11:09 +02001430 wl_display_roundtrip(b->parent.wl_display);
1431
1432 width = output->parent.configure_width;
1433 height = output->parent.configure_height;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001434 }
1435
Armin Krezović174448a2016-09-30 14:11:09 +02001436 if (wayland_output_set_size(&output->base, width, height) < 0)
1437 goto err_set_size;
1438
1439 weston_compositor_add_pending_output(&output->base, b->compositor);
1440
1441 return 0;
1442
1443err_set_size:
1444 wayland_backend_destroy_output_surface(output);
1445err_surface:
Pekka Paalanenae6d35d2017-08-16 12:07:14 +03001446 weston_output_release(&output->base);
Sergi Granell2dcbb8d2017-03-24 20:48:01 +01001447 free(output->title);
Armin Krezović174448a2016-09-30 14:11:09 +02001448 free(output);
1449
1450 return -1;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001451}
1452
Ander Conselvan de Oliveira563c5b82012-06-18 17:36:21 +03001453static void
1454shell_surface_ping(void *data, struct wl_shell_surface *shell_surface,
1455 uint32_t serial)
1456{
1457 wl_shell_surface_pong(shell_surface, serial);
1458}
1459
1460static void
1461shell_surface_configure(void *data, struct wl_shell_surface *shell_surface,
1462 uint32_t edges, int32_t width, int32_t height)
1463{
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001464 struct wayland_output *output = data;
1465
1466 output->parent.configure_width = width;
1467 output->parent.configure_height = height;
1468
Ander Conselvan de Oliveira563c5b82012-06-18 17:36:21 +03001469 /* FIXME: implement resizing */
1470}
1471
1472static void
1473shell_surface_popup_done(void *data, struct wl_shell_surface *shell_surface)
1474{
1475}
1476
1477static const struct wl_shell_surface_listener shell_surface_listener = {
1478 shell_surface_ping,
1479 shell_surface_configure,
1480 shell_surface_popup_done
1481};
1482
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001483/* Events received from the wayland-server this compositor is client of: */
1484
Jason Ekstrand7744f712013-10-27 22:24:55 -05001485/* parent input interface */
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001486static void
Jason Ekstrand7744f712013-10-27 22:24:55 -05001487input_set_cursor(struct wayland_input *input)
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001488{
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001489
Jason Ekstrand7744f712013-10-27 22:24:55 -05001490 struct wl_buffer *buffer;
1491 struct wl_cursor_image *image;
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001492
Giulio Camuffo954f1832014-10-11 18:27:30 +03001493 if (!input->backend->cursor)
Jason Ekstrand7744f712013-10-27 22:24:55 -05001494 return; /* Couldn't load the cursor. Can't set it */
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001495
Giulio Camuffo954f1832014-10-11 18:27:30 +03001496 image = input->backend->cursor->images[0];
Jason Ekstrand7744f712013-10-27 22:24:55 -05001497 buffer = wl_cursor_image_get_buffer(image);
Hardening842a36a2014-03-18 14:12:50 +01001498 if (!buffer)
1499 return;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001500
1501 wl_pointer_set_cursor(input->parent.pointer, input->enter_serial,
1502 input->parent.cursor.surface,
1503 image->hotspot_x, image->hotspot_y);
1504
1505 wl_surface_attach(input->parent.cursor.surface, buffer, 0, 0);
1506 wl_surface_damage(input->parent.cursor.surface, 0, 0,
1507 image->width, image->height);
1508 wl_surface_commit(input->parent.cursor.surface);
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001509}
1510
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001511static void
Daniel Stone37816df2012-05-16 18:45:18 +01001512input_handle_pointer_enter(void *data, struct wl_pointer *pointer,
1513 uint32_t serial, struct wl_surface *surface,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001514 wl_fixed_t fixed_x, wl_fixed_t fixed_y)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001515{
1516 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001517 int32_t fx, fy;
1518 enum theme_location location;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001519 double x, y;
1520
1521 x = wl_fixed_to_double(fixed_x);
1522 y = wl_fixed_to_double(fixed_y);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001523
Daniel Stone50692802012-06-22 13:21:41 +01001524 /* XXX: If we get a modifier event immediately before the focus,
1525 * we should try to keep the same serial. */
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001526 input->enter_serial = serial;
1527 input->output = wl_surface_get_user_data(surface);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001528
1529 if (input->output->frame) {
1530 location = frame_pointer_enter(input->output->frame, input,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001531 x, y);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001532 frame_interior(input->output->frame, &fx, &fy, NULL, NULL);
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001533 x -= fx;
1534 y -= fy;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001535
1536 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1537 weston_output_schedule_repaint(&input->output->base);
1538 } else {
1539 location = THEME_LOCATION_CLIENT_AREA;
1540 }
1541
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001542 weston_output_transform_coordinate(&input->output->base, x, y, &x, &y);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001543
1544 if (location == THEME_LOCATION_CLIENT_AREA) {
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001545 input->has_focus = true;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001546 notify_pointer_focus(&input->base, &input->output->base, x, y);
1547 wl_pointer_set_cursor(input->parent.pointer,
1548 input->enter_serial, NULL, 0, 0);
1549 } else {
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001550 input->has_focus = false;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001551 notify_pointer_focus(&input->base, NULL, 0, 0);
1552 input_set_cursor(input);
1553 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001554}
1555
1556static void
Daniel Stone37816df2012-05-16 18:45:18 +01001557input_handle_pointer_leave(void *data, struct wl_pointer *pointer,
1558 uint32_t serial, struct wl_surface *surface)
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001559{
1560 struct wayland_input *input = data;
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001561
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001562 if (!input->output)
1563 return;
1564
Jason Ekstrand7744f712013-10-27 22:24:55 -05001565 if (input->output->frame) {
1566 frame_pointer_leave(input->output->frame, input);
1567
1568 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1569 weston_output_schedule_repaint(&input->output->base);
1570 }
1571
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001572 notify_pointer_focus(&input->base, NULL, 0, 0);
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001573 input->output = NULL;
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001574 input->has_focus = false;
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001575}
1576
1577static void
Daniel Stone37816df2012-05-16 18:45:18 +01001578input_handle_motion(void *data, struct wl_pointer *pointer,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001579 uint32_t time, wl_fixed_t fixed_x, wl_fixed_t fixed_y)
Daniel Stone37816df2012-05-16 18:45:18 +01001580{
1581 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001582 int32_t fx, fy;
1583 enum theme_location location;
Peter Hutterer87743e92016-01-18 16:38:22 +10001584 bool want_frame = false;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001585 double x, y;
Daniel Stone37816df2012-05-16 18:45:18 +01001586
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001587 if (!input->output)
1588 return;
1589
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001590 x = wl_fixed_to_double(fixed_x);
1591 y = wl_fixed_to_double(fixed_y);
1592
Jason Ekstrand7744f712013-10-27 22:24:55 -05001593 if (input->output->frame) {
1594 location = frame_pointer_motion(input->output->frame, input,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001595 x, y);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001596 frame_interior(input->output->frame, &fx, &fy, NULL, NULL);
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001597 x -= fx;
1598 y -= fy;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001599
1600 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1601 weston_output_schedule_repaint(&input->output->base);
1602 } else {
1603 location = THEME_LOCATION_CLIENT_AREA;
1604 }
1605
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001606 weston_output_transform_coordinate(&input->output->base, x, y, &x, &y);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001607
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001608 if (input->has_focus && location != THEME_LOCATION_CLIENT_AREA) {
Jason Ekstrand7744f712013-10-27 22:24:55 -05001609 input_set_cursor(input);
1610 notify_pointer_focus(&input->base, NULL, 0, 0);
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001611 input->has_focus = false;
Peter Hutterer87743e92016-01-18 16:38:22 +10001612 want_frame = true;
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001613 } else if (!input->has_focus &&
1614 location == THEME_LOCATION_CLIENT_AREA) {
Jason Ekstrand7744f712013-10-27 22:24:55 -05001615 wl_pointer_set_cursor(input->parent.pointer,
1616 input->enter_serial, NULL, 0, 0);
1617 notify_pointer_focus(&input->base, &input->output->base, x, y);
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001618 input->has_focus = true;
Peter Hutterer87743e92016-01-18 16:38:22 +10001619 want_frame = true;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001620 }
1621
Peter Hutterer87743e92016-01-18 16:38:22 +10001622 if (location == THEME_LOCATION_CLIENT_AREA) {
Jason Ekstrand7744f712013-10-27 22:24:55 -05001623 notify_motion_absolute(&input->base, time, x, y);
Peter Hutterer87743e92016-01-18 16:38:22 +10001624 want_frame = true;
1625 }
1626
1627 if (want_frame && input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
1628 notify_pointer_frame(&input->base);
Daniel Stone37816df2012-05-16 18:45:18 +01001629}
1630
1631static void
1632input_handle_button(void *data, struct wl_pointer *pointer,
Daniel Stone4dbadb12012-05-30 16:31:51 +01001633 uint32_t serial, uint32_t time, uint32_t button,
Quentin Glidicd8b17bc2016-07-10 11:00:55 +02001634 enum wl_pointer_button_state state)
Daniel Stone37816df2012-05-16 18:45:18 +01001635{
1636 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001637 enum theme_location location;
Daniel Stone37816df2012-05-16 18:45:18 +01001638
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001639 if (!input->output)
1640 return;
1641
Jason Ekstrand7744f712013-10-27 22:24:55 -05001642 if (input->output->frame) {
Jason Ekstrand7744f712013-10-27 22:24:55 -05001643 location = frame_pointer_button(input->output->frame, input,
Quentin Glidicd8b17bc2016-07-10 11:00:55 +02001644 button, state);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001645
1646 if (frame_status(input->output->frame) & FRAME_STATUS_MOVE) {
Armin Krezović34476192016-11-21 18:42:42 +01001647 if (input->output->parent.xdg_toplevel)
1648 zxdg_toplevel_v6_move(input->output->parent.xdg_toplevel,
Jason Ekstrand7744f712013-10-27 22:24:55 -05001649 input->parent.seat, serial);
Armin Krezović34476192016-11-21 18:42:42 +01001650 else if (input->output->parent.shell_surface)
1651 wl_shell_surface_move(input->output->parent.shell_surface,
1652 input->parent.seat, serial);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001653 frame_status_clear(input->output->frame,
1654 FRAME_STATUS_MOVE);
1655 return;
1656 }
1657
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001658 if (frame_status(input->output->frame) & FRAME_STATUS_CLOSE) {
1659 wayland_output_destroy(&input->output->base);
Dima Ryazanovb7e70af2015-05-20 01:03:53 -07001660 input->output = NULL;
1661 input->keyboard_focus = NULL;
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001662
Giulio Camuffo954f1832014-10-11 18:27:30 +03001663 if (wl_list_empty(&input->backend->compositor->output_list))
Giulio Camuffo459137b2014-10-11 23:56:24 +03001664 weston_compositor_exit(input->backend->compositor);
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001665
1666 return;
1667 }
Jason Ekstrand7744f712013-10-27 22:24:55 -05001668
1669 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1670 weston_output_schedule_repaint(&input->output->base);
1671 } else {
1672 location = THEME_LOCATION_CLIENT_AREA;
1673 }
1674
Peter Hutterer87743e92016-01-18 16:38:22 +10001675 if (location == THEME_LOCATION_CLIENT_AREA) {
Jason Ekstrand7744f712013-10-27 22:24:55 -05001676 notify_button(&input->base, time, button, state);
Peter Hutterer87743e92016-01-18 16:38:22 +10001677 if (input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
1678 notify_pointer_frame(&input->base);
1679 }
Daniel Stone37816df2012-05-16 18:45:18 +01001680}
1681
1682static void
1683input_handle_axis(void *data, struct wl_pointer *pointer,
Daniel Stone2fce4022012-05-30 16:32:00 +01001684 uint32_t time, uint32_t axis, wl_fixed_t value)
Daniel Stone37816df2012-05-16 18:45:18 +01001685{
1686 struct wayland_input *input = data;
Peter Hutterer89b6a492016-01-18 15:58:17 +10001687 struct weston_pointer_axis_event weston_event;
Daniel Stone37816df2012-05-16 18:45:18 +01001688
Peter Hutterer89b6a492016-01-18 15:58:17 +10001689 weston_event.axis = axis;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001690 weston_event.value = wl_fixed_to_double(value);
Peter Hutterer89b6a492016-01-18 15:58:17 +10001691
Peter Hutterer87743e92016-01-18 16:38:22 +10001692 if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL &&
1693 input->vert.has_discrete) {
1694 weston_event.has_discrete = true;
1695 weston_event.discrete = input->vert.discrete;
1696 input->vert.has_discrete = false;
1697 } else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL &&
1698 input->horiz.has_discrete) {
1699 weston_event.has_discrete = true;
1700 weston_event.discrete = input->horiz.discrete;
1701 input->horiz.has_discrete = false;
1702 }
1703
Peter Hutterer89b6a492016-01-18 15:58:17 +10001704 notify_axis(&input->base, time, &weston_event);
Peter Hutterer87743e92016-01-18 16:38:22 +10001705
1706 if (input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
1707 notify_pointer_frame(&input->base);
1708}
1709
1710static void
1711input_handle_frame(void *data, struct wl_pointer *pointer)
1712{
1713 struct wayland_input *input = data;
1714
1715 notify_pointer_frame(&input->base);
1716}
1717
1718static void
1719input_handle_axis_source(void *data, struct wl_pointer *pointer,
1720 uint32_t source)
1721{
1722 struct wayland_input *input = data;
1723
1724 notify_axis_source(&input->base, source);
1725}
1726
1727static void
1728input_handle_axis_stop(void *data, struct wl_pointer *pointer,
1729 uint32_t time, uint32_t axis)
1730{
1731 struct wayland_input *input = data;
1732 struct weston_pointer_axis_event weston_event;
1733
1734 weston_event.axis = axis;
1735 weston_event.value = 0;
1736
1737 notify_axis(&input->base, time, &weston_event);
1738}
1739
1740static void
1741input_handle_axis_discrete(void *data, struct wl_pointer *pointer,
1742 uint32_t axis, int32_t discrete)
1743{
1744 struct wayland_input *input = data;
1745
1746 if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
1747 input->vert.has_discrete = true;
1748 input->vert.discrete = discrete;
1749 } else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
1750 input->horiz.has_discrete = true;
1751 input->horiz.discrete = discrete;
1752 }
Daniel Stone37816df2012-05-16 18:45:18 +01001753}
1754
1755static const struct wl_pointer_listener pointer_listener = {
1756 input_handle_pointer_enter,
1757 input_handle_pointer_leave,
1758 input_handle_motion,
1759 input_handle_button,
1760 input_handle_axis,
Peter Hutterer87743e92016-01-18 16:38:22 +10001761 input_handle_frame,
1762 input_handle_axis_source,
1763 input_handle_axis_stop,
1764 input_handle_axis_discrete,
Daniel Stone37816df2012-05-16 18:45:18 +01001765};
1766
1767static void
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001768input_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format,
1769 int fd, uint32_t size)
1770{
1771 struct wayland_input *input = data;
1772 struct xkb_keymap *keymap;
1773 char *map_str;
1774
U. Artie Eoffd8d47012014-05-06 14:50:03 -07001775 if (!data) {
1776 close(fd);
1777 return;
1778 }
Jason Ekstrandb7d9f2e2014-04-02 19:53:57 -05001779
1780 if (format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
1781 map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
1782 if (map_str == MAP_FAILED) {
1783 weston_log("mmap failed: %m\n");
1784 goto error;
1785 }
1786
Giulio Camuffo954f1832014-10-11 18:27:30 +03001787 keymap = xkb_keymap_new_from_string(input->backend->compositor->xkb_context,
Ran Benita2e1968f2014-08-19 23:59:51 +03001788 map_str,
1789 XKB_KEYMAP_FORMAT_TEXT_V1,
1790 0);
Jason Ekstrandb7d9f2e2014-04-02 19:53:57 -05001791 munmap(map_str, size);
1792
1793 if (!keymap) {
1794 weston_log("failed to compile keymap\n");
1795 goto error;
1796 }
1797
1798 input->keyboard_state_update = STATE_UPDATE_NONE;
1799 } else if (format == WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP) {
1800 weston_log("No keymap provided; falling back to defalt\n");
1801 keymap = NULL;
1802 input->keyboard_state_update = STATE_UPDATE_AUTOMATIC;
1803 } else {
1804 weston_log("Invalid keymap\n");
1805 goto error;
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001806 }
1807
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001808 close(fd);
1809
Derek Foreman1281a362015-07-31 16:55:32 -05001810 if (weston_seat_get_keyboard(&input->base))
Rui Matos0c194ce2013-10-10 19:44:21 +02001811 weston_seat_update_keymap(&input->base, keymap);
1812 else
1813 weston_seat_init_keyboard(&input->base, keymap);
1814
Ran Benitac9c74152014-08-19 23:59:52 +03001815 xkb_keymap_unref(keymap);
Jason Ekstrandb7d9f2e2014-04-02 19:53:57 -05001816
1817 return;
1818
1819error:
1820 wl_keyboard_release(input->parent.keyboard);
1821 close(fd);
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001822}
1823
1824static void
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001825input_handle_keyboard_enter(void *data,
Daniel Stone37816df2012-05-16 18:45:18 +01001826 struct wl_keyboard *keyboard,
1827 uint32_t serial,
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001828 struct wl_surface *surface,
1829 struct wl_array *keys)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001830{
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -05001831 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001832 struct wayland_output *focus;
1833
1834 focus = input->keyboard_focus;
1835 if (focus) {
1836 /* This shouldn't happen */
1837 focus->keyboard_count--;
1838 if (!focus->keyboard_count && focus->frame)
1839 frame_unset_flag(focus->frame, FRAME_FLAG_ACTIVE);
1840 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
1841 weston_output_schedule_repaint(&focus->base);
1842 }
1843
1844 input->keyboard_focus = wl_surface_get_user_data(surface);
1845 input->keyboard_focus->keyboard_count++;
1846
1847 focus = input->keyboard_focus;
1848 if (focus->frame) {
1849 frame_set_flag(focus->frame, FRAME_FLAG_ACTIVE);
1850 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
1851 weston_output_schedule_repaint(&focus->base);
1852 }
1853
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -05001854
Daniel Stone50692802012-06-22 13:21:41 +01001855 /* XXX: If we get a modifier event immediately before the focus,
1856 * we should try to keep the same serial. */
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001857 notify_keyboard_focus_in(&input->base, keys,
Daniel Stoned6da09e2012-06-22 13:21:29 +01001858 STATE_UPDATE_AUTOMATIC);
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001859}
1860
1861static void
1862input_handle_keyboard_leave(void *data,
Daniel Stone37816df2012-05-16 18:45:18 +01001863 struct wl_keyboard *keyboard,
1864 uint32_t serial,
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001865 struct wl_surface *surface)
1866{
1867 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001868 struct wayland_output *focus;
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001869
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001870 notify_keyboard_focus_out(&input->base);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001871
1872 focus = input->keyboard_focus;
1873 if (!focus)
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001874 return;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001875
1876 focus->keyboard_count--;
1877 if (!focus->keyboard_count && focus->frame) {
1878 frame_unset_flag(focus->frame, FRAME_FLAG_ACTIVE);
1879 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
1880 weston_output_schedule_repaint(&focus->base);
1881 }
1882
1883 input->keyboard_focus = NULL;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001884}
1885
Daniel Stone37816df2012-05-16 18:45:18 +01001886static void
1887input_handle_key(void *data, struct wl_keyboard *keyboard,
1888 uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
1889{
1890 struct wayland_input *input = data;
Daniel Stone37816df2012-05-16 18:45:18 +01001891
Daniel Stone50692802012-06-22 13:21:41 +01001892 input->key_serial = serial;
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001893 notify_key(&input->base, time, key,
Daniel Stonec9785ea2012-05-30 16:31:52 +01001894 state ? WL_KEYBOARD_KEY_STATE_PRESSED :
Daniel Stone1b4e11f2012-06-22 13:21:37 +01001895 WL_KEYBOARD_KEY_STATE_RELEASED,
Jason Ekstrandb7d9f2e2014-04-02 19:53:57 -05001896 input->keyboard_state_update);
Daniel Stone37816df2012-05-16 18:45:18 +01001897}
1898
Daniel Stone351eb612012-05-31 15:27:47 -04001899static void
Derek Foreman1281a362015-07-31 16:55:32 -05001900input_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
Daniel Stone50692802012-06-22 13:21:41 +01001901 uint32_t serial_in, uint32_t mods_depressed,
Daniel Stone351eb612012-05-31 15:27:47 -04001902 uint32_t mods_latched, uint32_t mods_locked,
1903 uint32_t group)
1904{
Derek Foreman1281a362015-07-31 16:55:32 -05001905 struct weston_keyboard *keyboard;
Daniel Stone50692802012-06-22 13:21:41 +01001906 struct wayland_input *input = data;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001907 struct wayland_backend *b = input->backend;
Daniel Stone50692802012-06-22 13:21:41 +01001908 uint32_t serial_out;
1909
1910 /* If we get a key event followed by a modifier event with the
1911 * same serial number, then we try to preserve those semantics by
1912 * reusing the same serial number on the way out too. */
1913 if (serial_in == input->key_serial)
Giulio Camuffo954f1832014-10-11 18:27:30 +03001914 serial_out = wl_display_get_serial(b->compositor->wl_display);
Daniel Stone50692802012-06-22 13:21:41 +01001915 else
Giulio Camuffo954f1832014-10-11 18:27:30 +03001916 serial_out = wl_display_next_serial(b->compositor->wl_display);
Daniel Stone50692802012-06-22 13:21:41 +01001917
Derek Foreman1281a362015-07-31 16:55:32 -05001918 keyboard = weston_seat_get_keyboard(&input->base);
1919 xkb_state_update_mask(keyboard->xkb_state.state,
Daniel Stone50692802012-06-22 13:21:41 +01001920 mods_depressed, mods_latched,
1921 mods_locked, 0, 0, group);
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001922 notify_modifiers(&input->base, serial_out);
Daniel Stone351eb612012-05-31 15:27:47 -04001923}
1924
Jonny Lamb497994a2014-08-12 14:58:26 +02001925static void
1926input_handle_repeat_info(void *data, struct wl_keyboard *keyboard,
1927 int32_t rate, int32_t delay)
1928{
1929 struct wayland_input *input = data;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001930 struct wayland_backend *b = input->backend;
Jonny Lamb497994a2014-08-12 14:58:26 +02001931
Giulio Camuffo954f1832014-10-11 18:27:30 +03001932 b->compositor->kb_repeat_rate = rate;
1933 b->compositor->kb_repeat_delay = delay;
Jonny Lamb497994a2014-08-12 14:58:26 +02001934}
1935
Daniel Stone37816df2012-05-16 18:45:18 +01001936static const struct wl_keyboard_listener keyboard_listener = {
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001937 input_handle_keymap,
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001938 input_handle_keyboard_enter,
1939 input_handle_keyboard_leave,
Daniel Stone37816df2012-05-16 18:45:18 +01001940 input_handle_key,
Daniel Stone351eb612012-05-31 15:27:47 -04001941 input_handle_modifiers,
Jonny Lamb497994a2014-08-12 14:58:26 +02001942 input_handle_repeat_info,
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001943};
1944
1945static void
Derek Foreman748c6952015-11-06 15:56:10 -06001946input_handle_touch_down(void *data, struct wl_touch *wl_touch,
1947 uint32_t serial, uint32_t time,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001948 struct wl_surface *surface, int32_t id,
1949 wl_fixed_t fixed_x, wl_fixed_t fixed_y)
Derek Foreman748c6952015-11-06 15:56:10 -06001950{
1951 struct wayland_input *input = data;
1952 struct wayland_output *output;
1953 enum theme_location location;
1954 bool first_touch;
1955 int32_t fx, fy;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001956 double x, y;
1957
1958 x = wl_fixed_to_double(fixed_x);
1959 y = wl_fixed_to_double(fixed_y);
Derek Foreman748c6952015-11-06 15:56:10 -06001960
1961 first_touch = (input->touch_points == 0);
1962 input->touch_points++;
1963
1964 input->touch_focus = wl_surface_get_user_data(surface);
1965 output = input->touch_focus;
1966 if (!first_touch && !input->touch_active)
1967 return;
1968
1969 if (output->frame) {
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001970 location = frame_touch_down(output->frame, input, id, x, y);
Derek Foreman748c6952015-11-06 15:56:10 -06001971
1972 frame_interior(output->frame, &fx, &fy, NULL, NULL);
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02001973 x -= fx;
1974 y -= fy;
Derek Foreman748c6952015-11-06 15:56:10 -06001975
1976 if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
1977 weston_output_schedule_repaint(&output->base);
1978
1979 if (first_touch && (frame_status(output->frame) & FRAME_STATUS_MOVE)) {
1980 input->touch_points--;
Armin Krezović34476192016-11-21 18:42:42 +01001981 if (output->parent.xdg_toplevel)
1982 zxdg_toplevel_v6_move(output->parent.xdg_toplevel,
1983 input->parent.seat, serial);
1984 else if (output->parent.shell_surface)
1985 wl_shell_surface_move(output->parent.shell_surface,
1986 input->parent.seat, serial);
Derek Foreman748c6952015-11-06 15:56:10 -06001987 frame_status_clear(output->frame,
1988 FRAME_STATUS_MOVE);
1989 return;
1990 }
1991
1992 if (first_touch && location != THEME_LOCATION_CLIENT_AREA)
1993 return;
1994 }
1995
1996 weston_output_transform_coordinate(&output->base, x, y, &x, &y);
1997
1998 notify_touch(&input->base, time, id, x, y, WL_TOUCH_DOWN);
1999 input->touch_active = true;
2000}
2001
2002static void
2003input_handle_touch_up(void *data, struct wl_touch *wl_touch,
2004 uint32_t serial, uint32_t time, int32_t id)
2005{
2006 struct wayland_input *input = data;
2007 struct wayland_output *output = input->touch_focus;
2008 bool active = input->touch_active;
2009
2010 input->touch_points--;
2011 if (input->touch_points == 0) {
2012 input->touch_focus = NULL;
2013 input->touch_active = false;
2014 }
2015
2016 if (!output)
2017 return;
2018
2019 if (output->frame) {
2020 frame_touch_up(output->frame, input, id);
2021
2022 if (frame_status(output->frame) & FRAME_STATUS_CLOSE) {
2023 wayland_output_destroy(&output->base);
2024 input->touch_focus = NULL;
2025 input->keyboard_focus = NULL;
2026 if (wl_list_empty(&input->backend->compositor->output_list))
2027 weston_compositor_exit(input->backend->compositor);
2028
2029 return;
2030 }
2031 if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
2032 weston_output_schedule_repaint(&output->base);
2033 }
2034
2035 if (active)
2036 notify_touch(&input->base, time, id, 0, 0, WL_TOUCH_UP);
2037}
2038
2039static void
2040input_handle_touch_motion(void *data, struct wl_touch *wl_touch,
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002041 uint32_t time, int32_t id,
2042 wl_fixed_t fixed_x, wl_fixed_t fixed_y)
Derek Foreman748c6952015-11-06 15:56:10 -06002043{
2044 struct wayland_input *input = data;
2045 struct wayland_output *output = input->touch_focus;
2046 int32_t fx, fy;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002047 double x, y;
2048
2049 x = wl_fixed_to_double(fixed_x);
2050 y = wl_fixed_to_double(fixed_y);
Derek Foreman748c6952015-11-06 15:56:10 -06002051
2052 if (!output || !input->touch_active)
2053 return;
2054
2055 if (output->frame) {
2056 frame_interior(output->frame, &fx, &fy, NULL, NULL);
Giulio Camuffo90a6fc62016-03-22 17:44:54 +02002057 x -= fx;
2058 y -= fy;
Derek Foreman748c6952015-11-06 15:56:10 -06002059 }
2060
2061 weston_output_transform_coordinate(&output->base, x, y, &x, &y);
2062
2063 notify_touch(&input->base, time, id, x, y, WL_TOUCH_MOTION);
2064}
2065
2066static void
2067input_handle_touch_frame(void *data, struct wl_touch *wl_touch)
2068{
2069 struct wayland_input *input = data;
2070
2071 if (!input->touch_focus || !input->touch_active)
2072 return;
2073
2074 notify_touch_frame(&input->base);
2075}
2076
2077static void
2078input_handle_touch_cancel(void *data, struct wl_touch *wl_touch)
2079{
2080 struct wayland_input *input = data;
2081
2082 if (!input->touch_focus || !input->touch_active)
2083 return;
2084
2085 notify_touch_cancel(&input->base);
2086}
2087
2088static const struct wl_touch_listener touch_listener = {
2089 input_handle_touch_down,
2090 input_handle_touch_up,
2091 input_handle_touch_motion,
2092 input_handle_touch_frame,
2093 input_handle_touch_cancel,
2094};
2095
2096
2097static void
Daniel Stone37816df2012-05-16 18:45:18 +01002098input_handle_capabilities(void *data, struct wl_seat *seat,
2099 enum wl_seat_capability caps)
2100{
2101 struct wayland_input *input = data;
2102
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05002103 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->parent.pointer) {
2104 input->parent.pointer = wl_seat_get_pointer(seat);
2105 wl_pointer_set_user_data(input->parent.pointer, input);
2106 wl_pointer_add_listener(input->parent.pointer,
2107 &pointer_listener, input);
Kristian Høgsberg7af7ced2012-08-10 10:01:33 -04002108 weston_seat_init_pointer(&input->base);
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05002109 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->parent.pointer) {
Derek Foremancfce7d02015-11-06 15:56:08 -06002110 if (input->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION)
2111 wl_pointer_release(input->parent.pointer);
2112 else
2113 wl_pointer_destroy(input->parent.pointer);
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05002114 input->parent.pointer = NULL;
Derek Foremancfce7d02015-11-06 15:56:08 -06002115 weston_seat_release_pointer(&input->base);
Daniel Stone37816df2012-05-16 18:45:18 +01002116 }
2117
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05002118 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->parent.keyboard) {
2119 input->parent.keyboard = wl_seat_get_keyboard(seat);
2120 wl_keyboard_set_user_data(input->parent.keyboard, input);
2121 wl_keyboard_add_listener(input->parent.keyboard,
2122 &keyboard_listener, input);
2123 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->parent.keyboard) {
Derek Foremancfce7d02015-11-06 15:56:08 -06002124 if (input->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
2125 wl_keyboard_release(input->parent.keyboard);
2126 else
2127 wl_keyboard_destroy(input->parent.keyboard);
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05002128 input->parent.keyboard = NULL;
Derek Foremancfce7d02015-11-06 15:56:08 -06002129 weston_seat_release_keyboard(&input->base);
Daniel Stone37816df2012-05-16 18:45:18 +01002130 }
Derek Foreman748c6952015-11-06 15:56:10 -06002131
2132 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->parent.touch) {
2133 input->parent.touch = wl_seat_get_touch(seat);
2134 wl_touch_set_user_data(input->parent.touch, input);
2135 wl_touch_add_listener(input->parent.touch,
2136 &touch_listener, input);
2137 weston_seat_init_touch(&input->base);
2138 } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->parent.touch) {
2139 if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION)
2140 wl_touch_release(input->parent.touch);
2141 else
2142 wl_touch_destroy(input->parent.touch);
2143 input->parent.touch = NULL;
2144 weston_seat_release_touch(&input->base);
2145 }
Daniel Stone37816df2012-05-16 18:45:18 +01002146}
2147
Jonny Lamb497994a2014-08-12 14:58:26 +02002148static void
2149input_handle_name(void *data, struct wl_seat *seat,
2150 const char *name)
2151{
2152}
2153
Daniel Stone37816df2012-05-16 18:45:18 +01002154static const struct wl_seat_listener seat_listener = {
2155 input_handle_capabilities,
Jonny Lamb497994a2014-08-12 14:58:26 +02002156 input_handle_name,
Daniel Stone37816df2012-05-16 18:45:18 +01002157};
2158
2159static void
Derek Foremancfce7d02015-11-06 15:56:08 -06002160display_add_seat(struct wayland_backend *b, uint32_t id, uint32_t available_version)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002161{
2162 struct wayland_input *input;
Derek Foremancfce7d02015-11-06 15:56:08 -06002163 uint32_t version = MIN(available_version, 4);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002164
Peter Huttererf3d62272013-08-08 11:57:05 +10002165 input = zalloc(sizeof *input);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002166 if (input == NULL)
2167 return;
2168
Giulio Camuffo954f1832014-10-11 18:27:30 +03002169 weston_seat_init(&input->base, b->compositor, "default");
2170 input->backend = b;
2171 input->parent.seat = wl_registry_bind(b->parent.registry, id,
Derek Foremancfce7d02015-11-06 15:56:08 -06002172 &wl_seat_interface, version);
2173 input->seat_version = version;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002174 wl_list_insert(b->input_list.prev, &input->link);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002175
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05002176 wl_seat_add_listener(input->parent.seat, &seat_listener, input);
2177 wl_seat_set_user_data(input->parent.seat, input);
Jason Ekstrand7744f712013-10-27 22:24:55 -05002178
2179 input->parent.cursor.surface =
Giulio Camuffo954f1832014-10-11 18:27:30 +03002180 wl_compositor_create_surface(b->parent.compositor);
Peter Hutterer87743e92016-01-18 16:38:22 +10002181
2182 input->vert.axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
2183 input->horiz.axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002184}
2185
2186static void
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002187wayland_parent_output_geometry(void *data, struct wl_output *output_proxy,
2188 int32_t x, int32_t y,
2189 int32_t physical_width, int32_t physical_height,
2190 int32_t subpixel, const char *make,
2191 const char *model, int32_t transform)
2192{
2193 struct wayland_parent_output *output = data;
2194
2195 output->x = x;
2196 output->y = y;
2197 output->physical.width = physical_width;
2198 output->physical.height = physical_height;
2199 output->physical.subpixel = subpixel;
2200
2201 free(output->physical.make);
2202 output->physical.make = strdup(make);
2203 free(output->physical.model);
2204 output->physical.model = strdup(model);
2205
2206 output->transform = transform;
2207}
2208
2209static struct weston_mode *
2210find_mode(struct wl_list *list, int32_t width, int32_t height, uint32_t refresh)
2211{
2212 struct weston_mode *mode;
2213
2214 wl_list_for_each(mode, list, link) {
2215 if (mode->width == width && mode->height == height &&
2216 mode->refresh == refresh)
2217 return mode;
2218 }
2219
2220 mode = zalloc(sizeof *mode);
2221 if (!mode)
2222 return NULL;
2223
2224 mode->width = width;
2225 mode->height = height;
2226 mode->refresh = refresh;
2227 wl_list_insert(list, &mode->link);
2228
2229 return mode;
2230}
2231
2232static void
2233wayland_parent_output_mode(void *data, struct wl_output *wl_output_proxy,
2234 uint32_t flags, int32_t width, int32_t height,
2235 int32_t refresh)
2236{
2237 struct wayland_parent_output *output = data;
2238 struct weston_mode *mode;
2239
2240 if (output->output) {
2241 mode = find_mode(&output->output->base.mode_list,
2242 width, height, refresh);
2243 if (!mode)
2244 return;
2245 mode->flags = flags;
2246 /* Do a mode-switch on current mode change? */
2247 } else {
2248 mode = find_mode(&output->mode_list, width, height, refresh);
2249 if (!mode)
2250 return;
2251 mode->flags = flags;
2252 if (flags & WL_OUTPUT_MODE_CURRENT)
2253 output->current_mode = mode;
2254 if (flags & WL_OUTPUT_MODE_PREFERRED)
2255 output->preferred_mode = mode;
2256 }
2257}
2258
2259static const struct wl_output_listener output_listener = {
2260 wayland_parent_output_geometry,
2261 wayland_parent_output_mode
2262};
2263
2264static void
Pekka Paalanenb07de932017-10-19 12:03:06 +03002265output_sync_callback(void *data, struct wl_callback *callback, uint32_t unused)
2266{
2267 struct wayland_parent_output *output = data;
2268
2269 assert(output->sync_cb == callback);
2270 wl_callback_destroy(callback);
2271 output->sync_cb = NULL;
2272
2273 assert(output->backend->sprawl_across_outputs);
2274
2275 wayland_output_create_for_parent_output(output->backend, output);
2276}
2277
2278static const struct wl_callback_listener output_sync_listener = {
2279 output_sync_callback
2280};
2281
2282static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03002283wayland_backend_register_output(struct wayland_backend *b, uint32_t id)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002284{
2285 struct wayland_parent_output *output;
2286
2287 output = zalloc(sizeof *output);
2288 if (!output)
2289 return;
2290
Pekka Paalanenb07de932017-10-19 12:03:06 +03002291 output->backend = b;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002292 output->id = id;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002293 output->global = wl_registry_bind(b->parent.registry, id,
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002294 &wl_output_interface, 1);
U. Artie Eoff8cbd8f32014-05-06 14:50:01 -07002295 if (!output->global) {
2296 free(output);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002297 return;
U. Artie Eoff8cbd8f32014-05-06 14:50:01 -07002298 }
2299
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002300 wl_output_add_listener(output->global, &output_listener, output);
2301
2302 output->scale = 0;
2303 output->transform = WL_OUTPUT_TRANSFORM_NORMAL;
2304 output->physical.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
2305 wl_list_init(&output->mode_list);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002306 wl_list_insert(&b->parent.output_list, &output->link);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002307
Giulio Camuffo954f1832014-10-11 18:27:30 +03002308 if (b->sprawl_across_outputs) {
Pekka Paalanenb07de932017-10-19 12:03:06 +03002309 output->sync_cb = wl_display_sync(b->parent.wl_display);
2310 wl_callback_add_listener(output->sync_cb,
2311 &output_sync_listener, output);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002312 }
2313}
2314
2315static void
2316wayland_parent_output_destroy(struct wayland_parent_output *output)
2317{
2318 struct weston_mode *mode, *next;
2319
Pekka Paalanenb07de932017-10-19 12:03:06 +03002320 if (output->sync_cb)
2321 wl_callback_destroy(output->sync_cb);
2322
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002323 if (output->output)
2324 wayland_output_destroy(&output->output->base);
2325
2326 wl_output_destroy(output->global);
2327 free(output->physical.make);
2328 free(output->physical.model);
2329
2330 wl_list_for_each_safe(mode, next, &output->mode_list, link) {
2331 wl_list_remove(&mode->link);
2332 free(mode);
2333 }
2334}
2335
2336static void
Armin Krezović34476192016-11-21 18:42:42 +01002337xdg_shell_ping(void *data, struct zxdg_shell_v6 *shell, uint32_t serial)
2338{
2339 zxdg_shell_v6_pong(shell, serial);
2340}
2341
2342static const struct zxdg_shell_v6_listener xdg_shell_listener = {
2343 xdg_shell_ping,
2344};
2345
2346static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04002347registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
2348 const char *interface, uint32_t version)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002349{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002350 struct wayland_backend *b = data;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002351
Benjamin Franzke080ab6c2011-04-30 10:41:27 +02002352 if (strcmp(interface, "wl_compositor") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002353 b->parent.compositor =
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04002354 wl_registry_bind(registry, name,
Derek Foremandbfd2482017-05-19 10:42:07 -05002355 &wl_compositor_interface,
2356 MIN(version, 4));
Armin Krezović34476192016-11-21 18:42:42 +01002357 } else if (strcmp(interface, "zxdg_shell_v6") == 0) {
2358 b->parent.xdg_shell =
2359 wl_registry_bind(registry, name,
2360 &zxdg_shell_v6_interface, 1);
2361 zxdg_shell_v6_add_listener(b->parent.xdg_shell,
2362 &xdg_shell_listener, b);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +02002363 } else if (strcmp(interface, "wl_shell") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002364 b->parent.shell =
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04002365 wl_registry_bind(registry, name,
2366 &wl_shell_interface, 1);
Jonas Ådahl496adb32015-11-17 16:00:27 +08002367 } else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002368 b->parent.fshell =
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002369 wl_registry_bind(registry, name,
Jonas Ådahl496adb32015-11-17 16:00:27 +08002370 &zwp_fullscreen_shell_v1_interface, 1);
Daniel Stone725c2c32012-06-22 14:04:36 +01002371 } else if (strcmp(interface, "wl_seat") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002372 display_add_seat(b, name, version);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002373 } else if (strcmp(interface, "wl_output") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002374 wayland_backend_register_output(b, name);
Jonas Ådahle5a12252013-04-05 23:07:11 +02002375 } else if (strcmp(interface, "wl_shm") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002376 b->parent.shm =
Jonas Ådahle5a12252013-04-05 23:07:11 +02002377 wl_registry_bind(registry, name, &wl_shm_interface, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002378 }
2379}
2380
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002381static void
2382registry_handle_global_remove(void *data, struct wl_registry *registry,
2383 uint32_t name)
2384{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002385 struct wayland_backend *b = data;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002386 struct wayland_parent_output *output;
2387
Giulio Camuffo954f1832014-10-11 18:27:30 +03002388 wl_list_for_each(output, &b->parent.output_list, link)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002389 if (output->id == name)
2390 wayland_parent_output_destroy(output);
2391}
2392
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04002393static const struct wl_registry_listener registry_listener = {
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002394 registry_handle_global,
2395 registry_handle_global_remove
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04002396};
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002397
Kristian Høgsberg95d843d2011-04-22 13:01:26 -04002398static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03002399wayland_backend_handle_event(int fd, uint32_t mask, void *data)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002400{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002401 struct wayland_backend *b = data;
Kristian Høgsbergfeb3c1d2012-10-15 12:56:11 -04002402 int count = 0;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002403
Kristian Høgsberg453de7a2013-10-30 23:15:44 -07002404 if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
Giulio Camuffo459137b2014-10-11 23:56:24 +03002405 weston_compositor_exit(b->compositor);
Kristian Høgsberg453de7a2013-10-30 23:15:44 -07002406 return 0;
2407 }
2408
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002409 if (mask & WL_EVENT_READABLE)
Giulio Camuffo954f1832014-10-11 18:27:30 +03002410 count = wl_display_dispatch(b->parent.wl_display);
Kristian Høgsbergf258a312011-12-28 22:51:20 -05002411 if (mask & WL_EVENT_WRITABLE)
Giulio Camuffo954f1832014-10-11 18:27:30 +03002412 wl_display_flush(b->parent.wl_display);
Kristian Høgsberg95d843d2011-04-22 13:01:26 -04002413
Kristian Høgsbergfeb3c1d2012-10-15 12:56:11 -04002414 if (mask == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002415 count = wl_display_dispatch_pending(b->parent.wl_display);
2416 wl_display_flush(b->parent.wl_display);
Kristian Høgsbergfeb3c1d2012-10-15 12:56:11 -04002417 }
2418
2419 return count;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002420}
2421
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05002422static void
Kristian Høgsberg7b884bc2012-07-31 14:32:01 -04002423wayland_restore(struct weston_compositor *ec)
2424{
2425}
2426
2427static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002428wayland_destroy(struct weston_compositor *ec)
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05002429{
Armin Krezović938dc522016-08-01 19:17:57 +02002430 struct wayland_backend *b = to_wayland_backend(ec);
Jonas Ådahle5a12252013-04-05 23:07:11 +02002431
Armin Krezović78895c52016-10-09 17:30:28 +02002432 wl_event_source_remove(b->parent.wl_source);
2433
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002434 weston_compositor_shutdown(ec);
Matt Roper361d2ad2011-08-29 13:52:23 -07002435
Giulio Camuffo954f1832014-10-11 18:27:30 +03002436 if (b->parent.shm)
2437 wl_shm_destroy(b->parent.shm);
Jonas Ådahle5a12252013-04-05 23:07:11 +02002438
Armin Krezović34476192016-11-21 18:42:42 +01002439 if (b->parent.xdg_shell)
2440 zxdg_shell_v6_destroy(b->parent.xdg_shell);
2441
2442 if (b->parent.shell)
2443 wl_shell_destroy(b->parent.shell);
2444
Armin Krezović78895c52016-10-09 17:30:28 +02002445 if (b->parent.fshell)
2446 zwp_fullscreen_shell_v1_release(b->parent.fshell);
2447
2448 if (b->parent.compositor)
2449 wl_compositor_destroy(b->parent.compositor);
2450
Armin Krezović78895c52016-10-09 17:30:28 +02002451 if (b->theme)
2452 theme_destroy(b->theme);
2453
2454 if (b->frame_device)
2455 cairo_device_destroy(b->frame_device);
2456
2457 wl_cursor_theme_destroy(b->cursor_theme);
2458
Daniel Stone698f9bf2016-11-24 15:31:33 +00002459 wl_registry_destroy(b->parent.registry);
2460 wl_display_flush(b->parent.wl_display);
2461 wl_display_disconnect(b->parent.wl_display);
2462
Giulio Camuffo954f1832014-10-11 18:27:30 +03002463 free(b);
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05002464}
2465
Jason Ekstrand7744f712013-10-27 22:24:55 -05002466static const char *left_ptrs[] = {
2467 "left_ptr",
2468 "default",
2469 "top_left_arrow",
2470 "left-arrow"
2471};
2472
2473static void
Benoit Gschwind244ff792016-04-28 20:33:11 +02002474create_cursor(struct wayland_backend *b,
2475 struct weston_wayland_backend_config *config)
Jason Ekstrand7744f712013-10-27 22:24:55 -05002476{
Jason Ekstrand7744f712013-10-27 22:24:55 -05002477 unsigned int i;
2478
Benoit Gschwind244ff792016-04-28 20:33:11 +02002479 b->cursor_theme = wl_cursor_theme_load(config->cursor_theme,
2480 config->cursor_size,
2481 b->parent.shm);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002482 if (!b->cursor_theme) {
Hardening842a36a2014-03-18 14:12:50 +01002483 fprintf(stderr, "could not load cursor theme\n");
2484 return;
2485 }
Jason Ekstrand7744f712013-10-27 22:24:55 -05002486
Giulio Camuffo954f1832014-10-11 18:27:30 +03002487 b->cursor = NULL;
2488 for (i = 0; !b->cursor && i < ARRAY_LENGTH(left_ptrs); ++i)
2489 b->cursor = wl_cursor_theme_get_cursor(b->cursor_theme,
Jason Ekstrand7744f712013-10-27 22:24:55 -05002490 left_ptrs[i]);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002491 if (!b->cursor) {
Jason Ekstrand7744f712013-10-27 22:24:55 -05002492 fprintf(stderr, "could not load left cursor\n");
2493 return;
2494 }
2495}
2496
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002497static void
Derek Foreman8ae2db52015-07-15 13:00:36 -05002498fullscreen_binding(struct weston_keyboard *keyboard, uint32_t time,
2499 uint32_t key, void *data)
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002500{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002501 struct wayland_backend *b = data;
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002502 struct wayland_input *input = NULL;
2503
Giulio Camuffo954f1832014-10-11 18:27:30 +03002504 wl_list_for_each(input, &b->input_list, link)
Derek Foreman8ae2db52015-07-15 13:00:36 -05002505 if (&input->base == keyboard->seat)
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002506 break;
2507
2508 if (!input || !input->output)
2509 return;
2510
2511 if (input->output->frame)
2512 wayland_output_set_fullscreen(input->output, 0, 0, NULL);
2513 else
2514 wayland_output_set_windowed(input->output);
2515
2516 weston_output_schedule_repaint(&input->output->base);
2517}
2518
Giulio Camuffo954f1832014-10-11 18:27:30 +03002519static struct wayland_backend *
Benoit Gschwind3a49b512016-04-28 20:33:10 +02002520wayland_backend_create(struct weston_compositor *compositor,
Pekka Paalanena256c5e2016-06-03 14:56:18 +03002521 struct weston_wayland_backend_config *new_config)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002522{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002523 struct wayland_backend *b;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002524 struct wl_event_loop *loop;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002525 int fd;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002526
Giulio Camuffo954f1832014-10-11 18:27:30 +03002527 b = zalloc(sizeof *b);
2528 if (b == NULL)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002529 return NULL;
2530
Giulio Camuffo954f1832014-10-11 18:27:30 +03002531 b->compositor = compositor;
Pekka Paalanen7da9a382017-08-30 11:29:49 +03002532 compositor->backend = &b->base;
2533
Giulio Camuffo954f1832014-10-11 18:27:30 +03002534 if (weston_compositor_set_presentation_clock_software(compositor) < 0)
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04002535 goto err_compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002536
Benoit Gschwind3a49b512016-04-28 20:33:10 +02002537 b->parent.wl_display = wl_display_connect(new_config->display_name);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002538 if (b->parent.wl_display == NULL) {
Martin Minarik6d118362012-06-07 18:01:59 +02002539 weston_log("failed to create display: %m\n");
Martin Olssonc5db50f2012-07-08 03:03:43 +02002540 goto err_compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002541 }
2542
Giulio Camuffo954f1832014-10-11 18:27:30 +03002543 wl_list_init(&b->parent.output_list);
2544 wl_list_init(&b->input_list);
2545 b->parent.registry = wl_display_get_registry(b->parent.wl_display);
2546 wl_registry_add_listener(b->parent.registry, &registry_listener, b);
2547 wl_display_roundtrip(b->parent.wl_display);
Jason Ekstrand7744f712013-10-27 22:24:55 -05002548
Benoit Gschwind244ff792016-04-28 20:33:11 +02002549 create_cursor(b, new_config);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002550
Armin Krezovićb08e1a52016-12-09 22:58:27 +01002551#ifdef ENABLE_EGL
Benoit Gschwind3a49b512016-04-28 20:33:10 +02002552 b->use_pixman = new_config->use_pixman;
Armin Krezovićb08e1a52016-12-09 22:58:27 +01002553#else
2554 b->use_pixman = true;
2555#endif
Armin Krezović174448a2016-09-30 14:11:09 +02002556 b->fullscreen = new_config->fullscreen;
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002557
Giulio Camuffo954f1832014-10-11 18:27:30 +03002558 if (!b->use_pixman) {
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002559 gl_renderer = weston_load_module("gl-renderer.so",
2560 "gl_renderer_interface");
2561 if (!gl_renderer)
Armin Krezović7e71b872016-10-09 17:30:22 +02002562 b->use_pixman = true;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002563 }
2564
Giulio Camuffo954f1832014-10-11 18:27:30 +03002565 if (!b->use_pixman) {
Miguel A. Vicodddc6702016-05-18 17:41:07 +02002566 if (gl_renderer->display_create(compositor,
2567 EGL_PLATFORM_WAYLAND_KHR,
2568 b->parent.wl_display,
Miguel A. Vico41700e32016-05-18 17:47:59 +02002569 NULL,
Miguel A. Vicodddc6702016-05-18 17:41:07 +02002570 gl_renderer->alpha_attribs,
2571 NULL,
2572 0) < 0) {
Jason Ekstrandff2fd462013-10-27 22:24:58 -05002573 weston_log("Failed to initialize the GL renderer; "
2574 "falling back to pixman.\n");
Armin Krezović7e71b872016-10-09 17:30:22 +02002575 b->use_pixman = true;
Jason Ekstrandff2fd462013-10-27 22:24:58 -05002576 }
2577 }
2578
Giulio Camuffo954f1832014-10-11 18:27:30 +03002579 if (b->use_pixman) {
2580 if (pixman_renderer_init(compositor) < 0) {
Jason Ekstrandff2fd462013-10-27 22:24:58 -05002581 weston_log("Failed to initialize pixman renderer\n");
2582 goto err_display;
2583 }
2584 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002585
Giulio Camuffo954f1832014-10-11 18:27:30 +03002586 b->base.destroy = wayland_destroy;
2587 b->base.restore = wayland_restore;
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +01002588
Giulio Camuffo954f1832014-10-11 18:27:30 +03002589 loop = wl_display_get_event_loop(compositor->wl_display);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002590
Giulio Camuffo954f1832014-10-11 18:27:30 +03002591 fd = wl_display_get_fd(b->parent.wl_display);
2592 b->parent.wl_source =
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002593 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
Giulio Camuffo954f1832014-10-11 18:27:30 +03002594 wayland_backend_handle_event, b);
2595 if (b->parent.wl_source == NULL)
Dawid Gajownik82d49252015-07-31 00:02:28 -03002596 goto err_display;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002597
Giulio Camuffo954f1832014-10-11 18:27:30 +03002598 wl_event_source_check(b->parent.wl_source);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002599
Emmanuel Gil Peyrotc59f18e2015-09-25 11:58:40 +02002600 if (compositor->renderer->import_dmabuf) {
2601 if (linux_dmabuf_setup(compositor) < 0)
2602 weston_log("Error: initializing dmabuf "
2603 "support failed.\n");
2604 }
2605
Giulio Camuffo954f1832014-10-11 18:27:30 +03002606 return b;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002607err_display:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002608 wl_display_disconnect(b->parent.wl_display);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002609err_compositor:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002610 weston_compositor_shutdown(compositor);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002611 free(b);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002612 return NULL;
2613}
2614
2615static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03002616wayland_backend_destroy(struct wayland_backend *b)
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002617{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002618 wl_display_disconnect(b->parent.wl_display);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002619
Giulio Camuffo954f1832014-10-11 18:27:30 +03002620 if (b->theme)
2621 theme_destroy(b->theme);
2622 if (b->frame_device)
2623 cairo_device_destroy(b->frame_device);
2624 wl_cursor_theme_destroy(b->cursor_theme);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002625
Giulio Camuffo954f1832014-10-11 18:27:30 +03002626 weston_compositor_shutdown(b->compositor);
2627 free(b);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002628}
2629
Armin Krezović174448a2016-09-30 14:11:09 +02002630static const struct weston_windowed_output_api windowed_api = {
2631 wayland_output_set_size,
2632 wayland_output_create,
2633};
2634
Benoit Gschwindcd63b3e2016-04-28 20:33:14 +02002635static void
Benoit Gschwinde091b452016-05-10 22:47:48 +02002636config_init_to_defaults(struct weston_wayland_backend_config *config)
2637{
2638}
2639
Benoit Gschwindcd63b3e2016-04-28 20:33:14 +02002640WL_EXPORT int
Quentin Glidic23e1d6f2016-12-02 14:08:44 +01002641weston_backend_init(struct weston_compositor *compositor,
2642 struct weston_backend_config *config_base)
Benoit Gschwindcd63b3e2016-04-28 20:33:14 +02002643{
2644 struct wayland_backend *b;
Benoit Gschwindcd63b3e2016-04-28 20:33:14 +02002645 struct wayland_parent_output *poutput;
2646 struct weston_wayland_backend_config new_config;
Armin Krezović174448a2016-09-30 14:11:09 +02002647 int ret;
Benoit Gschwindcd63b3e2016-04-28 20:33:14 +02002648
Benoit Gschwinde091b452016-05-10 22:47:48 +02002649 if (config_base == NULL ||
2650 config_base->struct_version != WESTON_WAYLAND_BACKEND_CONFIG_VERSION ||
2651 config_base->struct_size > sizeof(struct weston_wayland_backend_config)) {
2652 weston_log("wayland backend config structure is invalid\n");
Benoit Gschwinde091b452016-05-10 22:47:48 +02002653 return -1;
2654 }
2655
2656 config_init_to_defaults(&new_config);
2657 memcpy(&new_config, config_base, config_base->struct_size);
2658
Pekka Paalanena256c5e2016-06-03 14:56:18 +03002659 b = wayland_backend_create(compositor, &new_config);
Benoit Gschwind37a68072016-04-28 20:33:08 +02002660
Giulio Camuffo954f1832014-10-11 18:27:30 +03002661 if (!b)
2662 return -1;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002663
Benoit Gschwind37a68072016-04-28 20:33:08 +02002664 if (new_config.sprawl || b->parent.fshell) {
Armin Krezović7f1c0b82016-10-09 17:30:23 +02002665 b->sprawl_across_outputs = true;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002666 wl_display_roundtrip(b->parent.wl_display);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002667
Giulio Camuffo954f1832014-10-11 18:27:30 +03002668 wl_list_for_each(poutput, &b->parent.output_list, link)
2669 wayland_output_create_for_parent_output(b, poutput);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002670
Giulio Camuffo954f1832014-10-11 18:27:30 +03002671 return 0;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002672 }
2673
Benoit Gschwind37a68072016-04-28 20:33:08 +02002674 if (new_config.fullscreen) {
Armin Krezović174448a2016-09-30 14:11:09 +02002675 if (wayland_output_create_fullscreen(b) < 0) {
2676 weston_log("Unable to create a fullscreen output.\n");
Benoit Gschwindcd63b3e2016-04-28 20:33:14 +02002677 goto err_outputs;
Armin Krezović174448a2016-09-30 14:11:09 +02002678 }
Benoit Gschwind830b7882016-04-28 20:33:12 +02002679
Giulio Camuffo954f1832014-10-11 18:27:30 +03002680 return 0;
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002681 }
2682
Armin Krezović174448a2016-09-30 14:11:09 +02002683 ret = weston_plugin_api_register(compositor, WESTON_WINDOWED_OUTPUT_API_NAME,
2684 &windowed_api, sizeof(windowed_api));
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002685
Armin Krezović174448a2016-09-30 14:11:09 +02002686 if (ret < 0) {
2687 weston_log("Failed to register output API.\n");
2688 wayland_backend_destroy(b);
2689 return -1;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002690 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002691
Giulio Camuffo954f1832014-10-11 18:27:30 +03002692 weston_compositor_add_key_binding(compositor, KEY_F,
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002693 MODIFIER_CTRL | MODIFIER_ALT,
Giulio Camuffo954f1832014-10-11 18:27:30 +03002694 fullscreen_binding, b);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002695 return 0;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002696
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002697err_outputs:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002698 wayland_backend_destroy(b);
2699 return -1;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002700}