blob: 8a1878ca8b2c723f80e8ed388608311d88260ec8 [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
29#include <stddef.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010030#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <fcntl.h>
34#include <unistd.h>
Daniel Stoneb7452fe2012-06-01 12:14:06 +010035#include <sys/mman.h>
Jason Ekstrand5ea04802013-11-07 20:13:33 -060036#include <linux/input.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010037
Benjamin Franzkebe014562011-02-18 17:04:24 +010038#include <wayland-client.h>
39#include <wayland-egl.h>
Jason Ekstrand7744f712013-10-27 22:24:55 -050040#include <wayland-cursor.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010041
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010042#include "compositor.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010043#include "gl-renderer.h"
Jason Ekstrandff2fd462013-10-27 22:24:58 -050044#include "pixman-renderer.h"
Jon Cruz35b2eaa2015-06-15 15:37:08 -070045#include "shared/helpers.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070046#include "shared/image-loader.h"
47#include "shared/os-compatibility.h"
48#include "shared/cairo-util.h"
Jonas Ådahl496adb32015-11-17 16:00:27 +080049#include "fullscreen-shell-unstable-v1-client-protocol.h"
Pekka Paalanenb00c79b2016-02-18 16:53:27 +020050#include "presentation-time-server-protocol.h"
Emmanuel Gil Peyrotc59f18e2015-09-25 11:58:40 +020051#include "linux-dmabuf.h"
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010052
Jason Ekstrand48ce4212013-10-27 22:25:02 -050053#define WINDOW_TITLE "Weston Compositor"
54
Giulio Camuffo954f1832014-10-11 18:27:30 +030055struct wayland_backend {
56 struct weston_backend base;
57 struct weston_compositor *compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010058
59 struct {
Kristian Høgsberg362b6722012-06-18 15:13:51 -040060 struct wl_display *wl_display;
Kristian Høgsbergfa80e112012-10-10 21:34:26 -040061 struct wl_registry *registry;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010062 struct wl_compositor *compositor;
63 struct wl_shell *shell;
Jonas Ådahl496adb32015-11-17 16:00:27 +080064 struct zwp_fullscreen_shell_v1 *fshell;
Jonas Ådahle5a12252013-04-05 23:07:11 +020065 struct wl_shm *shm;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010066
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -050067 struct wl_list output_list;
68
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010069 struct wl_event_source *wl_source;
70 uint32_t event_mask;
71 } parent;
72
Jason Ekstrandff2fd462013-10-27 22:24:58 -050073 int use_pixman;
Jason Ekstrande4ca8b02014-04-02 19:53:55 -050074 int sprawl_across_outputs;
Jason Ekstrandff2fd462013-10-27 22:24:58 -050075
Jason Ekstrand7744f712013-10-27 22:24:55 -050076 struct theme *theme;
77 cairo_device_t *frame_device;
78 struct wl_cursor_theme *cursor_theme;
79 struct wl_cursor *cursor;
Kristian Høgsberg546a8122012-02-01 07:45:51 -050080
Jason Ekstrand06ced802013-11-07 20:13:29 -060081 struct wl_list input_list;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010082};
83
84struct wayland_output {
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -050085 struct weston_output base;
86
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010087 struct {
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -050088 int draw_initial_frame;
89 struct wl_surface *surface;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -050090
91 struct wl_output *output;
92 uint32_t global_id;
93
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -050094 struct wl_shell_surface *shell_surface;
Jason Ekstrand5ea04802013-11-07 20:13:33 -060095 int configure_width, configure_height;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010096 } parent;
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -050097
Jason Ekstrand7744f712013-10-27 22:24:55 -050098 int keyboard_count;
99
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600100 char *name;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500101 struct frame *frame;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500102
Jason Ekstrand7744f712013-10-27 22:24:55 -0500103 struct {
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500104 struct wl_egl_window *egl_window;
105 struct {
106 cairo_surface_t *top;
107 cairo_surface_t *left;
108 cairo_surface_t *right;
109 cairo_surface_t *bottom;
110 } border;
111 } gl;
112
113 struct {
114 struct wl_list buffers;
115 struct wl_list free_buffers;
116 } shm;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500117
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500118 struct weston_mode mode;
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500119 uint32_t scale;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100120};
121
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500122struct wayland_parent_output {
123 struct wayland_output *output;
124 struct wl_list link;
125
126 struct wl_output *global;
127 uint32_t id;
128
129 struct {
130 char *make;
131 char *model;
132 int32_t width, height;
133 uint32_t subpixel;
134 } physical;
135
136 int32_t x, y;
137 uint32_t transform;
138 uint32_t scale;
139
140 struct wl_list mode_list;
141 struct weston_mode *preferred_mode;
142 struct weston_mode *current_mode;
143};
144
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500145struct wayland_shm_buffer {
146 struct wayland_output *output;
147 struct wl_list link;
148 struct wl_list free_link;
149
150 struct wl_buffer *buffer;
151 void *data;
152 size_t size;
153 pixman_region32_t damage;
154 int frame_damaged;
155
156 pixman_image_t *pm_image;
157 cairo_surface_t *c_surface;
158};
159
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100160struct wayland_input {
Kristian Høgsberg7af7ced2012-08-10 10:01:33 -0400161 struct weston_seat base;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300162 struct wayland_backend *backend;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100163 struct wl_list link;
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500164
165 struct {
166 struct wl_seat *seat;
167 struct wl_pointer *pointer;
168 struct wl_keyboard *keyboard;
169 struct wl_touch *touch;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500170
171 struct {
172 struct wl_surface *surface;
173 int32_t hx, hy;
174 } cursor;
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500175 } parent;
176
Jason Ekstrandb7d9f2e2014-04-02 19:53:57 -0500177 enum weston_key_state_update keyboard_state_update;
Daniel Stone50692802012-06-22 13:21:41 +0100178 uint32_t key_serial;
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400179 uint32_t enter_serial;
Derek Foreman748c6952015-11-06 15:56:10 -0600180 uint32_t touch_points;
181 bool touch_active;
Derek Foreman4bcc54d2015-11-06 15:56:06 -0600182 bool has_focus;
Derek Foremancfce7d02015-11-06 15:56:08 -0600183 int seat_version;
Derek Foreman4bcc54d2015-11-06 15:56:06 -0600184
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400185 struct wayland_output *output;
Derek Foreman748c6952015-11-06 15:56:10 -0600186 struct wayland_output *touch_focus;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500187 struct wayland_output *keyboard_focus;
Peter Hutterer87743e92016-01-18 16:38:22 +1000188
189 struct weston_pointer_axis_event vert, horiz;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100190};
191
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300192struct gl_renderer_interface *gl_renderer;
193
Kristian Høgsberg546a8122012-02-01 07:45:51 -0500194static void
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500195wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
196{
197 cairo_surface_destroy(buffer->c_surface);
198 pixman_image_unref(buffer->pm_image);
199
200 wl_buffer_destroy(buffer->buffer);
201 munmap(buffer->data, buffer->size);
202
203 pixman_region32_fini(&buffer->damage);
204
205 wl_list_remove(&buffer->link);
206 wl_list_remove(&buffer->free_link);
207 free(buffer);
208}
209
210static void
211buffer_release(void *data, struct wl_buffer *buffer)
212{
213 struct wayland_shm_buffer *sb = data;
214
215 if (sb->output) {
216 wl_list_insert(&sb->output->shm.free_buffers, &sb->free_link);
217 } else {
218 wayland_shm_buffer_destroy(sb);
219 }
220}
221
222static const struct wl_buffer_listener buffer_listener = {
223 buffer_release
224};
225
226static struct wayland_shm_buffer *
227wayland_output_get_shm_buffer(struct wayland_output *output)
228{
Giulio Camuffo954f1832014-10-11 18:27:30 +0300229 struct wayland_backend *b =
230 (struct wayland_backend *) output->base.compositor->backend;
231 struct wl_shm *shm = b->parent.shm;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500232 struct wayland_shm_buffer *sb;
233
234 struct wl_shm_pool *pool;
235 int width, height, stride;
236 int32_t fx, fy;
237 int fd;
238 unsigned char *data;
239
240 if (!wl_list_empty(&output->shm.free_buffers)) {
241 sb = container_of(output->shm.free_buffers.next,
242 struct wayland_shm_buffer, free_link);
243 wl_list_remove(&sb->free_link);
244 wl_list_init(&sb->free_link);
245
246 return sb;
247 }
248
249 if (output->frame) {
250 width = frame_width(output->frame);
251 height = frame_height(output->frame);
252 } else {
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500253 width = output->base.current_mode->width;
254 height = output->base.current_mode->height;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500255 }
256
257 stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
258
259 fd = os_create_anonymous_file(height * stride);
260 if (fd < 0) {
Bryce W. Harringtona0935022014-03-21 05:54:02 +0000261 weston_log("could not create an anonymous file buffer: %m\n");
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500262 return NULL;
263 }
264
265 data = mmap(NULL, height * stride, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
266 if (data == MAP_FAILED) {
Bryce W. Harringtona0935022014-03-21 05:54:02 +0000267 weston_log("could not mmap %d memory for data: %m\n", height * stride);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500268 close(fd);
269 return NULL;
270 }
271
272 sb = zalloc(sizeof *sb);
Bryce W. Harringtonbfd74f42014-04-21 23:51:02 +0000273 if (sb == NULL) {
Thierry Reding6ac60c12014-05-27 09:08:29 +0200274 weston_log("could not zalloc %zu memory for sb: %m\n", sizeof *sb);
Bryce W. Harringtonbfd74f42014-04-21 23:51:02 +0000275 close(fd);
276 free(data);
277 return NULL;
278 }
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500279
280 sb->output = output;
281 wl_list_init(&sb->free_link);
282 wl_list_insert(&output->shm.buffers, &sb->link);
283
284 pixman_region32_init_rect(&sb->damage, 0, 0,
285 output->base.width, output->base.height);
286 sb->frame_damaged = 1;
287
288 sb->data = data;
289 sb->size = height * stride;
290
291 pool = wl_shm_create_pool(shm, fd, sb->size);
292
293 sb->buffer = wl_shm_pool_create_buffer(pool, 0,
294 width, height,
295 stride,
296 WL_SHM_FORMAT_ARGB8888);
297 wl_buffer_add_listener(sb->buffer, &buffer_listener, sb);
298 wl_shm_pool_destroy(pool);
299 close(fd);
300
301 memset(data, 0, sb->size);
302
303 sb->c_surface =
304 cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32,
305 width, height, stride);
306
307 fx = 0;
308 fy = 0;
309 if (output->frame)
310 frame_interior(output->frame, &fx, &fy, 0, 0);
311 sb->pm_image =
312 pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height,
313 (uint32_t *)(data + fy * stride) + fx,
314 stride);
315
316 return sb;
317}
318
319static void
Kristian Høgsbergcdd61d02012-02-07 09:56:15 -0500320frame_done(void *data, struct wl_callback *callback, uint32_t time)
Kristian Høgsberg33418202011-08-16 23:01:28 -0400321{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500322 struct weston_output *output = data;
Pekka Paalanenb5eedad2014-09-23 22:08:45 -0400323 struct timespec ts;
Kristian Høgsberg33418202011-08-16 23:01:28 -0400324
Kristian Høgsbergcdd61d02012-02-07 09:56:15 -0500325 wl_callback_destroy(callback);
Pekka Paalanenb5eedad2014-09-23 22:08:45 -0400326
327 /* XXX: use the presentation extension for proper timings */
Pekka Paalanen04f8a9b2015-04-02 16:26:06 +0300328
329 /*
330 * This is the fallback case, where Presentation extension is not
331 * available from the parent compositor. We do not know the base for
332 * 'time', so we cannot feed it to finish_frame(). Do the only thing
333 * we can, and pretend finish_frame time is when we process this
334 * event.
335 */
336 weston_compositor_read_presentation_clock(output->compositor, &ts);
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200337 weston_output_finish_frame(output, &ts, 0);
Kristian Høgsberg33418202011-08-16 23:01:28 -0400338}
339
340static const struct wl_callback_listener frame_listener = {
341 frame_done
342};
343
Kristian Høgsberg06cf6b02012-01-25 23:47:45 -0500344static void
Jonas Ådahle5a12252013-04-05 23:07:11 +0200345draw_initial_frame(struct wayland_output *output)
346{
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500347 struct wayland_shm_buffer *sb;
Jonas Ådahle5a12252013-04-05 23:07:11 +0200348
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500349 sb = wayland_output_get_shm_buffer(output);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200350
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500351 /* If we are rendering with GL, then orphan it so that it gets
352 * destroyed immediately */
353 if (output->gl.egl_window)
354 sb->output = NULL;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500355
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500356 wl_surface_attach(output->parent.surface, sb->buffer, 0, 0);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500357 wl_surface_damage(output->parent.surface, 0, 0,
358 output->base.current_mode->width,
359 output->base.current_mode->height);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200360}
361
362static void
Jason Ekstrand7744f712013-10-27 22:24:55 -0500363wayland_output_update_gl_border(struct wayland_output *output)
364{
365 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
366 cairo_t *cr;
367
368 if (!output->frame)
369 return;
370 if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
371 return;
372
373 fwidth = frame_width(output->frame);
374 fheight = frame_height(output->frame);
375 frame_interior(output->frame, &ix, &iy, &iwidth, &iheight);
376
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500377 if (!output->gl.border.top)
378 output->gl.border.top =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500379 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
380 fwidth, iy);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500381 cr = cairo_create(output->gl.border.top);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500382 frame_repaint(output->frame, cr);
383 cairo_destroy(cr);
384 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_TOP,
385 fwidth, iy,
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500386 cairo_image_surface_get_stride(output->gl.border.top) / 4,
387 cairo_image_surface_get_data(output->gl.border.top));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500388
389
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500390 if (!output->gl.border.left)
391 output->gl.border.left =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500392 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
393 ix, 1);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500394 cr = cairo_create(output->gl.border.left);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500395 cairo_translate(cr, 0, -iy);
396 frame_repaint(output->frame, cr);
397 cairo_destroy(cr);
398 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_LEFT,
399 ix, 1,
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500400 cairo_image_surface_get_stride(output->gl.border.left) / 4,
401 cairo_image_surface_get_data(output->gl.border.left));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500402
403
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500404 if (!output->gl.border.right)
405 output->gl.border.right =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500406 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
407 fwidth - (ix + iwidth), 1);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500408 cr = cairo_create(output->gl.border.right);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500409 cairo_translate(cr, -(iwidth + ix), -iy);
410 frame_repaint(output->frame, cr);
411 cairo_destroy(cr);
412 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_RIGHT,
413 fwidth - (ix + iwidth), 1,
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500414 cairo_image_surface_get_stride(output->gl.border.right) / 4,
415 cairo_image_surface_get_data(output->gl.border.right));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500416
417
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500418 if (!output->gl.border.bottom)
419 output->gl.border.bottom =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500420 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
421 fwidth, fheight - (iy + iheight));
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500422 cr = cairo_create(output->gl.border.bottom);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500423 cairo_translate(cr, 0, -(iy + iheight));
424 frame_repaint(output->frame, cr);
425 cairo_destroy(cr);
426 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_BOTTOM,
427 fwidth, fheight - (iy + iheight),
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500428 cairo_image_surface_get_stride(output->gl.border.bottom) / 4,
429 cairo_image_surface_get_data(output->gl.border.bottom));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500430}
431
432static void
Jonas Ådahle5a12252013-04-05 23:07:11 +0200433wayland_output_start_repaint_loop(struct weston_output *output_base)
434{
435 struct wayland_output *output = (struct wayland_output *) output_base;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300436 struct wayland_backend *wb =
437 (struct wayland_backend *)output->base.compositor->backend;
Jonas Ådahle5a12252013-04-05 23:07:11 +0200438 struct wl_callback *callback;
439
440 /* If this is the initial frame, we need to attach a buffer so that
441 * the compositor can map the surface and include it in its render
442 * loop. If the surface doesn't end up in the render loop, the frame
443 * callback won't be invoked. The buffer is transparent and of the
444 * same size as the future real output buffer. */
445 if (output->parent.draw_initial_frame) {
446 output->parent.draw_initial_frame = 0;
447
448 draw_initial_frame(output);
449 }
450
451 callback = wl_surface_frame(output->parent.surface);
452 wl_callback_add_listener(callback, &frame_listener, output);
453 wl_surface_commit(output->parent.surface);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300454 wl_display_flush(wb->parent.wl_display);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200455}
456
David Herrmann1edf44c2013-10-22 17:11:26 +0200457static int
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500458wayland_output_repaint_gl(struct weston_output *output_base,
459 pixman_region32_t *damage)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400460{
461 struct wayland_output *output = (struct wayland_output *) output_base;
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400462 struct weston_compositor *ec = output->base.compositor;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400463 struct wl_callback *callback;
Scott Moreau062be7e2012-04-20 13:37:33 -0600464
Kristian Høgsberg33418202011-08-16 23:01:28 -0400465 callback = wl_surface_frame(output->parent.surface);
466 wl_callback_add_listener(callback, &frame_listener, output);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100467
Jason Ekstrand7744f712013-10-27 22:24:55 -0500468 wayland_output_update_gl_border(output);
469
Pekka Paalanenbc106382012-10-10 12:49:31 +0300470 ec->renderer->repaint_output(&output->base, damage);
Ander Conselvan de Oliveira0a887722012-11-22 15:57:00 +0200471
472 pixman_region32_subtract(&ec->primary_plane.damage,
473 &ec->primary_plane.damage, damage);
David Herrmann1edf44c2013-10-22 17:11:26 +0200474 return 0;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100475}
476
Matt Roper361d2ad2011-08-29 13:52:23 -0700477static void
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500478wayland_output_update_shm_border(struct wayland_shm_buffer *buffer)
479{
480 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
481 cairo_t *cr;
482
483 if (!buffer->output->frame || !buffer->frame_damaged)
484 return;
485
486 cr = cairo_create(buffer->c_surface);
487
488 frame_interior(buffer->output->frame, &ix, &iy, &iwidth, &iheight);
489 fwidth = frame_width(buffer->output->frame);
490 fheight = frame_height(buffer->output->frame);
491
492 /* Set the clip so we don't unnecisaraly damage the surface */
493 cairo_move_to(cr, ix, iy);
494 cairo_rel_line_to(cr, iwidth, 0);
495 cairo_rel_line_to(cr, 0, iheight);
496 cairo_rel_line_to(cr, -iwidth, 0);
497 cairo_line_to(cr, ix, iy);
498 cairo_line_to(cr, 0, iy);
499 cairo_line_to(cr, 0, fheight);
500 cairo_line_to(cr, fwidth, fheight);
501 cairo_line_to(cr, fwidth, 0);
502 cairo_line_to(cr, 0, 0);
503 cairo_line_to(cr, 0, iy);
504 cairo_close_path(cr);
505 cairo_clip(cr);
506
507 /* Draw using a pattern so that the final result gets clipped */
508 cairo_push_group(cr);
509 frame_repaint(buffer->output->frame, cr);
510 cairo_pop_group_to_source(cr);
511 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
512 cairo_paint(cr);
513
514 cairo_destroy(cr);
515}
516
517static void
518wayland_shm_buffer_attach(struct wayland_shm_buffer *sb)
519{
520 pixman_region32_t damage;
521 pixman_box32_t *rects;
522 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
523 int i, n;
524
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500525 pixman_region32_init(&damage);
526 weston_transformed_region(sb->output->base.width,
527 sb->output->base.height,
528 sb->output->base.transform,
529 sb->output->base.current_scale,
530 &sb->damage, &damage);
531
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500532 if (sb->output->frame) {
533 frame_interior(sb->output->frame, &ix, &iy, &iwidth, &iheight);
534 fwidth = frame_width(sb->output->frame);
535 fheight = frame_height(sb->output->frame);
536
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500537 pixman_region32_translate(&damage, ix, iy);
538
539 if (sb->frame_damaged) {
540 pixman_region32_union_rect(&damage, &damage,
541 0, 0, fwidth, iy);
542 pixman_region32_union_rect(&damage, &damage,
543 0, iy, ix, iheight);
544 pixman_region32_union_rect(&damage, &damage,
545 ix + iwidth, iy,
546 fwidth - (ix + iwidth), iheight);
547 pixman_region32_union_rect(&damage, &damage,
548 0, iy + iheight,
549 fwidth, fheight - (iy + iheight));
550 }
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500551 }
552
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500553 rects = pixman_region32_rectangles(&damage, &n);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500554 wl_surface_attach(sb->output->parent.surface, sb->buffer, 0, 0);
555 for (i = 0; i < n; ++i)
556 wl_surface_damage(sb->output->parent.surface, rects[i].x1,
557 rects[i].y1, rects[i].x2 - rects[i].x1,
558 rects[i].y2 - rects[i].y1);
559
560 if (sb->output->frame)
561 pixman_region32_fini(&damage);
562}
563
564static int
565wayland_output_repaint_pixman(struct weston_output *output_base,
566 pixman_region32_t *damage)
567{
568 struct wayland_output *output = (struct wayland_output *) output_base;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300569 struct wayland_backend *b =
570 (struct wayland_backend *)output->base.compositor->backend;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500571 struct wl_callback *callback;
572 struct wayland_shm_buffer *sb;
573
574 if (output->frame) {
575 if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
576 wl_list_for_each(sb, &output->shm.buffers, link)
577 sb->frame_damaged = 1;
578 }
579
580 wl_list_for_each(sb, &output->shm.buffers, link)
581 pixman_region32_union(&sb->damage, &sb->damage, damage);
582
583 sb = wayland_output_get_shm_buffer(output);
584
585 wayland_output_update_shm_border(sb);
586 pixman_renderer_output_set_buffer(output_base, sb->pm_image);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300587 b->compositor->renderer->repaint_output(output_base, &sb->damage);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500588
589 wayland_shm_buffer_attach(sb);
590
591 callback = wl_surface_frame(output->parent.surface);
592 wl_callback_add_listener(callback, &frame_listener, output);
593 wl_surface_commit(output->parent.surface);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300594 wl_display_flush(b->parent.wl_display);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500595
596 pixman_region32_fini(&sb->damage);
597 pixman_region32_init(&sb->damage);
598 sb->frame_damaged = 0;
599
Giulio Camuffo954f1832014-10-11 18:27:30 +0300600 pixman_region32_subtract(&b->compositor->primary_plane.damage,
601 &b->compositor->primary_plane.damage, damage);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500602 return 0;
603}
604
605static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500606wayland_output_destroy(struct weston_output *output_base)
Matt Roper361d2ad2011-08-29 13:52:23 -0700607{
608 struct wayland_output *output = (struct wayland_output *) output_base;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300609 struct wayland_backend *b =
610 (struct wayland_backend *) output->base.compositor->backend;
Matt Roper361d2ad2011-08-29 13:52:23 -0700611
Giulio Camuffo954f1832014-10-11 18:27:30 +0300612 if (b->use_pixman) {
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500613 pixman_renderer_output_destroy(output_base);
614 } else {
615 gl_renderer->output_destroy(output_base);
616 }
John Kåre Alsaker94659272012-11-13 19:10:18 +0100617
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500618 wl_egl_window_destroy(output->gl.egl_window);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500619 wl_surface_destroy(output->parent.surface);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500620 if (output->parent.shell_surface)
621 wl_shell_surface_destroy(output->parent.shell_surface);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500622
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600623 if (output->frame)
Jason Ekstrand7744f712013-10-27 22:24:55 -0500624 frame_destroy(output->frame);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600625
626 cairo_surface_destroy(output->gl.border.top);
627 cairo_surface_destroy(output->gl.border.left);
628 cairo_surface_destroy(output->gl.border.right);
629 cairo_surface_destroy(output->gl.border.bottom);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500630
631 weston_output_destroy(&output->base);
Matt Roper361d2ad2011-08-29 13:52:23 -0700632 free(output);
633
634 return;
635}
636
Ander Conselvan de Oliveira563c5b82012-06-18 17:36:21 +0300637static const struct wl_shell_surface_listener shell_surface_listener;
638
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200639static int
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500640wayland_output_init_gl_renderer(struct wayland_output *output)
641{
Jason Ekstrand00b84282013-10-27 22:24:59 -0500642 int32_t fwidth = 0, fheight = 0;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500643
644 if (output->frame) {
645 fwidth = frame_width(output->frame);
646 fheight = frame_height(output->frame);
647 } else {
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500648 fwidth = output->base.current_mode->width;
649 fheight = output->base.current_mode->height;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500650 }
651
652 output->gl.egl_window =
653 wl_egl_window_create(output->parent.surface,
654 fwidth, fheight);
655 if (!output->gl.egl_window) {
656 weston_log("failure to create wl_egl_window\n");
657 return -1;
658 }
659
660 if (gl_renderer->output_create(&output->base,
Neil Roberts77c1a5b2014-03-07 18:05:50 +0000661 output->gl.egl_window,
Jonny Lamb671148f2015-03-20 15:26:52 +0100662 output->gl.egl_window,
Neil Roberts77c1a5b2014-03-07 18:05:50 +0000663 gl_renderer->alpha_attribs,
Derek Foremane76f1852015-05-15 12:12:39 -0500664 NULL,
665 0) < 0)
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500666 goto cleanup_window;
667
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500668 return 0;
669
670cleanup_window:
671 wl_egl_window_destroy(output->gl.egl_window);
672 return -1;
673}
674
675static int
676wayland_output_init_pixman_renderer(struct wayland_output *output)
677{
678 return pixman_renderer_output_create(&output->base);
679}
680
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600681static void
682wayland_output_resize_surface(struct wayland_output *output)
683{
Giulio Camuffo954f1832014-10-11 18:27:30 +0300684 struct wayland_backend *b =
685 (struct wayland_backend *)output->base.compositor->backend;
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600686 struct wayland_shm_buffer *buffer, *next;
687 int32_t ix, iy, iwidth, iheight;
688 int32_t width, height;
689 struct wl_region *region;
690
691 width = output->base.current_mode->width;
692 height = output->base.current_mode->height;
693
694 if (output->frame) {
695 frame_resize_inside(output->frame, width, height);
696
697 frame_input_rect(output->frame, &ix, &iy, &iwidth, &iheight);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300698 region = wl_compositor_create_region(b->parent.compositor);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600699 wl_region_add(region, ix, iy, iwidth, iheight);
700 wl_surface_set_input_region(output->parent.surface, region);
701 wl_region_destroy(region);
702
703 frame_opaque_rect(output->frame, &ix, &iy, &iwidth, &iheight);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300704 region = wl_compositor_create_region(b->parent.compositor);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600705 wl_region_add(region, ix, iy, iwidth, iheight);
706 wl_surface_set_opaque_region(output->parent.surface, region);
707 wl_region_destroy(region);
708
709 width = frame_width(output->frame);
710 height = frame_height(output->frame);
711 } else {
Giulio Camuffo954f1832014-10-11 18:27:30 +0300712 region = wl_compositor_create_region(b->parent.compositor);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600713 wl_region_add(region, 0, 0, width, height);
714 wl_surface_set_input_region(output->parent.surface, region);
715 wl_region_destroy(region);
716
Giulio Camuffo954f1832014-10-11 18:27:30 +0300717 region = wl_compositor_create_region(b->parent.compositor);
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600718 wl_region_add(region, 0, 0, width, height);
719 wl_surface_set_opaque_region(output->parent.surface, region);
720 wl_region_destroy(region);
721 }
722
723 if (output->gl.egl_window) {
724 wl_egl_window_resize(output->gl.egl_window,
725 width, height, 0, 0);
726
727 /* These will need to be re-created due to the resize */
728 gl_renderer->output_set_border(&output->base,
729 GL_RENDERER_BORDER_TOP,
730 0, 0, 0, NULL);
731 cairo_surface_destroy(output->gl.border.top);
732 output->gl.border.top = NULL;
733 gl_renderer->output_set_border(&output->base,
734 GL_RENDERER_BORDER_LEFT,
735 0, 0, 0, NULL);
736 cairo_surface_destroy(output->gl.border.left);
737 output->gl.border.left = NULL;
738 gl_renderer->output_set_border(&output->base,
739 GL_RENDERER_BORDER_RIGHT,
740 0, 0, 0, NULL);
741 cairo_surface_destroy(output->gl.border.right);
742 output->gl.border.right = NULL;
743 gl_renderer->output_set_border(&output->base,
744 GL_RENDERER_BORDER_BOTTOM,
745 0, 0, 0, NULL);
746 cairo_surface_destroy(output->gl.border.bottom);
747 output->gl.border.bottom = NULL;
748 }
749
750 /* Throw away any remaining SHM buffers */
Derek Foremanf53beb82015-05-29 16:32:52 -0500751 wl_list_for_each_safe(buffer, next, &output->shm.free_buffers, free_link)
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600752 wayland_shm_buffer_destroy(buffer);
753 /* These will get thrown away when they get released */
754 wl_list_for_each(buffer, &output->shm.buffers, link)
755 buffer->output = NULL;
756}
757
758static int
759wayland_output_set_windowed(struct wayland_output *output)
760{
Giulio Camuffo954f1832014-10-11 18:27:30 +0300761 struct wayland_backend *b =
762 (struct wayland_backend *)output->base.compositor->backend;
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600763 int tlen;
764 char *title;
765
766 if (output->frame)
767 return 0;
768
769 if (output->name) {
770 tlen = strlen(output->name) + strlen(WINDOW_TITLE " - ");
771 title = malloc(tlen + 1);
772 if (!title)
773 return -1;
774
775 snprintf(title, tlen + 1, WINDOW_TITLE " - %s", output->name);
776 } else {
777 title = strdup(WINDOW_TITLE);
778 }
779
Giulio Camuffo954f1832014-10-11 18:27:30 +0300780 if (!b->theme) {
781 b->theme = theme_create();
782 if (!b->theme) {
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600783 free(title);
784 return -1;
785 }
786 }
Giulio Camuffo954f1832014-10-11 18:27:30 +0300787 output->frame = frame_create(b->theme, 100, 100,
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600788 FRAME_BUTTON_CLOSE, title);
789 free(title);
790 if (!output->frame)
791 return -1;
792
793 if (output->keyboard_count)
794 frame_set_flag(output->frame, FRAME_FLAG_ACTIVE);
795
796 wayland_output_resize_surface(output);
797
798 wl_shell_surface_set_toplevel(output->parent.shell_surface);
799
800 return 0;
801}
802
803static void
804wayland_output_set_fullscreen(struct wayland_output *output,
805 enum wl_shell_surface_fullscreen_method method,
806 uint32_t framerate, struct wl_output *target)
807{
Giulio Camuffo954f1832014-10-11 18:27:30 +0300808 struct wayland_backend *b =
809 (struct wayland_backend *)output->base.compositor->backend;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500810
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600811 if (output->frame) {
812 frame_destroy(output->frame);
813 output->frame = NULL;
814 }
815
816 wayland_output_resize_surface(output);
817
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500818 if (output->parent.shell_surface) {
819 wl_shell_surface_set_fullscreen(output->parent.shell_surface,
820 method, framerate, target);
Giulio Camuffo954f1832014-10-11 18:27:30 +0300821 } else if (b->parent.fshell) {
Jonas Ådahl496adb32015-11-17 16:00:27 +0800822 zwp_fullscreen_shell_v1_present_surface(b->parent.fshell,
823 output->parent.surface,
824 method, target);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500825 }
826}
827
828static struct weston_mode *
829wayland_output_choose_mode(struct wayland_output *output,
830 struct weston_mode *ref_mode)
831{
832 struct weston_mode *mode;
833
834 /* First look for an exact match */
835 wl_list_for_each(mode, &output->base.mode_list, link)
836 if (mode->width == ref_mode->width &&
837 mode->height == ref_mode->height &&
838 mode->refresh == ref_mode->refresh)
839 return mode;
840
841 /* If we can't find an exact match, ignore refresh and try again */
842 wl_list_for_each(mode, &output->base.mode_list, link)
843 if (mode->width == ref_mode->width &&
844 mode->height == ref_mode->height)
845 return mode;
846
847 /* Yeah, we failed */
848 return NULL;
849}
850
851enum mode_status {
852 MODE_STATUS_UNKNOWN,
853 MODE_STATUS_SUCCESS,
854 MODE_STATUS_FAIL,
855 MODE_STATUS_CANCEL,
856};
857
858static void
859mode_feedback_successful(void *data,
Jonas Ådahl496adb32015-11-17 16:00:27 +0800860 struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500861{
862 enum mode_status *value = data;
863
864 printf("Mode switch successful\n");
865
866 *value = MODE_STATUS_SUCCESS;
867}
868
869static void
Jonas Ådahl496adb32015-11-17 16:00:27 +0800870mode_feedback_failed(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500871{
872 enum mode_status *value = data;
873
874 printf("Mode switch failed\n");
875
876 *value = MODE_STATUS_FAIL;
877}
878
879static void
Jonas Ådahl496adb32015-11-17 16:00:27 +0800880mode_feedback_cancelled(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500881{
882 enum mode_status *value = data;
883
884 printf("Mode switch cancelled\n");
885
886 *value = MODE_STATUS_CANCEL;
887}
888
Jonas Ådahl496adb32015-11-17 16:00:27 +0800889struct zwp_fullscreen_shell_mode_feedback_v1_listener mode_feedback_listener = {
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500890 mode_feedback_successful,
891 mode_feedback_failed,
892 mode_feedback_cancelled,
893};
894
895static int
896wayland_output_switch_mode(struct weston_output *output_base,
897 struct weston_mode *mode)
898{
899 struct wayland_output *output = (struct wayland_output *) output_base;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300900 struct wayland_backend *b;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500901 struct wl_surface *old_surface;
902 struct weston_mode *old_mode;
Jonas Ådahl496adb32015-11-17 16:00:27 +0800903 struct zwp_fullscreen_shell_mode_feedback_v1 *mode_feedback;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500904 enum mode_status mode_status;
905 int ret = 0;
906
907 if (output_base == NULL) {
908 weston_log("output is NULL.\n");
909 return -1;
910 }
911
912 if (mode == NULL) {
913 weston_log("mode is NULL.\n");
914 return -1;
915 }
916
Giulio Camuffo954f1832014-10-11 18:27:30 +0300917 b = (struct wayland_backend *)output_base->compositor->backend;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500918
Giulio Camuffo954f1832014-10-11 18:27:30 +0300919 if (output->parent.shell_surface || !b->parent.fshell)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500920 return -1;
921
922 mode = wayland_output_choose_mode(output, mode);
923 if (mode == NULL)
924 return -1;
925
926 if (output->base.current_mode == mode)
927 return 0;
928
929 old_mode = output->base.current_mode;
930 old_surface = output->parent.surface;
931 output->base.current_mode = mode;
932 output->parent.surface =
Giulio Camuffo954f1832014-10-11 18:27:30 +0300933 wl_compositor_create_surface(b->parent.compositor);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500934 wl_surface_set_user_data(output->parent.surface, output);
935
936 /* Blow the old buffers because we changed size/surfaces */
937 wayland_output_resize_surface(output);
938
939 mode_feedback =
Jonas Ådahl496adb32015-11-17 16:00:27 +0800940 zwp_fullscreen_shell_v1_present_surface_for_mode(b->parent.fshell,
941 output->parent.surface,
942 output->parent.output,
943 mode->refresh);
944 zwp_fullscreen_shell_mode_feedback_v1_add_listener(mode_feedback,
945 &mode_feedback_listener,
946 &mode_status);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500947
948 /* This should kick-start things again */
949 output->parent.draw_initial_frame = 1;
950 wayland_output_start_repaint_loop(&output->base);
951
952 mode_status = MODE_STATUS_UNKNOWN;
953 while (mode_status == MODE_STATUS_UNKNOWN && ret >= 0)
Giulio Camuffo954f1832014-10-11 18:27:30 +0300954 ret = wl_display_dispatch(b->parent.wl_display);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500955
Jonas Ådahl496adb32015-11-17 16:00:27 +0800956 zwp_fullscreen_shell_mode_feedback_v1_destroy(mode_feedback);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500957
958 if (mode_status == MODE_STATUS_FAIL) {
959 output->base.current_mode = old_mode;
960 wl_surface_destroy(output->parent.surface);
961 output->parent.surface = old_surface;
962 wayland_output_resize_surface(output);
963
964 return -1;
965 }
966
967 old_mode->flags &= ~WL_OUTPUT_MODE_CURRENT;
968 output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
969
Giulio Camuffo954f1832014-10-11 18:27:30 +0300970 if (b->use_pixman) {
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -0500971 pixman_renderer_output_destroy(output_base);
972 if (wayland_output_init_pixman_renderer(output) < 0)
973 goto err_output;
974 } else {
975 gl_renderer->output_destroy(output_base);
976 wl_egl_window_destroy(output->gl.egl_window);
977 if (wayland_output_init_gl_renderer(output) < 0)
978 goto err_output;
979 }
980 wl_surface_destroy(old_surface);
981
982 weston_output_schedule_repaint(&output->base);
983
984 return 0;
985
986err_output:
987 /* XXX */
988 return -1;
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600989}
990
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500991static struct wayland_output *
Giulio Camuffo954f1832014-10-11 18:27:30 +0300992wayland_output_create(struct wayland_backend *b, int x, int y,
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600993 int width, int height, const char *name, int fullscreen,
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500994 uint32_t transform, int32_t scale)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100995{
996 struct wayland_output *output;
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500997 int output_width, output_height;
Jason Ekstrand5ea04802013-11-07 20:13:33 -0600998
999 weston_log("Creating %dx%d wayland output at (%d, %d)\n",
1000 width, height, x, y);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001001
Peter Huttererf3d62272013-08-08 11:57:05 +10001002 output = zalloc(sizeof *output);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001003 if (output == NULL)
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001004 return NULL;
1005
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001006 output->name = name ? strdup(name) : NULL;
1007 output->base.make = "waywayland";
1008 output->base.model = "none";
1009
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001010 output_width = width * scale;
1011 output_height = height * scale;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001012
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001013 output->parent.surface =
Giulio Camuffo954f1832014-10-11 18:27:30 +03001014 wl_compositor_create_surface(b->parent.compositor);
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001015 if (!output->parent.surface)
1016 goto err_name;
1017 wl_surface_set_user_data(output->parent.surface, output);
1018
1019 output->parent.draw_initial_frame = 1;
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001020
Giulio Camuffo954f1832014-10-11 18:27:30 +03001021 if (b->parent.shell) {
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001022 output->parent.shell_surface =
Giulio Camuffo954f1832014-10-11 18:27:30 +03001023 wl_shell_get_shell_surface(b->parent.shell,
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001024 output->parent.surface);
1025 if (!output->parent.shell_surface)
1026 goto err_surface;
1027 wl_shell_surface_add_listener(output->parent.shell_surface,
1028 &shell_surface_listener, output);
1029 }
1030
Giulio Camuffo954f1832014-10-11 18:27:30 +03001031 if (fullscreen && b->parent.shell) {
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001032 wl_shell_surface_set_fullscreen(output->parent.shell_surface,
1033 0, 0, NULL);
Giulio Camuffo954f1832014-10-11 18:27:30 +03001034 wl_display_roundtrip(b->parent.wl_display);
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001035 if (!width)
1036 output_width = output->parent.configure_width;
1037 if (!height)
1038 output_height = output->parent.configure_height;
1039 }
1040
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04001041 output->mode.flags =
1042 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001043 output->mode.width = output_width;
1044 output->mode.height = output_height;
1045 output->mode.refresh = 60000;
1046 output->scale = scale;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04001047 wl_list_init(&output->base.mode_list);
1048 wl_list_insert(&output->base.mode_list, &output->mode.link);
Hardeningff39efa2013-09-18 23:56:35 +02001049 output->base.current_mode = &output->mode;
Kristian Høgsberg546a8122012-02-01 07:45:51 -05001050
Jason Ekstrandff2fd462013-10-27 22:24:58 -05001051 wl_list_init(&output->shm.buffers);
1052 wl_list_init(&output->shm.free_buffers);
1053
Giulio Camuffo954f1832014-10-11 18:27:30 +03001054 weston_output_init(&output->base, b->compositor, x, y, width, height,
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001055 transform, scale);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001056
Giulio Camuffo954f1832014-10-11 18:27:30 +03001057 if (b->use_pixman) {
Jason Ekstrandff2fd462013-10-27 22:24:58 -05001058 if (wayland_output_init_pixman_renderer(output) < 0)
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001059 goto err_output;
Jason Ekstrandff2fd462013-10-27 22:24:58 -05001060 output->base.repaint = wayland_output_repaint_pixman;
1061 } else {
1062 if (wayland_output_init_gl_renderer(output) < 0)
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001063 goto err_output;
Jason Ekstrandff2fd462013-10-27 22:24:58 -05001064 output->base.repaint = wayland_output_repaint_gl;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001065 }
1066
Jonas Ådahle5a12252013-04-05 23:07:11 +02001067 output->base.start_repaint_loop = wayland_output_start_repaint_loop;
Matt Roper361d2ad2011-08-29 13:52:23 -07001068 output->base.destroy = wayland_output_destroy;
Jesse Barnes5308a5e2012-02-09 13:12:57 -08001069 output->base.assign_planes = NULL;
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02001070 output->base.set_backlight = NULL;
1071 output->base.set_dpms = NULL;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001072 output->base.switch_mode = wayland_output_switch_mode;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +01001073
Giulio Camuffo954f1832014-10-11 18:27:30 +03001074 weston_compositor_add_output(b->compositor, &output->base);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001075
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001076 return output;
Benjamin Franzkebe014562011-02-18 17:04:24 +01001077
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001078err_output:
1079 weston_output_destroy(&output->base);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001080 if (output->parent.shell_surface)
1081 wl_shell_surface_destroy(output->parent.shell_surface);
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001082err_surface:
1083 wl_surface_destroy(output->parent.surface);
1084err_name:
1085 free(output->name);
1086
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001087 /* FIXME: cleanup weston_output */
Benjamin Franzkebe014562011-02-18 17:04:24 +01001088 free(output);
1089
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001090 return NULL;
1091}
1092
1093static struct wayland_output *
Giulio Camuffo954f1832014-10-11 18:27:30 +03001094wayland_output_create_for_config(struct wayland_backend *b,
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001095 struct weston_config_section *config_section,
Jason Ekstrand0cf39352013-11-07 20:13:31 -06001096 int option_width, int option_height,
Jason Ekstrand12c6dd92013-11-07 20:13:32 -06001097 int option_scale, int32_t x, int32_t y)
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001098{
1099 struct wayland_output *output;
1100 char *mode, *t, *name, *str;
1101 int width, height, scale;
1102 uint32_t transform;
Derek Foreman64a3df02014-10-23 12:24:18 -05001103 unsigned int slen;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001104
1105 weston_config_section_get_string(config_section, "name", &name, NULL);
1106 if (name) {
1107 slen = strlen(name);
1108 slen += strlen(WINDOW_TITLE " - ");
1109 str = malloc(slen + 1);
1110 if (str)
1111 snprintf(str, slen + 1, WINDOW_TITLE " - %s", name);
1112 free(name);
1113 name = str;
1114 }
1115 if (!name)
U. Artie Eoff1a08d112014-01-17 12:22:50 -08001116 name = strdup(WINDOW_TITLE);
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001117
1118 weston_config_section_get_string(config_section,
1119 "mode", &mode, "1024x600");
1120 if (sscanf(mode, "%dx%d", &width, &height) != 2) {
1121 weston_log("Invalid mode \"%s\" for output %s\n",
1122 mode, name);
1123 width = 1024;
1124 height = 640;
1125 }
1126 free(mode);
1127
Jason Ekstrand0cf39352013-11-07 20:13:31 -06001128 if (option_width)
1129 width = option_width;
1130 if (option_height)
1131 height = option_height;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001132
1133 weston_config_section_get_int(config_section, "scale", &scale, 1);
1134
Jason Ekstrand12c6dd92013-11-07 20:13:32 -06001135 if (option_scale)
1136 scale = option_scale;
1137
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001138 weston_config_section_get_string(config_section,
1139 "transform", &t, "normal");
Derek Foreman64a3df02014-10-23 12:24:18 -05001140 if (weston_parse_transform(t, &transform) < 0)
1141 weston_log("Invalid transform \"%s\" for output %s\n",
1142 t, name);
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001143 free(t);
1144
Giulio Camuffo954f1832014-10-11 18:27:30 +03001145 output = wayland_output_create(b, x, y, width, height, name, 0,
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001146 transform, scale);
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001147 free(name);
1148
1149 return output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001150}
1151
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001152static struct wayland_output *
Giulio Camuffo954f1832014-10-11 18:27:30 +03001153wayland_output_create_for_parent_output(struct wayland_backend *b,
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001154 struct wayland_parent_output *poutput)
1155{
1156 struct wayland_output *output;
1157 struct weston_mode *mode;
1158 int32_t x;
1159
1160 if (poutput->current_mode) {
1161 mode = poutput->current_mode;
1162 } else if (poutput->preferred_mode) {
U. Artie Eoff67072d02014-05-06 14:50:02 -07001163 mode = poutput->preferred_mode;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001164 } else if (!wl_list_empty(&poutput->mode_list)) {
1165 mode = container_of(poutput->mode_list.next,
1166 struct weston_mode, link);
1167 } else {
Chris Michael90eea272015-09-29 17:03:20 +03001168 weston_log("No valid modes found. Skipping output\n");
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001169 return NULL;
1170 }
1171
Giulio Camuffo954f1832014-10-11 18:27:30 +03001172 if (!wl_list_empty(&b->compositor->output_list)) {
1173 output = container_of(b->compositor->output_list.prev,
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001174 struct wayland_output, base.link);
1175 x = output->base.x + output->base.current_mode->width;
1176 } else {
1177 x = 0;
1178 }
1179
Giulio Camuffo954f1832014-10-11 18:27:30 +03001180 output = wayland_output_create(b, x, 0, mode->width, mode->height,
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001181 NULL, 0,
1182 WL_OUTPUT_TRANSFORM_NORMAL, 1);
1183 if (!output)
1184 return NULL;
1185
1186 output->parent.output = poutput->global;
1187
1188 output->base.make = poutput->physical.make;
1189 output->base.model = poutput->physical.model;
1190 wl_list_init(&output->base.mode_list);
1191 wl_list_insert_list(&output->base.mode_list, &poutput->mode_list);
1192 wl_list_init(&poutput->mode_list);
1193
1194 wayland_output_set_fullscreen(output,
1195 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER,
1196 mode->refresh, poutput->global);
1197
1198 if (output->parent.shell_surface) {
1199 wl_shell_surface_set_fullscreen(output->parent.shell_surface,
1200 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER,
1201 mode->refresh, poutput->global);
Giulio Camuffo954f1832014-10-11 18:27:30 +03001202 } else if (b->parent.fshell) {
Jonas Ådahl496adb32015-11-17 16:00:27 +08001203 zwp_fullscreen_shell_v1_present_surface(b->parent.fshell,
1204 output->parent.surface,
1205 ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER,
1206 poutput->global);
1207 zwp_fullscreen_shell_mode_feedback_v1_destroy(
1208 zwp_fullscreen_shell_v1_present_surface_for_mode(b->parent.fshell,
1209 output->parent.surface,
1210 poutput->global,
1211 mode->refresh));
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001212 }
1213
1214 return output;
1215}
1216
Ander Conselvan de Oliveira563c5b82012-06-18 17:36:21 +03001217static void
1218shell_surface_ping(void *data, struct wl_shell_surface *shell_surface,
1219 uint32_t serial)
1220{
1221 wl_shell_surface_pong(shell_surface, serial);
1222}
1223
1224static void
1225shell_surface_configure(void *data, struct wl_shell_surface *shell_surface,
1226 uint32_t edges, int32_t width, int32_t height)
1227{
Jason Ekstrand5ea04802013-11-07 20:13:33 -06001228 struct wayland_output *output = data;
1229
1230 output->parent.configure_width = width;
1231 output->parent.configure_height = height;
1232
Ander Conselvan de Oliveira563c5b82012-06-18 17:36:21 +03001233 /* FIXME: implement resizing */
1234}
1235
1236static void
1237shell_surface_popup_done(void *data, struct wl_shell_surface *shell_surface)
1238{
1239}
1240
1241static const struct wl_shell_surface_listener shell_surface_listener = {
1242 shell_surface_ping,
1243 shell_surface_configure,
1244 shell_surface_popup_done
1245};
1246
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001247/* Events received from the wayland-server this compositor is client of: */
1248
Jason Ekstrand7744f712013-10-27 22:24:55 -05001249/* parent input interface */
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001250static void
Jason Ekstrand7744f712013-10-27 22:24:55 -05001251input_set_cursor(struct wayland_input *input)
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001252{
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001253
Jason Ekstrand7744f712013-10-27 22:24:55 -05001254 struct wl_buffer *buffer;
1255 struct wl_cursor_image *image;
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001256
Giulio Camuffo954f1832014-10-11 18:27:30 +03001257 if (!input->backend->cursor)
Jason Ekstrand7744f712013-10-27 22:24:55 -05001258 return; /* Couldn't load the cursor. Can't set it */
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001259
Giulio Camuffo954f1832014-10-11 18:27:30 +03001260 image = input->backend->cursor->images[0];
Jason Ekstrand7744f712013-10-27 22:24:55 -05001261 buffer = wl_cursor_image_get_buffer(image);
Hardening842a36a2014-03-18 14:12:50 +01001262 if (!buffer)
1263 return;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001264
1265 wl_pointer_set_cursor(input->parent.pointer, input->enter_serial,
1266 input->parent.cursor.surface,
1267 image->hotspot_x, image->hotspot_y);
1268
1269 wl_surface_attach(input->parent.cursor.surface, buffer, 0, 0);
1270 wl_surface_damage(input->parent.cursor.surface, 0, 0,
1271 image->width, image->height);
1272 wl_surface_commit(input->parent.cursor.surface);
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001273}
1274
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001275static void
Daniel Stone37816df2012-05-16 18:45:18 +01001276input_handle_pointer_enter(void *data, struct wl_pointer *pointer,
1277 uint32_t serial, struct wl_surface *surface,
Kristian Høgsberge11bbe42012-05-09 12:19:04 -04001278 wl_fixed_t x, wl_fixed_t y)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001279{
1280 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001281 int32_t fx, fy;
1282 enum theme_location location;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001283
Daniel Stone50692802012-06-22 13:21:41 +01001284 /* XXX: If we get a modifier event immediately before the focus,
1285 * we should try to keep the same serial. */
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001286 input->enter_serial = serial;
1287 input->output = wl_surface_get_user_data(surface);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001288
1289 if (input->output->frame) {
1290 location = frame_pointer_enter(input->output->frame, input,
1291 wl_fixed_to_int(x),
1292 wl_fixed_to_int(y));
1293 frame_interior(input->output->frame, &fx, &fy, NULL, NULL);
1294 x -= wl_fixed_from_int(fx);
1295 y -= wl_fixed_from_int(fy);
1296
1297 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1298 weston_output_schedule_repaint(&input->output->base);
1299 } else {
1300 location = THEME_LOCATION_CLIENT_AREA;
1301 }
1302
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001303 weston_output_transform_coordinate(&input->output->base, x, y, &x, &y);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001304
1305 if (location == THEME_LOCATION_CLIENT_AREA) {
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001306 input->has_focus = true;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001307 notify_pointer_focus(&input->base, &input->output->base, x, y);
1308 wl_pointer_set_cursor(input->parent.pointer,
1309 input->enter_serial, NULL, 0, 0);
1310 } else {
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001311 input->has_focus = false;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001312 notify_pointer_focus(&input->base, NULL, 0, 0);
1313 input_set_cursor(input);
1314 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001315}
1316
1317static void
Daniel Stone37816df2012-05-16 18:45:18 +01001318input_handle_pointer_leave(void *data, struct wl_pointer *pointer,
1319 uint32_t serial, struct wl_surface *surface)
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001320{
1321 struct wayland_input *input = data;
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001322
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001323 if (!input->output)
1324 return;
1325
Jason Ekstrand7744f712013-10-27 22:24:55 -05001326 if (input->output->frame) {
1327 frame_pointer_leave(input->output->frame, input);
1328
1329 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1330 weston_output_schedule_repaint(&input->output->base);
1331 }
1332
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001333 notify_pointer_focus(&input->base, NULL, 0, 0);
Kristian Høgsberg539d85f2012-08-13 23:29:53 -04001334 input->output = NULL;
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001335 input->has_focus = false;
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001336}
1337
1338static void
Daniel Stone37816df2012-05-16 18:45:18 +01001339input_handle_motion(void *data, struct wl_pointer *pointer,
1340 uint32_t time, wl_fixed_t x, wl_fixed_t y)
1341{
1342 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001343 int32_t fx, fy;
1344 enum theme_location location;
Peter Hutterer87743e92016-01-18 16:38:22 +10001345 bool want_frame = false;
Daniel Stone37816df2012-05-16 18:45:18 +01001346
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001347 if (!input->output)
1348 return;
1349
Jason Ekstrand7744f712013-10-27 22:24:55 -05001350 if (input->output->frame) {
1351 location = frame_pointer_motion(input->output->frame, input,
1352 wl_fixed_to_int(x),
1353 wl_fixed_to_int(y));
1354 frame_interior(input->output->frame, &fx, &fy, NULL, NULL);
1355 x -= wl_fixed_from_int(fx);
1356 y -= wl_fixed_from_int(fy);
1357
1358 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1359 weston_output_schedule_repaint(&input->output->base);
1360 } else {
1361 location = THEME_LOCATION_CLIENT_AREA;
1362 }
1363
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001364 weston_output_transform_coordinate(&input->output->base, x, y, &x, &y);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001365
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001366 if (input->has_focus && location != THEME_LOCATION_CLIENT_AREA) {
Jason Ekstrand7744f712013-10-27 22:24:55 -05001367 input_set_cursor(input);
1368 notify_pointer_focus(&input->base, NULL, 0, 0);
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001369 input->has_focus = false;
Peter Hutterer87743e92016-01-18 16:38:22 +10001370 want_frame = true;
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001371 } else if (!input->has_focus &&
1372 location == THEME_LOCATION_CLIENT_AREA) {
Jason Ekstrand7744f712013-10-27 22:24:55 -05001373 wl_pointer_set_cursor(input->parent.pointer,
1374 input->enter_serial, NULL, 0, 0);
1375 notify_pointer_focus(&input->base, &input->output->base, x, y);
Derek Foreman4bcc54d2015-11-06 15:56:06 -06001376 input->has_focus = true;
Peter Hutterer87743e92016-01-18 16:38:22 +10001377 want_frame = true;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001378 }
1379
Peter Hutterer87743e92016-01-18 16:38:22 +10001380 if (location == THEME_LOCATION_CLIENT_AREA) {
Jason Ekstrand7744f712013-10-27 22:24:55 -05001381 notify_motion_absolute(&input->base, time, x, y);
Peter Hutterer87743e92016-01-18 16:38:22 +10001382 want_frame = true;
1383 }
1384
1385 if (want_frame && input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
1386 notify_pointer_frame(&input->base);
Daniel Stone37816df2012-05-16 18:45:18 +01001387}
1388
1389static void
1390input_handle_button(void *data, struct wl_pointer *pointer,
Daniel Stone4dbadb12012-05-30 16:31:51 +01001391 uint32_t serial, uint32_t time, uint32_t button,
1392 uint32_t state_w)
Daniel Stone37816df2012-05-16 18:45:18 +01001393{
1394 struct wayland_input *input = data;
Daniel Stone4dbadb12012-05-30 16:31:51 +01001395 enum wl_pointer_button_state state = state_w;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001396 enum frame_button_state fstate;
1397 enum theme_location location;
Daniel Stone37816df2012-05-16 18:45:18 +01001398
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001399 if (!input->output)
1400 return;
1401
Jason Ekstrand7744f712013-10-27 22:24:55 -05001402 if (input->output->frame) {
1403 fstate = state == WL_POINTER_BUTTON_STATE_PRESSED ?
1404 FRAME_BUTTON_PRESSED : FRAME_BUTTON_RELEASED;
1405
1406 location = frame_pointer_button(input->output->frame, input,
1407 button, fstate);
1408
1409 if (frame_status(input->output->frame) & FRAME_STATUS_MOVE) {
1410
1411 wl_shell_surface_move(input->output->parent.shell_surface,
1412 input->parent.seat, serial);
1413 frame_status_clear(input->output->frame,
1414 FRAME_STATUS_MOVE);
1415 return;
1416 }
1417
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001418 if (frame_status(input->output->frame) & FRAME_STATUS_CLOSE) {
1419 wayland_output_destroy(&input->output->base);
Dima Ryazanovb7e70af2015-05-20 01:03:53 -07001420 input->output = NULL;
1421 input->keyboard_focus = NULL;
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001422
Giulio Camuffo954f1832014-10-11 18:27:30 +03001423 if (wl_list_empty(&input->backend->compositor->output_list))
Giulio Camuffo459137b2014-10-11 23:56:24 +03001424 weston_compositor_exit(input->backend->compositor);
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001425
1426 return;
1427 }
Jason Ekstrand7744f712013-10-27 22:24:55 -05001428
1429 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1430 weston_output_schedule_repaint(&input->output->base);
1431 } else {
1432 location = THEME_LOCATION_CLIENT_AREA;
1433 }
1434
Peter Hutterer87743e92016-01-18 16:38:22 +10001435 if (location == THEME_LOCATION_CLIENT_AREA) {
Jason Ekstrand7744f712013-10-27 22:24:55 -05001436 notify_button(&input->base, time, button, state);
Peter Hutterer87743e92016-01-18 16:38:22 +10001437 if (input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
1438 notify_pointer_frame(&input->base);
1439 }
Daniel Stone37816df2012-05-16 18:45:18 +01001440}
1441
1442static void
1443input_handle_axis(void *data, struct wl_pointer *pointer,
Daniel Stone2fce4022012-05-30 16:32:00 +01001444 uint32_t time, uint32_t axis, wl_fixed_t value)
Daniel Stone37816df2012-05-16 18:45:18 +01001445{
1446 struct wayland_input *input = data;
Peter Hutterer89b6a492016-01-18 15:58:17 +10001447 struct weston_pointer_axis_event weston_event;
Daniel Stone37816df2012-05-16 18:45:18 +01001448
Peter Hutterer89b6a492016-01-18 15:58:17 +10001449 weston_event.axis = axis;
1450 weston_event.value = value;
1451
Peter Hutterer87743e92016-01-18 16:38:22 +10001452 if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL &&
1453 input->vert.has_discrete) {
1454 weston_event.has_discrete = true;
1455 weston_event.discrete = input->vert.discrete;
1456 input->vert.has_discrete = false;
1457 } else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL &&
1458 input->horiz.has_discrete) {
1459 weston_event.has_discrete = true;
1460 weston_event.discrete = input->horiz.discrete;
1461 input->horiz.has_discrete = false;
1462 }
1463
Peter Hutterer89b6a492016-01-18 15:58:17 +10001464 notify_axis(&input->base, time, &weston_event);
Peter Hutterer87743e92016-01-18 16:38:22 +10001465
1466 if (input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
1467 notify_pointer_frame(&input->base);
1468}
1469
1470static void
1471input_handle_frame(void *data, struct wl_pointer *pointer)
1472{
1473 struct wayland_input *input = data;
1474
1475 notify_pointer_frame(&input->base);
1476}
1477
1478static void
1479input_handle_axis_source(void *data, struct wl_pointer *pointer,
1480 uint32_t source)
1481{
1482 struct wayland_input *input = data;
1483
1484 notify_axis_source(&input->base, source);
1485}
1486
1487static void
1488input_handle_axis_stop(void *data, struct wl_pointer *pointer,
1489 uint32_t time, uint32_t axis)
1490{
1491 struct wayland_input *input = data;
1492 struct weston_pointer_axis_event weston_event;
1493
1494 weston_event.axis = axis;
1495 weston_event.value = 0;
1496
1497 notify_axis(&input->base, time, &weston_event);
1498}
1499
1500static void
1501input_handle_axis_discrete(void *data, struct wl_pointer *pointer,
1502 uint32_t axis, int32_t discrete)
1503{
1504 struct wayland_input *input = data;
1505
1506 if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
1507 input->vert.has_discrete = true;
1508 input->vert.discrete = discrete;
1509 } else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
1510 input->horiz.has_discrete = true;
1511 input->horiz.discrete = discrete;
1512 }
Daniel Stone37816df2012-05-16 18:45:18 +01001513}
1514
1515static const struct wl_pointer_listener pointer_listener = {
1516 input_handle_pointer_enter,
1517 input_handle_pointer_leave,
1518 input_handle_motion,
1519 input_handle_button,
1520 input_handle_axis,
Peter Hutterer87743e92016-01-18 16:38:22 +10001521 input_handle_frame,
1522 input_handle_axis_source,
1523 input_handle_axis_stop,
1524 input_handle_axis_discrete,
Daniel Stone37816df2012-05-16 18:45:18 +01001525};
1526
1527static void
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001528input_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format,
1529 int fd, uint32_t size)
1530{
1531 struct wayland_input *input = data;
1532 struct xkb_keymap *keymap;
1533 char *map_str;
1534
U. Artie Eoffd8d47012014-05-06 14:50:03 -07001535 if (!data) {
1536 close(fd);
1537 return;
1538 }
Jason Ekstrandb7d9f2e2014-04-02 19:53:57 -05001539
1540 if (format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
1541 map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
1542 if (map_str == MAP_FAILED) {
1543 weston_log("mmap failed: %m\n");
1544 goto error;
1545 }
1546
Giulio Camuffo954f1832014-10-11 18:27:30 +03001547 keymap = xkb_keymap_new_from_string(input->backend->compositor->xkb_context,
Ran Benita2e1968f2014-08-19 23:59:51 +03001548 map_str,
1549 XKB_KEYMAP_FORMAT_TEXT_V1,
1550 0);
Jason Ekstrandb7d9f2e2014-04-02 19:53:57 -05001551 munmap(map_str, size);
1552
1553 if (!keymap) {
1554 weston_log("failed to compile keymap\n");
1555 goto error;
1556 }
1557
1558 input->keyboard_state_update = STATE_UPDATE_NONE;
1559 } else if (format == WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP) {
1560 weston_log("No keymap provided; falling back to defalt\n");
1561 keymap = NULL;
1562 input->keyboard_state_update = STATE_UPDATE_AUTOMATIC;
1563 } else {
1564 weston_log("Invalid keymap\n");
1565 goto error;
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001566 }
1567
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001568 close(fd);
1569
Derek Foreman1281a362015-07-31 16:55:32 -05001570 if (weston_seat_get_keyboard(&input->base))
Rui Matos0c194ce2013-10-10 19:44:21 +02001571 weston_seat_update_keymap(&input->base, keymap);
1572 else
1573 weston_seat_init_keyboard(&input->base, keymap);
1574
Ran Benitac9c74152014-08-19 23:59:52 +03001575 xkb_keymap_unref(keymap);
Jason Ekstrandb7d9f2e2014-04-02 19:53:57 -05001576
1577 return;
1578
1579error:
1580 wl_keyboard_release(input->parent.keyboard);
1581 close(fd);
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001582}
1583
1584static void
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001585input_handle_keyboard_enter(void *data,
Daniel Stone37816df2012-05-16 18:45:18 +01001586 struct wl_keyboard *keyboard,
1587 uint32_t serial,
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001588 struct wl_surface *surface,
1589 struct wl_array *keys)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001590{
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -05001591 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001592 struct wayland_output *focus;
1593
1594 focus = input->keyboard_focus;
1595 if (focus) {
1596 /* This shouldn't happen */
1597 focus->keyboard_count--;
1598 if (!focus->keyboard_count && focus->frame)
1599 frame_unset_flag(focus->frame, FRAME_FLAG_ACTIVE);
1600 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
1601 weston_output_schedule_repaint(&focus->base);
1602 }
1603
1604 input->keyboard_focus = wl_surface_get_user_data(surface);
1605 input->keyboard_focus->keyboard_count++;
1606
1607 focus = input->keyboard_focus;
1608 if (focus->frame) {
1609 frame_set_flag(focus->frame, FRAME_FLAG_ACTIVE);
1610 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
1611 weston_output_schedule_repaint(&focus->base);
1612 }
1613
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -05001614
Daniel Stone50692802012-06-22 13:21:41 +01001615 /* XXX: If we get a modifier event immediately before the focus,
1616 * we should try to keep the same serial. */
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001617 notify_keyboard_focus_in(&input->base, keys,
Daniel Stoned6da09e2012-06-22 13:21:29 +01001618 STATE_UPDATE_AUTOMATIC);
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001619}
1620
1621static void
1622input_handle_keyboard_leave(void *data,
Daniel Stone37816df2012-05-16 18:45:18 +01001623 struct wl_keyboard *keyboard,
1624 uint32_t serial,
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001625 struct wl_surface *surface)
1626{
1627 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001628 struct wayland_output *focus;
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001629
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001630 notify_keyboard_focus_out(&input->base);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001631
1632 focus = input->keyboard_focus;
1633 if (!focus)
Dima Ryazanov01d5c022015-05-18 23:14:16 -07001634 return;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001635
1636 focus->keyboard_count--;
1637 if (!focus->keyboard_count && focus->frame) {
1638 frame_unset_flag(focus->frame, FRAME_FLAG_ACTIVE);
1639 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
1640 weston_output_schedule_repaint(&focus->base);
1641 }
1642
1643 input->keyboard_focus = NULL;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001644}
1645
Daniel Stone37816df2012-05-16 18:45:18 +01001646static void
1647input_handle_key(void *data, struct wl_keyboard *keyboard,
1648 uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
1649{
1650 struct wayland_input *input = data;
Daniel Stone37816df2012-05-16 18:45:18 +01001651
Daniel Stone50692802012-06-22 13:21:41 +01001652 input->key_serial = serial;
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001653 notify_key(&input->base, time, key,
Daniel Stonec9785ea2012-05-30 16:31:52 +01001654 state ? WL_KEYBOARD_KEY_STATE_PRESSED :
Daniel Stone1b4e11f2012-06-22 13:21:37 +01001655 WL_KEYBOARD_KEY_STATE_RELEASED,
Jason Ekstrandb7d9f2e2014-04-02 19:53:57 -05001656 input->keyboard_state_update);
Daniel Stone37816df2012-05-16 18:45:18 +01001657}
1658
Daniel Stone351eb612012-05-31 15:27:47 -04001659static void
Derek Foreman1281a362015-07-31 16:55:32 -05001660input_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
Daniel Stone50692802012-06-22 13:21:41 +01001661 uint32_t serial_in, uint32_t mods_depressed,
Daniel Stone351eb612012-05-31 15:27:47 -04001662 uint32_t mods_latched, uint32_t mods_locked,
1663 uint32_t group)
1664{
Derek Foreman1281a362015-07-31 16:55:32 -05001665 struct weston_keyboard *keyboard;
Daniel Stone50692802012-06-22 13:21:41 +01001666 struct wayland_input *input = data;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001667 struct wayland_backend *b = input->backend;
Daniel Stone50692802012-06-22 13:21:41 +01001668 uint32_t serial_out;
1669
1670 /* If we get a key event followed by a modifier event with the
1671 * same serial number, then we try to preserve those semantics by
1672 * reusing the same serial number on the way out too. */
1673 if (serial_in == input->key_serial)
Giulio Camuffo954f1832014-10-11 18:27:30 +03001674 serial_out = wl_display_get_serial(b->compositor->wl_display);
Daniel Stone50692802012-06-22 13:21:41 +01001675 else
Giulio Camuffo954f1832014-10-11 18:27:30 +03001676 serial_out = wl_display_next_serial(b->compositor->wl_display);
Daniel Stone50692802012-06-22 13:21:41 +01001677
Derek Foreman1281a362015-07-31 16:55:32 -05001678 keyboard = weston_seat_get_keyboard(&input->base);
1679 xkb_state_update_mask(keyboard->xkb_state.state,
Daniel Stone50692802012-06-22 13:21:41 +01001680 mods_depressed, mods_latched,
1681 mods_locked, 0, 0, group);
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001682 notify_modifiers(&input->base, serial_out);
Daniel Stone351eb612012-05-31 15:27:47 -04001683}
1684
Jonny Lamb497994a2014-08-12 14:58:26 +02001685static void
1686input_handle_repeat_info(void *data, struct wl_keyboard *keyboard,
1687 int32_t rate, int32_t delay)
1688{
1689 struct wayland_input *input = data;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001690 struct wayland_backend *b = input->backend;
Jonny Lamb497994a2014-08-12 14:58:26 +02001691
Giulio Camuffo954f1832014-10-11 18:27:30 +03001692 b->compositor->kb_repeat_rate = rate;
1693 b->compositor->kb_repeat_delay = delay;
Jonny Lamb497994a2014-08-12 14:58:26 +02001694}
1695
Daniel Stone37816df2012-05-16 18:45:18 +01001696static const struct wl_keyboard_listener keyboard_listener = {
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001697 input_handle_keymap,
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001698 input_handle_keyboard_enter,
1699 input_handle_keyboard_leave,
Daniel Stone37816df2012-05-16 18:45:18 +01001700 input_handle_key,
Daniel Stone351eb612012-05-31 15:27:47 -04001701 input_handle_modifiers,
Jonny Lamb497994a2014-08-12 14:58:26 +02001702 input_handle_repeat_info,
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001703};
1704
1705static void
Derek Foreman748c6952015-11-06 15:56:10 -06001706input_handle_touch_down(void *data, struct wl_touch *wl_touch,
1707 uint32_t serial, uint32_t time,
1708 struct wl_surface *surface, int32_t id, wl_fixed_t x,
1709 wl_fixed_t y)
1710{
1711 struct wayland_input *input = data;
1712 struct wayland_output *output;
1713 enum theme_location location;
1714 bool first_touch;
1715 int32_t fx, fy;
1716
1717 first_touch = (input->touch_points == 0);
1718 input->touch_points++;
1719
1720 input->touch_focus = wl_surface_get_user_data(surface);
1721 output = input->touch_focus;
1722 if (!first_touch && !input->touch_active)
1723 return;
1724
1725 if (output->frame) {
1726 location = frame_touch_down(output->frame, input, id,
1727 wl_fixed_to_int(x),
1728 wl_fixed_to_int(y));
1729
1730 frame_interior(output->frame, &fx, &fy, NULL, NULL);
1731 x -= wl_fixed_from_int(fx);
1732 y -= wl_fixed_from_int(fy);
1733
1734 if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
1735 weston_output_schedule_repaint(&output->base);
1736
1737 if (first_touch && (frame_status(output->frame) & FRAME_STATUS_MOVE)) {
1738 input->touch_points--;
1739 wl_shell_surface_move(output->parent.shell_surface,
1740 input->parent.seat, serial);
1741 frame_status_clear(output->frame,
1742 FRAME_STATUS_MOVE);
1743 return;
1744 }
1745
1746 if (first_touch && location != THEME_LOCATION_CLIENT_AREA)
1747 return;
1748 }
1749
1750 weston_output_transform_coordinate(&output->base, x, y, &x, &y);
1751
1752 notify_touch(&input->base, time, id, x, y, WL_TOUCH_DOWN);
1753 input->touch_active = true;
1754}
1755
1756static void
1757input_handle_touch_up(void *data, struct wl_touch *wl_touch,
1758 uint32_t serial, uint32_t time, int32_t id)
1759{
1760 struct wayland_input *input = data;
1761 struct wayland_output *output = input->touch_focus;
1762 bool active = input->touch_active;
1763
1764 input->touch_points--;
1765 if (input->touch_points == 0) {
1766 input->touch_focus = NULL;
1767 input->touch_active = false;
1768 }
1769
1770 if (!output)
1771 return;
1772
1773 if (output->frame) {
1774 frame_touch_up(output->frame, input, id);
1775
1776 if (frame_status(output->frame) & FRAME_STATUS_CLOSE) {
1777 wayland_output_destroy(&output->base);
1778 input->touch_focus = NULL;
1779 input->keyboard_focus = NULL;
1780 if (wl_list_empty(&input->backend->compositor->output_list))
1781 weston_compositor_exit(input->backend->compositor);
1782
1783 return;
1784 }
1785 if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
1786 weston_output_schedule_repaint(&output->base);
1787 }
1788
1789 if (active)
1790 notify_touch(&input->base, time, id, 0, 0, WL_TOUCH_UP);
1791}
1792
1793static void
1794input_handle_touch_motion(void *data, struct wl_touch *wl_touch,
1795 uint32_t time, int32_t id, wl_fixed_t x,
1796 wl_fixed_t y)
1797{
1798 struct wayland_input *input = data;
1799 struct wayland_output *output = input->touch_focus;
1800 int32_t fx, fy;
1801
1802 if (!output || !input->touch_active)
1803 return;
1804
1805 if (output->frame) {
1806 frame_interior(output->frame, &fx, &fy, NULL, NULL);
1807 x -= wl_fixed_from_int(fx);
1808 y -= wl_fixed_from_int(fy);
1809 }
1810
1811 weston_output_transform_coordinate(&output->base, x, y, &x, &y);
1812
1813 notify_touch(&input->base, time, id, x, y, WL_TOUCH_MOTION);
1814}
1815
1816static void
1817input_handle_touch_frame(void *data, struct wl_touch *wl_touch)
1818{
1819 struct wayland_input *input = data;
1820
1821 if (!input->touch_focus || !input->touch_active)
1822 return;
1823
1824 notify_touch_frame(&input->base);
1825}
1826
1827static void
1828input_handle_touch_cancel(void *data, struct wl_touch *wl_touch)
1829{
1830 struct wayland_input *input = data;
1831
1832 if (!input->touch_focus || !input->touch_active)
1833 return;
1834
1835 notify_touch_cancel(&input->base);
1836}
1837
1838static const struct wl_touch_listener touch_listener = {
1839 input_handle_touch_down,
1840 input_handle_touch_up,
1841 input_handle_touch_motion,
1842 input_handle_touch_frame,
1843 input_handle_touch_cancel,
1844};
1845
1846
1847static void
Daniel Stone37816df2012-05-16 18:45:18 +01001848input_handle_capabilities(void *data, struct wl_seat *seat,
1849 enum wl_seat_capability caps)
1850{
1851 struct wayland_input *input = data;
1852
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001853 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->parent.pointer) {
1854 input->parent.pointer = wl_seat_get_pointer(seat);
1855 wl_pointer_set_user_data(input->parent.pointer, input);
1856 wl_pointer_add_listener(input->parent.pointer,
1857 &pointer_listener, input);
Kristian Høgsberg7af7ced2012-08-10 10:01:33 -04001858 weston_seat_init_pointer(&input->base);
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001859 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->parent.pointer) {
Derek Foremancfce7d02015-11-06 15:56:08 -06001860 if (input->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION)
1861 wl_pointer_release(input->parent.pointer);
1862 else
1863 wl_pointer_destroy(input->parent.pointer);
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001864 input->parent.pointer = NULL;
Derek Foremancfce7d02015-11-06 15:56:08 -06001865 weston_seat_release_pointer(&input->base);
Daniel Stone37816df2012-05-16 18:45:18 +01001866 }
1867
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001868 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->parent.keyboard) {
1869 input->parent.keyboard = wl_seat_get_keyboard(seat);
1870 wl_keyboard_set_user_data(input->parent.keyboard, input);
1871 wl_keyboard_add_listener(input->parent.keyboard,
1872 &keyboard_listener, input);
1873 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->parent.keyboard) {
Derek Foremancfce7d02015-11-06 15:56:08 -06001874 if (input->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
1875 wl_keyboard_release(input->parent.keyboard);
1876 else
1877 wl_keyboard_destroy(input->parent.keyboard);
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001878 input->parent.keyboard = NULL;
Derek Foremancfce7d02015-11-06 15:56:08 -06001879 weston_seat_release_keyboard(&input->base);
Daniel Stone37816df2012-05-16 18:45:18 +01001880 }
Derek Foreman748c6952015-11-06 15:56:10 -06001881
1882 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->parent.touch) {
1883 input->parent.touch = wl_seat_get_touch(seat);
1884 wl_touch_set_user_data(input->parent.touch, input);
1885 wl_touch_add_listener(input->parent.touch,
1886 &touch_listener, input);
1887 weston_seat_init_touch(&input->base);
1888 } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->parent.touch) {
1889 if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION)
1890 wl_touch_release(input->parent.touch);
1891 else
1892 wl_touch_destroy(input->parent.touch);
1893 input->parent.touch = NULL;
1894 weston_seat_release_touch(&input->base);
1895 }
Daniel Stone37816df2012-05-16 18:45:18 +01001896}
1897
Jonny Lamb497994a2014-08-12 14:58:26 +02001898static void
1899input_handle_name(void *data, struct wl_seat *seat,
1900 const char *name)
1901{
1902}
1903
Daniel Stone37816df2012-05-16 18:45:18 +01001904static const struct wl_seat_listener seat_listener = {
1905 input_handle_capabilities,
Jonny Lamb497994a2014-08-12 14:58:26 +02001906 input_handle_name,
Daniel Stone37816df2012-05-16 18:45:18 +01001907};
1908
1909static void
Derek Foremancfce7d02015-11-06 15:56:08 -06001910display_add_seat(struct wayland_backend *b, uint32_t id, uint32_t available_version)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001911{
1912 struct wayland_input *input;
Derek Foremancfce7d02015-11-06 15:56:08 -06001913 uint32_t version = MIN(available_version, 4);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001914
Peter Huttererf3d62272013-08-08 11:57:05 +10001915 input = zalloc(sizeof *input);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001916 if (input == NULL)
1917 return;
1918
Giulio Camuffo954f1832014-10-11 18:27:30 +03001919 weston_seat_init(&input->base, b->compositor, "default");
1920 input->backend = b;
1921 input->parent.seat = wl_registry_bind(b->parent.registry, id,
Derek Foremancfce7d02015-11-06 15:56:08 -06001922 &wl_seat_interface, version);
1923 input->seat_version = version;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001924 wl_list_insert(b->input_list.prev, &input->link);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001925
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001926 wl_seat_add_listener(input->parent.seat, &seat_listener, input);
1927 wl_seat_set_user_data(input->parent.seat, input);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001928
1929 input->parent.cursor.surface =
Giulio Camuffo954f1832014-10-11 18:27:30 +03001930 wl_compositor_create_surface(b->parent.compositor);
Peter Hutterer87743e92016-01-18 16:38:22 +10001931
1932 input->vert.axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
1933 input->horiz.axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001934}
1935
1936static void
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05001937wayland_parent_output_geometry(void *data, struct wl_output *output_proxy,
1938 int32_t x, int32_t y,
1939 int32_t physical_width, int32_t physical_height,
1940 int32_t subpixel, const char *make,
1941 const char *model, int32_t transform)
1942{
1943 struct wayland_parent_output *output = data;
1944
1945 output->x = x;
1946 output->y = y;
1947 output->physical.width = physical_width;
1948 output->physical.height = physical_height;
1949 output->physical.subpixel = subpixel;
1950
1951 free(output->physical.make);
1952 output->physical.make = strdup(make);
1953 free(output->physical.model);
1954 output->physical.model = strdup(model);
1955
1956 output->transform = transform;
1957}
1958
1959static struct weston_mode *
1960find_mode(struct wl_list *list, int32_t width, int32_t height, uint32_t refresh)
1961{
1962 struct weston_mode *mode;
1963
1964 wl_list_for_each(mode, list, link) {
1965 if (mode->width == width && mode->height == height &&
1966 mode->refresh == refresh)
1967 return mode;
1968 }
1969
1970 mode = zalloc(sizeof *mode);
1971 if (!mode)
1972 return NULL;
1973
1974 mode->width = width;
1975 mode->height = height;
1976 mode->refresh = refresh;
1977 wl_list_insert(list, &mode->link);
1978
1979 return mode;
1980}
1981
1982static void
1983wayland_parent_output_mode(void *data, struct wl_output *wl_output_proxy,
1984 uint32_t flags, int32_t width, int32_t height,
1985 int32_t refresh)
1986{
1987 struct wayland_parent_output *output = data;
1988 struct weston_mode *mode;
1989
1990 if (output->output) {
1991 mode = find_mode(&output->output->base.mode_list,
1992 width, height, refresh);
1993 if (!mode)
1994 return;
1995 mode->flags = flags;
1996 /* Do a mode-switch on current mode change? */
1997 } else {
1998 mode = find_mode(&output->mode_list, width, height, refresh);
1999 if (!mode)
2000 return;
2001 mode->flags = flags;
2002 if (flags & WL_OUTPUT_MODE_CURRENT)
2003 output->current_mode = mode;
2004 if (flags & WL_OUTPUT_MODE_PREFERRED)
2005 output->preferred_mode = mode;
2006 }
2007}
2008
2009static const struct wl_output_listener output_listener = {
2010 wayland_parent_output_geometry,
2011 wayland_parent_output_mode
2012};
2013
2014static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03002015wayland_backend_register_output(struct wayland_backend *b, uint32_t id)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002016{
2017 struct wayland_parent_output *output;
2018
2019 output = zalloc(sizeof *output);
2020 if (!output)
2021 return;
2022
2023 output->id = id;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002024 output->global = wl_registry_bind(b->parent.registry, id,
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002025 &wl_output_interface, 1);
U. Artie Eoff8cbd8f32014-05-06 14:50:01 -07002026 if (!output->global) {
2027 free(output);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002028 return;
U. Artie Eoff8cbd8f32014-05-06 14:50:01 -07002029 }
2030
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002031 wl_output_add_listener(output->global, &output_listener, output);
2032
2033 output->scale = 0;
2034 output->transform = WL_OUTPUT_TRANSFORM_NORMAL;
2035 output->physical.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
2036 wl_list_init(&output->mode_list);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002037 wl_list_insert(&b->parent.output_list, &output->link);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002038
Giulio Camuffo954f1832014-10-11 18:27:30 +03002039 if (b->sprawl_across_outputs) {
2040 wl_display_roundtrip(b->parent.wl_display);
2041 wayland_output_create_for_parent_output(b, output);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002042 }
2043}
2044
2045static void
2046wayland_parent_output_destroy(struct wayland_parent_output *output)
2047{
2048 struct weston_mode *mode, *next;
2049
2050 if (output->output)
2051 wayland_output_destroy(&output->output->base);
2052
2053 wl_output_destroy(output->global);
2054 free(output->physical.make);
2055 free(output->physical.model);
2056
2057 wl_list_for_each_safe(mode, next, &output->mode_list, link) {
2058 wl_list_remove(&mode->link);
2059 free(mode);
2060 }
2061}
2062
2063static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04002064registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
2065 const char *interface, uint32_t version)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002066{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002067 struct wayland_backend *b = data;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002068
Benjamin Franzke080ab6c2011-04-30 10:41:27 +02002069 if (strcmp(interface, "wl_compositor") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002070 b->parent.compositor =
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04002071 wl_registry_bind(registry, name,
2072 &wl_compositor_interface, 1);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +02002073 } else if (strcmp(interface, "wl_shell") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002074 b->parent.shell =
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04002075 wl_registry_bind(registry, name,
2076 &wl_shell_interface, 1);
Jonas Ådahl496adb32015-11-17 16:00:27 +08002077 } else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002078 b->parent.fshell =
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002079 wl_registry_bind(registry, name,
Jonas Ådahl496adb32015-11-17 16:00:27 +08002080 &zwp_fullscreen_shell_v1_interface, 1);
Daniel Stone725c2c32012-06-22 14:04:36 +01002081 } else if (strcmp(interface, "wl_seat") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002082 display_add_seat(b, name, version);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002083 } else if (strcmp(interface, "wl_output") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002084 wayland_backend_register_output(b, name);
Jonas Ådahle5a12252013-04-05 23:07:11 +02002085 } else if (strcmp(interface, "wl_shm") == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002086 b->parent.shm =
Jonas Ådahle5a12252013-04-05 23:07:11 +02002087 wl_registry_bind(registry, name, &wl_shm_interface, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002088 }
2089}
2090
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002091static void
2092registry_handle_global_remove(void *data, struct wl_registry *registry,
2093 uint32_t name)
2094{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002095 struct wayland_backend *b = data;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002096 struct wayland_parent_output *output;
2097
Giulio Camuffo954f1832014-10-11 18:27:30 +03002098 wl_list_for_each(output, &b->parent.output_list, link)
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002099 if (output->id == name)
2100 wayland_parent_output_destroy(output);
2101}
2102
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04002103static const struct wl_registry_listener registry_listener = {
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002104 registry_handle_global,
2105 registry_handle_global_remove
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04002106};
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002107
Kristian Høgsberg95d843d2011-04-22 13:01:26 -04002108static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03002109wayland_backend_handle_event(int fd, uint32_t mask, void *data)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002110{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002111 struct wayland_backend *b = data;
Kristian Høgsbergfeb3c1d2012-10-15 12:56:11 -04002112 int count = 0;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002113
Kristian Høgsberg453de7a2013-10-30 23:15:44 -07002114 if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
Giulio Camuffo459137b2014-10-11 23:56:24 +03002115 weston_compositor_exit(b->compositor);
Kristian Høgsberg453de7a2013-10-30 23:15:44 -07002116 return 0;
2117 }
2118
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002119 if (mask & WL_EVENT_READABLE)
Giulio Camuffo954f1832014-10-11 18:27:30 +03002120 count = wl_display_dispatch(b->parent.wl_display);
Kristian Høgsbergf258a312011-12-28 22:51:20 -05002121 if (mask & WL_EVENT_WRITABLE)
Giulio Camuffo954f1832014-10-11 18:27:30 +03002122 wl_display_flush(b->parent.wl_display);
Kristian Høgsberg95d843d2011-04-22 13:01:26 -04002123
Kristian Høgsbergfeb3c1d2012-10-15 12:56:11 -04002124 if (mask == 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002125 count = wl_display_dispatch_pending(b->parent.wl_display);
2126 wl_display_flush(b->parent.wl_display);
Kristian Høgsbergfeb3c1d2012-10-15 12:56:11 -04002127 }
2128
2129 return count;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002130}
2131
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05002132static void
Kristian Høgsberg7b884bc2012-07-31 14:32:01 -04002133wayland_restore(struct weston_compositor *ec)
2134{
2135}
2136
2137static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002138wayland_destroy(struct weston_compositor *ec)
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05002139{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002140 struct wayland_backend *b = (struct wayland_backend *) ec->backend;
Jonas Ådahle5a12252013-04-05 23:07:11 +02002141
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002142 weston_compositor_shutdown(ec);
Matt Roper361d2ad2011-08-29 13:52:23 -07002143
Giulio Camuffo954f1832014-10-11 18:27:30 +03002144 if (b->parent.shm)
2145 wl_shm_destroy(b->parent.shm);
Jonas Ådahle5a12252013-04-05 23:07:11 +02002146
Giulio Camuffo954f1832014-10-11 18:27:30 +03002147 free(b);
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05002148}
2149
Jason Ekstrand7744f712013-10-27 22:24:55 -05002150static const char *left_ptrs[] = {
2151 "left_ptr",
2152 "default",
2153 "top_left_arrow",
2154 "left-arrow"
2155};
2156
2157static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03002158create_cursor(struct wayland_backend *b, struct weston_config *config)
Jason Ekstrand7744f712013-10-27 22:24:55 -05002159{
2160 struct weston_config_section *s;
2161 int size;
2162 char *theme = NULL;
2163 unsigned int i;
2164
2165 s = weston_config_get_section(config, "shell", NULL, NULL);
2166 weston_config_section_get_string(s, "cursor-theme", &theme, NULL);
2167 weston_config_section_get_int(s, "cursor-size", &size, 32);
2168
Giulio Camuffo954f1832014-10-11 18:27:30 +03002169 b->cursor_theme = wl_cursor_theme_load(theme, size, b->parent.shm);
2170 if (!b->cursor_theme) {
Hardening842a36a2014-03-18 14:12:50 +01002171 fprintf(stderr, "could not load cursor theme\n");
2172 return;
2173 }
Jason Ekstrand7744f712013-10-27 22:24:55 -05002174
U. Artie Eoffff755002014-01-17 12:36:58 -08002175 free(theme);
2176
Giulio Camuffo954f1832014-10-11 18:27:30 +03002177 b->cursor = NULL;
2178 for (i = 0; !b->cursor && i < ARRAY_LENGTH(left_ptrs); ++i)
2179 b->cursor = wl_cursor_theme_get_cursor(b->cursor_theme,
Jason Ekstrand7744f712013-10-27 22:24:55 -05002180 left_ptrs[i]);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002181 if (!b->cursor) {
Jason Ekstrand7744f712013-10-27 22:24:55 -05002182 fprintf(stderr, "could not load left cursor\n");
2183 return;
2184 }
2185}
2186
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002187static void
Derek Foreman8ae2db52015-07-15 13:00:36 -05002188fullscreen_binding(struct weston_keyboard *keyboard, uint32_t time,
2189 uint32_t key, void *data)
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002190{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002191 struct wayland_backend *b = data;
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002192 struct wayland_input *input = NULL;
2193
Giulio Camuffo954f1832014-10-11 18:27:30 +03002194 wl_list_for_each(input, &b->input_list, link)
Derek Foreman8ae2db52015-07-15 13:00:36 -05002195 if (&input->base == keyboard->seat)
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002196 break;
2197
2198 if (!input || !input->output)
2199 return;
2200
2201 if (input->output->frame)
2202 wayland_output_set_fullscreen(input->output, 0, 0, NULL);
2203 else
2204 wayland_output_set_windowed(input->output);
2205
2206 weston_output_schedule_repaint(&input->output->base);
2207}
2208
Giulio Camuffo954f1832014-10-11 18:27:30 +03002209static struct wayland_backend *
2210wayland_backend_create(struct weston_compositor *compositor, int use_pixman,
2211 const char *display_name, int *argc, char *argv[],
2212 struct weston_config *config)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002213{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002214 struct wayland_backend *b;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002215 struct wl_event_loop *loop;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002216 int fd;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002217
Giulio Camuffo954f1832014-10-11 18:27:30 +03002218 b = zalloc(sizeof *b);
2219 if (b == NULL)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002220 return NULL;
2221
Giulio Camuffo954f1832014-10-11 18:27:30 +03002222 b->compositor = compositor;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002223 if (weston_compositor_set_presentation_clock_software(compositor) < 0)
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04002224 goto err_compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002225
Giulio Camuffo954f1832014-10-11 18:27:30 +03002226 b->parent.wl_display = wl_display_connect(display_name);
2227 if (b->parent.wl_display == NULL) {
Martin Minarik6d118362012-06-07 18:01:59 +02002228 weston_log("failed to create display: %m\n");
Martin Olssonc5db50f2012-07-08 03:03:43 +02002229 goto err_compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002230 }
2231
Giulio Camuffo954f1832014-10-11 18:27:30 +03002232 wl_list_init(&b->parent.output_list);
2233 wl_list_init(&b->input_list);
2234 b->parent.registry = wl_display_get_registry(b->parent.wl_display);
2235 wl_registry_add_listener(b->parent.registry, &registry_listener, b);
2236 wl_display_roundtrip(b->parent.wl_display);
Jason Ekstrand7744f712013-10-27 22:24:55 -05002237
Giulio Camuffo954f1832014-10-11 18:27:30 +03002238 create_cursor(b, config);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002239
Giulio Camuffo954f1832014-10-11 18:27:30 +03002240 b->use_pixman = use_pixman;
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03002241
Giulio Camuffo954f1832014-10-11 18:27:30 +03002242 if (!b->use_pixman) {
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002243 gl_renderer = weston_load_module("gl-renderer.so",
2244 "gl_renderer_interface");
2245 if (!gl_renderer)
Giulio Camuffo954f1832014-10-11 18:27:30 +03002246 b->use_pixman = 1;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002247 }
2248
Giulio Camuffo954f1832014-10-11 18:27:30 +03002249 if (!b->use_pixman) {
2250 if (gl_renderer->create(compositor,
Derek Foremane76f1852015-05-15 12:12:39 -05002251 EGL_PLATFORM_WAYLAND_KHR,
Giulio Camuffo954f1832014-10-11 18:27:30 +03002252 b->parent.wl_display,
Derek Foremane76f1852015-05-15 12:12:39 -05002253 gl_renderer->alpha_attribs,
2254 NULL,
2255 0) < 0) {
Jason Ekstrandff2fd462013-10-27 22:24:58 -05002256 weston_log("Failed to initialize the GL renderer; "
2257 "falling back to pixman.\n");
Giulio Camuffo954f1832014-10-11 18:27:30 +03002258 b->use_pixman = 1;
Jason Ekstrandff2fd462013-10-27 22:24:58 -05002259 }
2260 }
2261
Giulio Camuffo954f1832014-10-11 18:27:30 +03002262 if (b->use_pixman) {
2263 if (pixman_renderer_init(compositor) < 0) {
Jason Ekstrandff2fd462013-10-27 22:24:58 -05002264 weston_log("Failed to initialize pixman renderer\n");
2265 goto err_display;
2266 }
2267 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002268
Giulio Camuffo954f1832014-10-11 18:27:30 +03002269 b->base.destroy = wayland_destroy;
2270 b->base.restore = wayland_restore;
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +01002271
Giulio Camuffo954f1832014-10-11 18:27:30 +03002272 loop = wl_display_get_event_loop(compositor->wl_display);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002273
Giulio Camuffo954f1832014-10-11 18:27:30 +03002274 fd = wl_display_get_fd(b->parent.wl_display);
2275 b->parent.wl_source =
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002276 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
Giulio Camuffo954f1832014-10-11 18:27:30 +03002277 wayland_backend_handle_event, b);
2278 if (b->parent.wl_source == NULL)
Dawid Gajownik82d49252015-07-31 00:02:28 -03002279 goto err_display;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002280
Giulio Camuffo954f1832014-10-11 18:27:30 +03002281 wl_event_source_check(b->parent.wl_source);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002282
Emmanuel Gil Peyrotc59f18e2015-09-25 11:58:40 +02002283 if (compositor->renderer->import_dmabuf) {
2284 if (linux_dmabuf_setup(compositor) < 0)
2285 weston_log("Error: initializing dmabuf "
2286 "support failed.\n");
2287 }
2288
Giulio Camuffo954f1832014-10-11 18:27:30 +03002289 compositor->backend = &b->base;
2290 return b;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002291err_display:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002292 wl_display_disconnect(b->parent.wl_display);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002293err_compositor:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002294 weston_compositor_shutdown(compositor);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002295 free(b);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002296 return NULL;
2297}
2298
2299static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03002300wayland_backend_destroy(struct wayland_backend *b)
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002301{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002302 wl_display_disconnect(b->parent.wl_display);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002303
Giulio Camuffo954f1832014-10-11 18:27:30 +03002304 if (b->theme)
2305 theme_destroy(b->theme);
2306 if (b->frame_device)
2307 cairo_device_destroy(b->frame_device);
2308 wl_cursor_theme_destroy(b->cursor_theme);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002309
Giulio Camuffo954f1832014-10-11 18:27:30 +03002310 weston_compositor_shutdown(b->compositor);
2311 free(b);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002312}
2313
Giulio Camuffo954f1832014-10-11 18:27:30 +03002314WL_EXPORT int
2315backend_init(struct weston_compositor *compositor, int *argc, char *argv[],
Giulio Camuffo93daabb2015-10-17 19:24:14 +03002316 struct weston_config *config,
2317 struct weston_backend_config *config_base)
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002318{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002319 struct wayland_backend *b;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002320 struct wayland_output *output;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002321 struct wayland_parent_output *poutput;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002322 struct weston_config_section *section;
Jason Ekstrande4ca8b02014-04-02 19:53:55 -05002323 int x, count, width, height, scale, use_pixman, fullscreen, sprawl;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002324 const char *section_name, *display_name;
2325 char *name;
2326
2327 const struct weston_option wayland_options[] = {
2328 { WESTON_OPTION_INTEGER, "width", 0, &width },
2329 { WESTON_OPTION_INTEGER, "height", 0, &height },
Jason Ekstrand12c6dd92013-11-07 20:13:32 -06002330 { WESTON_OPTION_INTEGER, "scale", 0, &scale },
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002331 { WESTON_OPTION_STRING, "display", 0, &display_name },
2332 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &use_pixman },
2333 { WESTON_OPTION_INTEGER, "output-count", 0, &count },
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002334 { WESTON_OPTION_BOOLEAN, "fullscreen", 0, &fullscreen },
Jason Ekstrande4ca8b02014-04-02 19:53:55 -05002335 { WESTON_OPTION_BOOLEAN, "sprawl", 0, &sprawl },
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002336 };
2337
2338 width = 0;
2339 height = 0;
Jason Ekstrand12c6dd92013-11-07 20:13:32 -06002340 scale = 0;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002341 display_name = NULL;
2342 use_pixman = 0;
2343 count = 1;
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002344 fullscreen = 0;
Jason Ekstrande4ca8b02014-04-02 19:53:55 -05002345 sprawl = 0;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002346 parse_options(wayland_options,
2347 ARRAY_LENGTH(wayland_options), argc, argv);
2348
Giulio Camuffo954f1832014-10-11 18:27:30 +03002349 b = wayland_backend_create(compositor, use_pixman, display_name,
2350 argc, argv, config);
2351 if (!b)
2352 return -1;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002353
Giulio Camuffo954f1832014-10-11 18:27:30 +03002354 if (sprawl || b->parent.fshell) {
2355 b->sprawl_across_outputs = 1;
2356 wl_display_roundtrip(b->parent.wl_display);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002357
Giulio Camuffo954f1832014-10-11 18:27:30 +03002358 wl_list_for_each(poutput, &b->parent.output_list, link)
2359 wayland_output_create_for_parent_output(b, poutput);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002360
Giulio Camuffo954f1832014-10-11 18:27:30 +03002361 return 0;
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002362 }
2363
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002364 if (fullscreen) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002365 output = wayland_output_create(b, 0, 0, width, height,
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002366 NULL, 1, 0, 1);
2367 if (!output)
2368 goto err_outputs;
2369
Axel Davydd8b88d2013-11-17 21:34:16 +01002370 wayland_output_set_fullscreen(output, 0, 0, NULL);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002371 return 0;
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002372 }
2373
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002374 section = NULL;
2375 x = 0;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002376 while (weston_config_next_section(config, &section, &section_name)) {
2377 if (!section_name || strcmp(section_name, "output") != 0)
2378 continue;
2379 weston_config_section_get_string(section, "name", &name, NULL);
2380 if (name == NULL)
2381 continue;
2382
2383 if (name[0] != 'W' || name[1] != 'L') {
2384 free(name);
2385 continue;
2386 }
2387 free(name);
2388
Giulio Camuffo954f1832014-10-11 18:27:30 +03002389 output = wayland_output_create_for_config(b, section, width,
Jason Ekstrand12c6dd92013-11-07 20:13:32 -06002390 height, scale, x, 0);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002391 if (!output)
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002392 goto err_outputs;
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002393 if (wayland_output_set_windowed(output))
2394 goto err_outputs;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002395
2396 x += output->base.width;
2397 --count;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002398 }
2399
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002400 if (!width)
2401 width = 1024;
2402 if (!height)
2403 height = 640;
Jason Ekstrand12c6dd92013-11-07 20:13:32 -06002404 if (!scale)
2405 scale = 1;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002406 while (count > 0) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002407 output = wayland_output_create(b, x, 0, width, height,
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002408 NULL, 0, 0, scale);
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002409 if (!output)
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002410 goto err_outputs;
Jason Ekstrand5ea04802013-11-07 20:13:33 -06002411 if (wayland_output_set_windowed(output))
2412 goto err_outputs;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002413
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002414 x += width;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002415 --count;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002416 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002417
Giulio Camuffo954f1832014-10-11 18:27:30 +03002418 weston_compositor_add_key_binding(compositor, KEY_F,
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002419 MODIFIER_CTRL | MODIFIER_ALT,
Giulio Camuffo954f1832014-10-11 18:27:30 +03002420 fullscreen_binding, b);
Jason Ekstrand53ee0dc2014-04-02 19:53:54 -05002421
Giulio Camuffo954f1832014-10-11 18:27:30 +03002422 return 0;
Jason Ekstrand0cf39352013-11-07 20:13:31 -06002423
Jason Ekstrand48ce4212013-10-27 22:25:02 -05002424err_outputs:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002425 wayland_backend_destroy(b);
2426 return -1;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01002427}