blob: 50bcb8d580eaa7c04bfdaad810d9f78bfe04d929 [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 *
Kristian Høgsberg96aa7da2011-09-15 15:43:14 -04005 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010014 *
Kristian Høgsberg96aa7da2011-09-15 15:43:14 -040015 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010022 */
23
Daniel Stonec228e232013-05-22 18:03:19 +030024#include "config.h"
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010025
26#include <stddef.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010027#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <fcntl.h>
31#include <unistd.h>
Daniel Stoneb7452fe2012-06-01 12:14:06 +010032#include <sys/mman.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010033
Benjamin Franzkebe014562011-02-18 17:04:24 +010034#include <wayland-client.h>
35#include <wayland-egl.h>
Jason Ekstrand7744f712013-10-27 22:24:55 -050036#include <wayland-cursor.h>
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010037
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010038#include "compositor.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010039#include "gl-renderer.h"
Jason Ekstrandff2fd462013-10-27 22:24:58 -050040#include "pixman-renderer.h"
Kristian Høgsberg3c2360f2013-01-28 16:01:22 -050041#include "../shared/image-loader.h"
Jonas Ådahle5a12252013-04-05 23:07:11 +020042#include "../shared/os-compatibility.h"
Jason Ekstrand7744f712013-10-27 22:24:55 -050043#include "../shared/cairo-util.h"
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010044
Jason Ekstrand48ce4212013-10-27 22:25:02 -050045#define WINDOW_TITLE "Weston Compositor"
46
47struct wayland_backend_options {
48 int width, height;
49 char *display_name;
50 int use_pixman;
51 int count;
52};
53
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010054struct wayland_compositor {
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -050055 struct weston_compositor base;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010056
57 struct {
Kristian Høgsberg362b6722012-06-18 15:13:51 -040058 struct wl_display *wl_display;
Kristian Høgsbergfa80e112012-10-10 21:34:26 -040059 struct wl_registry *registry;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010060 struct wl_compositor *compositor;
61 struct wl_shell *shell;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010062 struct wl_output *output;
Jonas Ådahle5a12252013-04-05 23:07:11 +020063 struct wl_shm *shm;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010064
65 struct {
66 int32_t x, y, width, height;
67 } screen_allocation;
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;
74
Jason Ekstrand7744f712013-10-27 22:24:55 -050075 struct theme *theme;
76 cairo_device_t *frame_device;
77 struct wl_cursor_theme *cursor_theme;
78 struct wl_cursor *cursor;
Kristian Høgsberg546a8122012-02-01 07:45:51 -050079
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -050080 struct wl_list inputs;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010081};
82
83struct wayland_output {
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -050084 struct weston_output base;
85
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010086 struct {
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -050087 int draw_initial_frame;
88 struct wl_surface *surface;
89 struct wl_shell_surface *shell_surface;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010090 } parent;
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -050091
Jason Ekstrand7744f712013-10-27 22:24:55 -050092 int keyboard_count;
93
94 struct frame *frame;
Jason Ekstrandff2fd462013-10-27 22:24:58 -050095
Jason Ekstrand7744f712013-10-27 22:24:55 -050096 struct {
Jason Ekstrandff2fd462013-10-27 22:24:58 -050097 struct wl_egl_window *egl_window;
98 struct {
99 cairo_surface_t *top;
100 cairo_surface_t *left;
101 cairo_surface_t *right;
102 cairo_surface_t *bottom;
103 } border;
104 } gl;
105
106 struct {
107 struct wl_list buffers;
108 struct wl_list free_buffers;
109 } shm;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500110
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500111 struct weston_mode mode;
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500112 uint32_t scale;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100113};
114
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500115struct wayland_shm_buffer {
116 struct wayland_output *output;
117 struct wl_list link;
118 struct wl_list free_link;
119
120 struct wl_buffer *buffer;
121 void *data;
122 size_t size;
123 pixman_region32_t damage;
124 int frame_damaged;
125
126 pixman_image_t *pm_image;
127 cairo_surface_t *c_surface;
128};
129
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100130struct wayland_input {
Kristian Høgsberg7af7ced2012-08-10 10:01:33 -0400131 struct weston_seat base;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100132 struct wayland_compositor *compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100133 struct wl_list link;
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500134
135 struct {
136 struct wl_seat *seat;
137 struct wl_pointer *pointer;
138 struct wl_keyboard *keyboard;
139 struct wl_touch *touch;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500140
141 struct {
142 struct wl_surface *surface;
143 int32_t hx, hy;
144 } cursor;
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -0500145 } parent;
146
Daniel Stone50692802012-06-22 13:21:41 +0100147 uint32_t key_serial;
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400148 uint32_t enter_serial;
149 int focus;
150 struct wayland_output *output;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500151 struct wayland_output *keyboard_focus;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100152};
153
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300154struct gl_renderer_interface *gl_renderer;
155
Kristian Høgsberg546a8122012-02-01 07:45:51 -0500156static void
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500157wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
158{
159 cairo_surface_destroy(buffer->c_surface);
160 pixman_image_unref(buffer->pm_image);
161
162 wl_buffer_destroy(buffer->buffer);
163 munmap(buffer->data, buffer->size);
164
165 pixman_region32_fini(&buffer->damage);
166
167 wl_list_remove(&buffer->link);
168 wl_list_remove(&buffer->free_link);
169 free(buffer);
170}
171
172static void
173buffer_release(void *data, struct wl_buffer *buffer)
174{
175 struct wayland_shm_buffer *sb = data;
176
177 if (sb->output) {
178 wl_list_insert(&sb->output->shm.free_buffers, &sb->free_link);
179 } else {
180 wayland_shm_buffer_destroy(sb);
181 }
182}
183
184static const struct wl_buffer_listener buffer_listener = {
185 buffer_release
186};
187
188static struct wayland_shm_buffer *
189wayland_output_get_shm_buffer(struct wayland_output *output)
190{
191 struct wayland_compositor *c =
192 (struct wayland_compositor *) output->base.compositor;
193 struct wl_shm *shm = c->parent.shm;
194 struct wayland_shm_buffer *sb;
195
196 struct wl_shm_pool *pool;
197 int width, height, stride;
198 int32_t fx, fy;
199 int fd;
200 unsigned char *data;
201
202 if (!wl_list_empty(&output->shm.free_buffers)) {
203 sb = container_of(output->shm.free_buffers.next,
204 struct wayland_shm_buffer, free_link);
205 wl_list_remove(&sb->free_link);
206 wl_list_init(&sb->free_link);
207
208 return sb;
209 }
210
211 if (output->frame) {
212 width = frame_width(output->frame);
213 height = frame_height(output->frame);
214 } else {
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500215 width = output->base.current_mode->width;
216 height = output->base.current_mode->height;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500217 }
218
219 stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
220
221 fd = os_create_anonymous_file(height * stride);
222 if (fd < 0) {
223 perror("os_create_anonymous_file");
224 return NULL;
225 }
226
227 data = mmap(NULL, height * stride, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
228 if (data == MAP_FAILED) {
229 perror("mmap");
230 close(fd);
231 return NULL;
232 }
233
234 sb = zalloc(sizeof *sb);
235
236 sb->output = output;
237 wl_list_init(&sb->free_link);
238 wl_list_insert(&output->shm.buffers, &sb->link);
239
240 pixman_region32_init_rect(&sb->damage, 0, 0,
241 output->base.width, output->base.height);
242 sb->frame_damaged = 1;
243
244 sb->data = data;
245 sb->size = height * stride;
246
247 pool = wl_shm_create_pool(shm, fd, sb->size);
248
249 sb->buffer = wl_shm_pool_create_buffer(pool, 0,
250 width, height,
251 stride,
252 WL_SHM_FORMAT_ARGB8888);
253 wl_buffer_add_listener(sb->buffer, &buffer_listener, sb);
254 wl_shm_pool_destroy(pool);
255 close(fd);
256
257 memset(data, 0, sb->size);
258
259 sb->c_surface =
260 cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32,
261 width, height, stride);
262
263 fx = 0;
264 fy = 0;
265 if (output->frame)
266 frame_interior(output->frame, &fx, &fy, 0, 0);
267 sb->pm_image =
268 pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height,
269 (uint32_t *)(data + fy * stride) + fx,
270 stride);
271
272 return sb;
273}
274
275static void
Kristian Høgsbergcdd61d02012-02-07 09:56:15 -0500276frame_done(void *data, struct wl_callback *callback, uint32_t time)
Kristian Høgsberg33418202011-08-16 23:01:28 -0400277{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500278 struct weston_output *output = data;
Kristian Høgsberg33418202011-08-16 23:01:28 -0400279
Kristian Høgsbergcdd61d02012-02-07 09:56:15 -0500280 wl_callback_destroy(callback);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500281 weston_output_finish_frame(output, time);
Kristian Høgsberg33418202011-08-16 23:01:28 -0400282}
283
284static const struct wl_callback_listener frame_listener = {
285 frame_done
286};
287
Kristian Høgsberg06cf6b02012-01-25 23:47:45 -0500288static void
Jonas Ådahle5a12252013-04-05 23:07:11 +0200289draw_initial_frame(struct wayland_output *output)
290{
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500291 struct wayland_shm_buffer *sb;
Jonas Ådahle5a12252013-04-05 23:07:11 +0200292
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500293 sb = wayland_output_get_shm_buffer(output);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200294
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500295 /* If we are rendering with GL, then orphan it so that it gets
296 * destroyed immediately */
297 if (output->gl.egl_window)
298 sb->output = NULL;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500299
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500300 wl_surface_attach(output->parent.surface, sb->buffer, 0, 0);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200301
302 /* We only need to damage some part, as its only transparant
303 * pixels anyway. */
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500304 wl_surface_damage(output->parent.surface, 0, 0, 1, 1);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200305}
306
307static void
Jason Ekstrand7744f712013-10-27 22:24:55 -0500308wayland_output_update_gl_border(struct wayland_output *output)
309{
310 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
311 cairo_t *cr;
312
313 if (!output->frame)
314 return;
315 if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
316 return;
317
318 fwidth = frame_width(output->frame);
319 fheight = frame_height(output->frame);
320 frame_interior(output->frame, &ix, &iy, &iwidth, &iheight);
321
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500322 if (!output->gl.border.top)
323 output->gl.border.top =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500324 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
325 fwidth, iy);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500326 cr = cairo_create(output->gl.border.top);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500327 frame_repaint(output->frame, cr);
328 cairo_destroy(cr);
329 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_TOP,
330 fwidth, iy,
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500331 cairo_image_surface_get_stride(output->gl.border.top) / 4,
332 cairo_image_surface_get_data(output->gl.border.top));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500333
334
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500335 if (!output->gl.border.left)
336 output->gl.border.left =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500337 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
338 ix, 1);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500339 cr = cairo_create(output->gl.border.left);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500340 cairo_translate(cr, 0, -iy);
341 frame_repaint(output->frame, cr);
342 cairo_destroy(cr);
343 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_LEFT,
344 ix, 1,
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500345 cairo_image_surface_get_stride(output->gl.border.left) / 4,
346 cairo_image_surface_get_data(output->gl.border.left));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500347
348
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500349 if (!output->gl.border.right)
350 output->gl.border.right =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500351 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
352 fwidth - (ix + iwidth), 1);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500353 cr = cairo_create(output->gl.border.right);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500354 cairo_translate(cr, -(iwidth + ix), -iy);
355 frame_repaint(output->frame, cr);
356 cairo_destroy(cr);
357 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_RIGHT,
358 fwidth - (ix + iwidth), 1,
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500359 cairo_image_surface_get_stride(output->gl.border.right) / 4,
360 cairo_image_surface_get_data(output->gl.border.right));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500361
362
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500363 if (!output->gl.border.bottom)
364 output->gl.border.bottom =
Jason Ekstrand7744f712013-10-27 22:24:55 -0500365 cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
366 fwidth, fheight - (iy + iheight));
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500367 cr = cairo_create(output->gl.border.bottom);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500368 cairo_translate(cr, 0, -(iy + iheight));
369 frame_repaint(output->frame, cr);
370 cairo_destroy(cr);
371 gl_renderer->output_set_border(&output->base, GL_RENDERER_BORDER_BOTTOM,
372 fwidth, fheight - (iy + iheight),
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500373 cairo_image_surface_get_stride(output->gl.border.bottom) / 4,
374 cairo_image_surface_get_data(output->gl.border.bottom));
Jason Ekstrand7744f712013-10-27 22:24:55 -0500375}
376
377static void
Jonas Ådahle5a12252013-04-05 23:07:11 +0200378wayland_output_start_repaint_loop(struct weston_output *output_base)
379{
380 struct wayland_output *output = (struct wayland_output *) output_base;
Jason Ekstrand286ff682013-10-27 22:24:57 -0500381 struct wayland_compositor *wc =
382 (struct wayland_compositor *)output->base.compositor;
Jonas Ådahle5a12252013-04-05 23:07:11 +0200383 struct wl_callback *callback;
384
385 /* If this is the initial frame, we need to attach a buffer so that
386 * the compositor can map the surface and include it in its render
387 * loop. If the surface doesn't end up in the render loop, the frame
388 * callback won't be invoked. The buffer is transparent and of the
389 * same size as the future real output buffer. */
390 if (output->parent.draw_initial_frame) {
391 output->parent.draw_initial_frame = 0;
392
393 draw_initial_frame(output);
394 }
395
396 callback = wl_surface_frame(output->parent.surface);
397 wl_callback_add_listener(callback, &frame_listener, output);
398 wl_surface_commit(output->parent.surface);
Jason Ekstrand286ff682013-10-27 22:24:57 -0500399 wl_display_flush(wc->parent.wl_display);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200400}
401
David Herrmann1edf44c2013-10-22 17:11:26 +0200402static int
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500403wayland_output_repaint_gl(struct weston_output *output_base,
404 pixman_region32_t *damage)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400405{
406 struct wayland_output *output = (struct wayland_output *) output_base;
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400407 struct weston_compositor *ec = output->base.compositor;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400408 struct wl_callback *callback;
Scott Moreau062be7e2012-04-20 13:37:33 -0600409
Kristian Høgsberg33418202011-08-16 23:01:28 -0400410 callback = wl_surface_frame(output->parent.surface);
411 wl_callback_add_listener(callback, &frame_listener, output);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100412
Jason Ekstrand7744f712013-10-27 22:24:55 -0500413 wayland_output_update_gl_border(output);
414
Pekka Paalanenbc106382012-10-10 12:49:31 +0300415 ec->renderer->repaint_output(&output->base, damage);
Ander Conselvan de Oliveira0a887722012-11-22 15:57:00 +0200416
417 pixman_region32_subtract(&ec->primary_plane.damage,
418 &ec->primary_plane.damage, damage);
David Herrmann1edf44c2013-10-22 17:11:26 +0200419 return 0;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100420}
421
Matt Roper361d2ad2011-08-29 13:52:23 -0700422static void
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500423wayland_output_update_shm_border(struct wayland_shm_buffer *buffer)
424{
425 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
426 cairo_t *cr;
427
428 if (!buffer->output->frame || !buffer->frame_damaged)
429 return;
430
431 cr = cairo_create(buffer->c_surface);
432
433 frame_interior(buffer->output->frame, &ix, &iy, &iwidth, &iheight);
434 fwidth = frame_width(buffer->output->frame);
435 fheight = frame_height(buffer->output->frame);
436
437 /* Set the clip so we don't unnecisaraly damage the surface */
438 cairo_move_to(cr, ix, iy);
439 cairo_rel_line_to(cr, iwidth, 0);
440 cairo_rel_line_to(cr, 0, iheight);
441 cairo_rel_line_to(cr, -iwidth, 0);
442 cairo_line_to(cr, ix, iy);
443 cairo_line_to(cr, 0, iy);
444 cairo_line_to(cr, 0, fheight);
445 cairo_line_to(cr, fwidth, fheight);
446 cairo_line_to(cr, fwidth, 0);
447 cairo_line_to(cr, 0, 0);
448 cairo_line_to(cr, 0, iy);
449 cairo_close_path(cr);
450 cairo_clip(cr);
451
452 /* Draw using a pattern so that the final result gets clipped */
453 cairo_push_group(cr);
454 frame_repaint(buffer->output->frame, cr);
455 cairo_pop_group_to_source(cr);
456 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
457 cairo_paint(cr);
458
459 cairo_destroy(cr);
460}
461
462static void
463wayland_shm_buffer_attach(struct wayland_shm_buffer *sb)
464{
465 pixman_region32_t damage;
466 pixman_box32_t *rects;
467 int32_t ix, iy, iwidth, iheight, fwidth, fheight;
468 int i, n;
469
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500470 pixman_region32_init(&damage);
471 weston_transformed_region(sb->output->base.width,
472 sb->output->base.height,
473 sb->output->base.transform,
474 sb->output->base.current_scale,
475 &sb->damage, &damage);
476
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500477 if (sb->output->frame) {
478 frame_interior(sb->output->frame, &ix, &iy, &iwidth, &iheight);
479 fwidth = frame_width(sb->output->frame);
480 fheight = frame_height(sb->output->frame);
481
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500482 pixman_region32_translate(&damage, ix, iy);
483
484 if (sb->frame_damaged) {
485 pixman_region32_union_rect(&damage, &damage,
486 0, 0, fwidth, iy);
487 pixman_region32_union_rect(&damage, &damage,
488 0, iy, ix, iheight);
489 pixman_region32_union_rect(&damage, &damage,
490 ix + iwidth, iy,
491 fwidth - (ix + iwidth), iheight);
492 pixman_region32_union_rect(&damage, &damage,
493 0, iy + iheight,
494 fwidth, fheight - (iy + iheight));
495 }
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500496 }
497
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500498 rects = pixman_region32_rectangles(&damage, &n);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500499 wl_surface_attach(sb->output->parent.surface, sb->buffer, 0, 0);
500 for (i = 0; i < n; ++i)
501 wl_surface_damage(sb->output->parent.surface, rects[i].x1,
502 rects[i].y1, rects[i].x2 - rects[i].x1,
503 rects[i].y2 - rects[i].y1);
504
505 if (sb->output->frame)
506 pixman_region32_fini(&damage);
507}
508
509static int
510wayland_output_repaint_pixman(struct weston_output *output_base,
511 pixman_region32_t *damage)
512{
513 struct wayland_output *output = (struct wayland_output *) output_base;
514 struct wayland_compositor *c =
515 (struct wayland_compositor *)output->base.compositor;
516 struct wl_callback *callback;
517 struct wayland_shm_buffer *sb;
518
519 if (output->frame) {
520 if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
521 wl_list_for_each(sb, &output->shm.buffers, link)
522 sb->frame_damaged = 1;
523 }
524
525 wl_list_for_each(sb, &output->shm.buffers, link)
526 pixman_region32_union(&sb->damage, &sb->damage, damage);
527
528 sb = wayland_output_get_shm_buffer(output);
529
530 wayland_output_update_shm_border(sb);
531 pixman_renderer_output_set_buffer(output_base, sb->pm_image);
532 c->base.renderer->repaint_output(output_base, &sb->damage);
533
534 wayland_shm_buffer_attach(sb);
535
536 callback = wl_surface_frame(output->parent.surface);
537 wl_callback_add_listener(callback, &frame_listener, output);
538 wl_surface_commit(output->parent.surface);
539 wl_display_flush(c->parent.wl_display);
540
541 pixman_region32_fini(&sb->damage);
542 pixman_region32_init(&sb->damage);
543 sb->frame_damaged = 0;
544
545 pixman_region32_subtract(&c->base.primary_plane.damage,
546 &c->base.primary_plane.damage, damage);
547 return 0;
548}
549
550static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500551wayland_output_destroy(struct weston_output *output_base)
Matt Roper361d2ad2011-08-29 13:52:23 -0700552{
553 struct wayland_output *output = (struct wayland_output *) output_base;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500554 struct wayland_compositor *c =
555 (struct wayland_compositor *) output->base.compositor;
Matt Roper361d2ad2011-08-29 13:52:23 -0700556
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500557 if (c->use_pixman) {
558 pixman_renderer_output_destroy(output_base);
559 } else {
560 gl_renderer->output_destroy(output_base);
561 }
John Kåre Alsaker94659272012-11-13 19:10:18 +0100562
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500563 wl_egl_window_destroy(output->gl.egl_window);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500564 wl_surface_destroy(output->parent.surface);
565 wl_shell_surface_destroy(output->parent.shell_surface);
566
567 if (output->frame) {
568 frame_destroy(output->frame);
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500569 cairo_surface_destroy(output->gl.border.top);
570 cairo_surface_destroy(output->gl.border.left);
571 cairo_surface_destroy(output->gl.border.right);
572 cairo_surface_destroy(output->gl.border.bottom);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500573 }
574
575 weston_output_destroy(&output->base);
Matt Roper361d2ad2011-08-29 13:52:23 -0700576 free(output);
577
578 return;
579}
580
Ander Conselvan de Oliveira563c5b82012-06-18 17:36:21 +0300581static const struct wl_shell_surface_listener shell_surface_listener;
582
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200583static int
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500584wayland_output_init_gl_renderer(struct wayland_output *output)
585{
Jason Ekstrand00b84282013-10-27 22:24:59 -0500586 int32_t fwidth = 0, fheight = 0;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500587
588 if (output->frame) {
589 fwidth = frame_width(output->frame);
590 fheight = frame_height(output->frame);
591 } else {
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500592 fwidth = output->base.current_mode->width;
593 fheight = output->base.current_mode->height;
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500594 }
595
596 output->gl.egl_window =
597 wl_egl_window_create(output->parent.surface,
598 fwidth, fheight);
599 if (!output->gl.egl_window) {
600 weston_log("failure to create wl_egl_window\n");
601 return -1;
602 }
603
604 if (gl_renderer->output_create(&output->base,
605 output->gl.egl_window) < 0)
606 goto cleanup_window;
607
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500608 return 0;
609
610cleanup_window:
611 wl_egl_window_destroy(output->gl.egl_window);
612 return -1;
613}
614
615static int
616wayland_output_init_pixman_renderer(struct wayland_output *output)
617{
618 return pixman_renderer_output_create(&output->base);
619}
620
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500621static struct wayland_output *
622wayland_output_create(struct wayland_compositor *c, int x, int y,
623 int width, int height, const char *name,
624 uint32_t transform, int32_t scale)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100625{
626 struct wayland_output *output;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500627 int32_t fx, fy, fwidth, fheight;
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500628 int output_width, output_height;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500629 struct wl_region *region;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100630
Peter Huttererf3d62272013-08-08 11:57:05 +1000631 output = zalloc(sizeof *output);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100632 if (output == NULL)
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500633 return NULL;
634
635 output_width = width * scale;
636 output_height = height * scale;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100637
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400638 output->mode.flags =
639 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500640 output->mode.width = output_width;
641 output->mode.height = output_height;
642 output->mode.refresh = 60000;
643 output->scale = scale;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400644 wl_list_init(&output->base.mode_list);
645 wl_list_insert(&output->base.mode_list, &output->mode.link);
646
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500647 weston_log("Creating %dx%d wayland output at (%d, %d)\n",
648 width, height, x, y);
649
Hardeningff39efa2013-09-18 23:56:35 +0200650 output->base.current_mode = &output->mode;
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500651 weston_output_init(&output->base, &c->base, x, y, width, height,
652 transform, scale);
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400653
Kristian Høgsberg90bc88c2012-08-13 23:34:04 -0400654 output->base.make = "waywayland";
655 output->base.model = "none";
Kristian Høgsberg546a8122012-02-01 07:45:51 -0500656
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500657 wl_list_init(&output->shm.buffers);
658 wl_list_init(&output->shm.free_buffers);
659
Jason Ekstrand7744f712013-10-27 22:24:55 -0500660 if (!c->theme)
661 c->theme = theme_create();
662 output->frame = frame_create(c->theme, width, height,
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500663 FRAME_BUTTON_CLOSE, name);
664 frame_resize_inside(output->frame, output_width, output_height);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500665
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100666 output->parent.surface =
667 wl_compositor_create_surface(c->parent.compositor);
668 wl_surface_set_user_data(output->parent.surface, output);
669
Jason Ekstrandff2fd462013-10-27 22:24:58 -0500670 if (c->use_pixman) {
671 if (wayland_output_init_pixman_renderer(output) < 0)
672 goto cleanup_output;
673 output->base.repaint = wayland_output_repaint_pixman;
674 } else {
675 if (wayland_output_init_gl_renderer(output) < 0)
676 goto cleanup_output;
677 output->base.repaint = wayland_output_repaint_gl;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100678 }
679
Jason Ekstrand7744f712013-10-27 22:24:55 -0500680 frame_input_rect(output->frame, &fx, &fy, &fwidth, &fheight);
681 region = wl_compositor_create_region(c->parent.compositor);
682 wl_region_add(region, fx, fy, fwidth, fheight);
683 wl_surface_set_input_region(output->parent.surface, region);
684 wl_region_destroy(region);
685
686 frame_opaque_rect(output->frame, &fx, &fy, &fwidth, &fheight);
687 region = wl_compositor_create_region(c->parent.compositor);
688 wl_region_add(region, fx, fy, fwidth, fheight);
689 wl_surface_set_opaque_region(output->parent.surface, region);
690 wl_region_destroy(region);
691
Jonas Ådahle5a12252013-04-05 23:07:11 +0200692 output->parent.draw_initial_frame = 1;
Pekka Paalanen9d1613e2011-11-25 12:09:16 +0200693 output->parent.shell_surface =
694 wl_shell_get_shell_surface(c->parent.shell,
695 output->parent.surface);
Ander Conselvan de Oliveira563c5b82012-06-18 17:36:21 +0300696 wl_shell_surface_add_listener(output->parent.shell_surface,
697 &shell_surface_listener, output);
Pekka Paalanen9d1613e2011-11-25 12:09:16 +0200698 wl_shell_surface_set_toplevel(output->parent.shell_surface);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100699
Jonas Ådahle5a12252013-04-05 23:07:11 +0200700 output->base.start_repaint_loop = wayland_output_start_repaint_loop;
Matt Roper361d2ad2011-08-29 13:52:23 -0700701 output->base.destroy = wayland_output_destroy;
Jesse Barnes5308a5e2012-02-09 13:12:57 -0800702 output->base.assign_planes = NULL;
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +0200703 output->base.set_backlight = NULL;
704 output->base.set_dpms = NULL;
Alex Wu2dda6042012-04-17 17:20:47 +0800705 output->base.switch_mode = NULL;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100706
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100707 wl_list_insert(c->base.output_list.prev, &output->base.link);
708
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500709 return output;
Benjamin Franzkebe014562011-02-18 17:04:24 +0100710
Benjamin Franzkebe014562011-02-18 17:04:24 +0100711cleanup_output:
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500712 /* FIXME: cleanup weston_output */
Benjamin Franzkebe014562011-02-18 17:04:24 +0100713 free(output);
714
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500715 return NULL;
716}
717
718static struct wayland_output *
719wayland_output_create_for_config(struct wayland_compositor *c,
720 struct wayland_backend_options *options,
721 struct weston_config_section *config_section,
722 int32_t x, int32_t y)
723{
724 struct wayland_output *output;
725 char *mode, *t, *name, *str;
726 int width, height, scale;
727 uint32_t transform;
728 unsigned int i, slen;
729
730 static const struct { const char *name; uint32_t token; } transform_names[] = {
731 { "normal", WL_OUTPUT_TRANSFORM_NORMAL },
732 { "90", WL_OUTPUT_TRANSFORM_90 },
733 { "180", WL_OUTPUT_TRANSFORM_180 },
734 { "270", WL_OUTPUT_TRANSFORM_270 },
735 { "flipped", WL_OUTPUT_TRANSFORM_FLIPPED },
736 { "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
737 { "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
738 { "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
739 };
740
741 weston_config_section_get_string(config_section, "name", &name, NULL);
742 if (name) {
743 slen = strlen(name);
744 slen += strlen(WINDOW_TITLE " - ");
745 str = malloc(slen + 1);
746 if (str)
747 snprintf(str, slen + 1, WINDOW_TITLE " - %s", name);
748 free(name);
749 name = str;
750 }
751 if (!name)
752 name = WINDOW_TITLE;
753
754 weston_config_section_get_string(config_section,
755 "mode", &mode, "1024x600");
756 if (sscanf(mode, "%dx%d", &width, &height) != 2) {
757 weston_log("Invalid mode \"%s\" for output %s\n",
758 mode, name);
759 width = 1024;
760 height = 640;
761 }
762 free(mode);
763
764 if (options->width)
765 width = options->width;
766 if (options->height)
767 height = options->height;
768
769 weston_config_section_get_int(config_section, "scale", &scale, 1);
770
771 weston_config_section_get_string(config_section,
772 "transform", &t, "normal");
773 transform = WL_OUTPUT_TRANSFORM_NORMAL;
774 for (i = 0; i < ARRAY_LENGTH(transform_names); i++) {
775 if (strcmp(transform_names[i].name, t) == 0) {
776 transform = transform_names[i].token;
777 break;
778 }
779 }
780 if (i >= ARRAY_LENGTH(transform_names))
781 weston_log("Invalid transform \"%s\" for output %s\n", t, name);
782 free(t);
783
784 output = wayland_output_create(c, x, y, width, height, name, transform, scale);
785 free(name);
786
787 return output;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100788}
789
Ander Conselvan de Oliveira563c5b82012-06-18 17:36:21 +0300790static void
791shell_surface_ping(void *data, struct wl_shell_surface *shell_surface,
792 uint32_t serial)
793{
794 wl_shell_surface_pong(shell_surface, serial);
795}
796
797static void
798shell_surface_configure(void *data, struct wl_shell_surface *shell_surface,
799 uint32_t edges, int32_t width, int32_t height)
800{
801 /* FIXME: implement resizing */
802}
803
804static void
805shell_surface_popup_done(void *data, struct wl_shell_surface *shell_surface)
806{
807}
808
809static const struct wl_shell_surface_listener shell_surface_listener = {
810 shell_surface_ping,
811 shell_surface_configure,
812 shell_surface_popup_done
813};
814
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100815/* Events received from the wayland-server this compositor is client of: */
816
817/* parent output interface */
818static void
819display_handle_geometry(void *data,
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400820 struct wl_output *wl_output,
821 int x,
822 int y,
823 int physical_width,
824 int physical_height,
825 int subpixel,
826 const char *make,
Kristian Høgsberg0e696472012-07-22 15:49:57 -0400827 const char *model,
828 int transform)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100829{
830 struct wayland_compositor *c = data;
831
Kristian Høgsbergf8fc08f2010-12-01 20:10:10 -0500832 c->parent.screen_allocation.x = x;
833 c->parent.screen_allocation.y = y;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400834}
835
836static void
837display_handle_mode(void *data,
838 struct wl_output *wl_output,
839 uint32_t flags,
840 int width,
841 int height,
842 int refresh)
843{
844 struct wayland_compositor *c = data;
845
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100846 c->parent.screen_allocation.width = width;
847 c->parent.screen_allocation.height = height;
848}
849
850static const struct wl_output_listener output_listener = {
851 display_handle_geometry,
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400852 display_handle_mode
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100853};
854
Jason Ekstrand7744f712013-10-27 22:24:55 -0500855/* parent input interface */
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400856static void
Jason Ekstrand7744f712013-10-27 22:24:55 -0500857input_set_cursor(struct wayland_input *input)
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400858{
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400859
Jason Ekstrand7744f712013-10-27 22:24:55 -0500860 struct wl_buffer *buffer;
861 struct wl_cursor_image *image;
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400862
Jason Ekstrand7744f712013-10-27 22:24:55 -0500863 if (!input->compositor->cursor)
864 return; /* Couldn't load the cursor. Can't set it */
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400865
Jason Ekstrand7744f712013-10-27 22:24:55 -0500866 image = input->compositor->cursor->images[0];
867 buffer = wl_cursor_image_get_buffer(image);
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400868
Jason Ekstrand7744f712013-10-27 22:24:55 -0500869
870 wl_pointer_set_cursor(input->parent.pointer, input->enter_serial,
871 input->parent.cursor.surface,
872 image->hotspot_x, image->hotspot_y);
873
874 wl_surface_attach(input->parent.cursor.surface, buffer, 0, 0);
875 wl_surface_damage(input->parent.cursor.surface, 0, 0,
876 image->width, image->height);
877 wl_surface_commit(input->parent.cursor.surface);
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400878}
879
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100880static void
Daniel Stone37816df2012-05-16 18:45:18 +0100881input_handle_pointer_enter(void *data, struct wl_pointer *pointer,
882 uint32_t serial, struct wl_surface *surface,
Kristian Høgsberge11bbe42012-05-09 12:19:04 -0400883 wl_fixed_t x, wl_fixed_t y)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100884{
885 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500886 int32_t fx, fy;
887 enum theme_location location;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100888
Daniel Stone50692802012-06-22 13:21:41 +0100889 /* XXX: If we get a modifier event immediately before the focus,
890 * we should try to keep the same serial. */
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400891 input->enter_serial = serial;
892 input->output = wl_surface_get_user_data(surface);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500893
894 if (input->output->frame) {
895 location = frame_pointer_enter(input->output->frame, input,
896 wl_fixed_to_int(x),
897 wl_fixed_to_int(y));
898 frame_interior(input->output->frame, &fx, &fy, NULL, NULL);
899 x -= wl_fixed_from_int(fx);
900 y -= wl_fixed_from_int(fy);
901
902 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
903 weston_output_schedule_repaint(&input->output->base);
904 } else {
905 location = THEME_LOCATION_CLIENT_AREA;
906 }
907
908 x += wl_fixed_from_int(input->output->base.x);
909 y += wl_fixed_from_int(input->output->base.y);
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500910 weston_output_transform_coordinate(&input->output->base, x, y, &x, &y);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500911
912 if (location == THEME_LOCATION_CLIENT_AREA) {
913 input->focus = 1;
914 notify_pointer_focus(&input->base, &input->output->base, x, y);
915 wl_pointer_set_cursor(input->parent.pointer,
916 input->enter_serial, NULL, 0, 0);
917 } else {
918 input->focus = 0;
919 notify_pointer_focus(&input->base, NULL, 0, 0);
920 input_set_cursor(input);
921 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +0100922}
923
924static void
Daniel Stone37816df2012-05-16 18:45:18 +0100925input_handle_pointer_leave(void *data, struct wl_pointer *pointer,
926 uint32_t serial, struct wl_surface *surface)
Kristian Høgsberg06d58b72012-02-23 09:59:05 -0500927{
928 struct wayland_input *input = data;
Kristian Høgsberg06d58b72012-02-23 09:59:05 -0500929
Jason Ekstrand7744f712013-10-27 22:24:55 -0500930 if (input->output->frame) {
931 frame_pointer_leave(input->output->frame, input);
932
933 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
934 weston_output_schedule_repaint(&input->output->base);
935 }
936
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -0400937 notify_pointer_focus(&input->base, NULL, 0, 0);
Kristian Høgsberg539d85f2012-08-13 23:29:53 -0400938 input->output = NULL;
939 input->focus = 0;
Kristian Høgsberg06d58b72012-02-23 09:59:05 -0500940}
941
942static void
Daniel Stone37816df2012-05-16 18:45:18 +0100943input_handle_motion(void *data, struct wl_pointer *pointer,
944 uint32_t time, wl_fixed_t x, wl_fixed_t y)
945{
946 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500947 int32_t fx, fy;
948 enum theme_location location;
Daniel Stone37816df2012-05-16 18:45:18 +0100949
Jason Ekstrand7744f712013-10-27 22:24:55 -0500950 if (input->output->frame) {
951 location = frame_pointer_motion(input->output->frame, input,
952 wl_fixed_to_int(x),
953 wl_fixed_to_int(y));
954 frame_interior(input->output->frame, &fx, &fy, NULL, NULL);
955 x -= wl_fixed_from_int(fx);
956 y -= wl_fixed_from_int(fy);
957
958 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
959 weston_output_schedule_repaint(&input->output->base);
960 } else {
961 location = THEME_LOCATION_CLIENT_AREA;
962 }
963
964 x += wl_fixed_from_int(input->output->base.x);
965 y += wl_fixed_from_int(input->output->base.y);
Jason Ekstrand48ce4212013-10-27 22:25:02 -0500966 weston_output_transform_coordinate(&input->output->base, x, y, &x, &y);
Jason Ekstrand7744f712013-10-27 22:24:55 -0500967
968 if (input->focus && location != THEME_LOCATION_CLIENT_AREA) {
969 input_set_cursor(input);
970 notify_pointer_focus(&input->base, NULL, 0, 0);
971 input->focus = 0;
972 } else if (!input->focus && location == THEME_LOCATION_CLIENT_AREA) {
973 wl_pointer_set_cursor(input->parent.pointer,
974 input->enter_serial, NULL, 0, 0);
975 notify_pointer_focus(&input->base, &input->output->base, x, y);
976 input->focus = 1;
977 }
978
979 if (location == THEME_LOCATION_CLIENT_AREA)
980 notify_motion_absolute(&input->base, time, x, y);
Daniel Stone37816df2012-05-16 18:45:18 +0100981}
982
983static void
984input_handle_button(void *data, struct wl_pointer *pointer,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100985 uint32_t serial, uint32_t time, uint32_t button,
986 uint32_t state_w)
Daniel Stone37816df2012-05-16 18:45:18 +0100987{
988 struct wayland_input *input = data;
Daniel Stone4dbadb12012-05-30 16:31:51 +0100989 enum wl_pointer_button_state state = state_w;
Jason Ekstrand7744f712013-10-27 22:24:55 -0500990 enum frame_button_state fstate;
991 enum theme_location location;
Daniel Stone37816df2012-05-16 18:45:18 +0100992
Jason Ekstrand7744f712013-10-27 22:24:55 -0500993 if (input->output->frame) {
994 fstate = state == WL_POINTER_BUTTON_STATE_PRESSED ?
995 FRAME_BUTTON_PRESSED : FRAME_BUTTON_RELEASED;
996
997 location = frame_pointer_button(input->output->frame, input,
998 button, fstate);
999
1000 if (frame_status(input->output->frame) & FRAME_STATUS_MOVE) {
1001
1002 wl_shell_surface_move(input->output->parent.shell_surface,
1003 input->parent.seat, serial);
1004 frame_status_clear(input->output->frame,
1005 FRAME_STATUS_MOVE);
1006 return;
1007 }
1008
1009 if (frame_status(input->output->frame) & FRAME_STATUS_CLOSE)
1010 wl_display_terminate(input->compositor->base.wl_display);
1011
1012 if (frame_status(input->output->frame) & FRAME_STATUS_REPAINT)
1013 weston_output_schedule_repaint(&input->output->base);
1014 } else {
1015 location = THEME_LOCATION_CLIENT_AREA;
1016 }
1017
1018 if (location == THEME_LOCATION_CLIENT_AREA)
1019 notify_button(&input->base, time, button, state);
Daniel Stone37816df2012-05-16 18:45:18 +01001020}
1021
1022static void
1023input_handle_axis(void *data, struct wl_pointer *pointer,
Daniel Stone2fce4022012-05-30 16:32:00 +01001024 uint32_t time, uint32_t axis, wl_fixed_t value)
Daniel Stone37816df2012-05-16 18:45:18 +01001025{
1026 struct wayland_input *input = data;
Daniel Stone37816df2012-05-16 18:45:18 +01001027
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001028 notify_axis(&input->base, time, axis, value);
Daniel Stone37816df2012-05-16 18:45:18 +01001029}
1030
1031static const struct wl_pointer_listener pointer_listener = {
1032 input_handle_pointer_enter,
1033 input_handle_pointer_leave,
1034 input_handle_motion,
1035 input_handle_button,
1036 input_handle_axis,
1037};
1038
1039static void
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001040input_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format,
1041 int fd, uint32_t size)
1042{
1043 struct wayland_input *input = data;
1044 struct xkb_keymap *keymap;
1045 char *map_str;
1046
1047 if (!data) {
1048 close(fd);
1049 return;
1050 }
1051
1052 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
1053 close(fd);
1054 return;
1055 }
1056
1057 map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
1058 if (map_str == MAP_FAILED) {
1059 close(fd);
1060 return;
1061 }
1062
1063 keymap = xkb_map_new_from_string(input->compositor->base.xkb_context,
1064 map_str,
1065 XKB_KEYMAP_FORMAT_TEXT_V1,
1066 0);
1067 munmap(map_str, size);
1068 close(fd);
1069
1070 if (!keymap) {
Martin Minarik6d118362012-06-07 18:01:59 +02001071 weston_log("failed to compile keymap\n");
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001072 return;
1073 }
1074
Rui Matos0c194ce2013-10-10 19:44:21 +02001075 if (input->base.keyboard)
1076 weston_seat_update_keymap(&input->base, keymap);
1077 else
1078 weston_seat_init_keyboard(&input->base, keymap);
1079
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001080 xkb_map_unref(keymap);
1081}
1082
1083static void
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001084input_handle_keyboard_enter(void *data,
Daniel Stone37816df2012-05-16 18:45:18 +01001085 struct wl_keyboard *keyboard,
1086 uint32_t serial,
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001087 struct wl_surface *surface,
1088 struct wl_array *keys)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001089{
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -05001090 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001091 struct wayland_output *focus;
1092
1093 focus = input->keyboard_focus;
1094 if (focus) {
1095 /* This shouldn't happen */
1096 focus->keyboard_count--;
1097 if (!focus->keyboard_count && focus->frame)
1098 frame_unset_flag(focus->frame, FRAME_FLAG_ACTIVE);
1099 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
1100 weston_output_schedule_repaint(&focus->base);
1101 }
1102
1103 input->keyboard_focus = wl_surface_get_user_data(surface);
1104 input->keyboard_focus->keyboard_count++;
1105
1106 focus = input->keyboard_focus;
1107 if (focus->frame) {
1108 frame_set_flag(focus->frame, FRAME_FLAG_ACTIVE);
1109 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
1110 weston_output_schedule_repaint(&focus->base);
1111 }
1112
Kristian Høgsbergaf82bea2011-01-27 20:18:17 -05001113
Daniel Stone50692802012-06-22 13:21:41 +01001114 /* XXX: If we get a modifier event immediately before the focus,
1115 * we should try to keep the same serial. */
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001116 notify_keyboard_focus_in(&input->base, keys,
Daniel Stoned6da09e2012-06-22 13:21:29 +01001117 STATE_UPDATE_AUTOMATIC);
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001118}
1119
1120static void
1121input_handle_keyboard_leave(void *data,
Daniel Stone37816df2012-05-16 18:45:18 +01001122 struct wl_keyboard *keyboard,
1123 uint32_t serial,
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001124 struct wl_surface *surface)
1125{
1126 struct wayland_input *input = data;
Jason Ekstrand7744f712013-10-27 22:24:55 -05001127 struct wayland_output *focus;
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001128
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001129 notify_keyboard_focus_out(&input->base);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001130
1131 focus = input->keyboard_focus;
1132 if (!focus)
1133 return; /* This shouldn't happen */
1134
1135 focus->keyboard_count--;
1136 if (!focus->keyboard_count && focus->frame) {
1137 frame_unset_flag(focus->frame, FRAME_FLAG_ACTIVE);
1138 if (frame_status(focus->frame) & FRAME_STATUS_REPAINT)
1139 weston_output_schedule_repaint(&focus->base);
1140 }
1141
1142 input->keyboard_focus = NULL;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001143}
1144
Daniel Stone37816df2012-05-16 18:45:18 +01001145static void
1146input_handle_key(void *data, struct wl_keyboard *keyboard,
1147 uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
1148{
1149 struct wayland_input *input = data;
Daniel Stone37816df2012-05-16 18:45:18 +01001150
Daniel Stone50692802012-06-22 13:21:41 +01001151 input->key_serial = serial;
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001152 notify_key(&input->base, time, key,
Daniel Stonec9785ea2012-05-30 16:31:52 +01001153 state ? WL_KEYBOARD_KEY_STATE_PRESSED :
Daniel Stone1b4e11f2012-06-22 13:21:37 +01001154 WL_KEYBOARD_KEY_STATE_RELEASED,
Daniel Stone50692802012-06-22 13:21:41 +01001155 STATE_UPDATE_NONE);
Daniel Stone37816df2012-05-16 18:45:18 +01001156}
1157
Daniel Stone351eb612012-05-31 15:27:47 -04001158static void
1159input_handle_modifiers(void *data, struct wl_keyboard *keyboard,
Daniel Stone50692802012-06-22 13:21:41 +01001160 uint32_t serial_in, uint32_t mods_depressed,
Daniel Stone351eb612012-05-31 15:27:47 -04001161 uint32_t mods_latched, uint32_t mods_locked,
1162 uint32_t group)
1163{
Daniel Stone50692802012-06-22 13:21:41 +01001164 struct wayland_input *input = data;
1165 struct wayland_compositor *c = input->compositor;
1166 uint32_t serial_out;
1167
1168 /* If we get a key event followed by a modifier event with the
1169 * same serial number, then we try to preserve those semantics by
1170 * reusing the same serial number on the way out too. */
1171 if (serial_in == input->key_serial)
1172 serial_out = wl_display_get_serial(c->base.wl_display);
1173 else
1174 serial_out = wl_display_next_serial(c->base.wl_display);
1175
Kristian Høgsberg7af7ced2012-08-10 10:01:33 -04001176 xkb_state_update_mask(input->base.xkb_state.state,
Daniel Stone50692802012-06-22 13:21:41 +01001177 mods_depressed, mods_latched,
1178 mods_locked, 0, 0, group);
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -04001179 notify_modifiers(&input->base, serial_out);
Daniel Stone351eb612012-05-31 15:27:47 -04001180}
1181
Daniel Stone37816df2012-05-16 18:45:18 +01001182static const struct wl_keyboard_listener keyboard_listener = {
Daniel Stoneb7452fe2012-06-01 12:14:06 +01001183 input_handle_keymap,
Kristian Høgsberg06d58b72012-02-23 09:59:05 -05001184 input_handle_keyboard_enter,
1185 input_handle_keyboard_leave,
Daniel Stone37816df2012-05-16 18:45:18 +01001186 input_handle_key,
Daniel Stone351eb612012-05-31 15:27:47 -04001187 input_handle_modifiers,
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001188};
1189
1190static void
Daniel Stone37816df2012-05-16 18:45:18 +01001191input_handle_capabilities(void *data, struct wl_seat *seat,
1192 enum wl_seat_capability caps)
1193{
1194 struct wayland_input *input = data;
1195
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001196 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->parent.pointer) {
1197 input->parent.pointer = wl_seat_get_pointer(seat);
1198 wl_pointer_set_user_data(input->parent.pointer, input);
1199 wl_pointer_add_listener(input->parent.pointer,
1200 &pointer_listener, input);
Kristian Høgsberg7af7ced2012-08-10 10:01:33 -04001201 weston_seat_init_pointer(&input->base);
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001202 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->parent.pointer) {
1203 wl_pointer_destroy(input->parent.pointer);
1204 input->parent.pointer = NULL;
Daniel Stone37816df2012-05-16 18:45:18 +01001205 }
1206
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001207 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->parent.keyboard) {
1208 input->parent.keyboard = wl_seat_get_keyboard(seat);
1209 wl_keyboard_set_user_data(input->parent.keyboard, input);
1210 wl_keyboard_add_listener(input->parent.keyboard,
1211 &keyboard_listener, input);
1212 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->parent.keyboard) {
1213 wl_keyboard_destroy(input->parent.keyboard);
1214 input->parent.keyboard = NULL;
Daniel Stone37816df2012-05-16 18:45:18 +01001215 }
1216}
1217
1218static const struct wl_seat_listener seat_listener = {
1219 input_handle_capabilities,
1220};
1221
1222static void
1223display_add_seat(struct wayland_compositor *c, uint32_t id)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001224{
1225 struct wayland_input *input;
1226
Peter Huttererf3d62272013-08-08 11:57:05 +10001227 input = zalloc(sizeof *input);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001228 if (input == NULL)
1229 return;
1230
Rob Bradford9af5f9e2013-05-31 18:09:50 +01001231 weston_seat_init(&input->base, &c->base, "default");
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001232 input->compositor = c;
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001233 input->parent.seat = wl_registry_bind(c->parent.registry, id,
1234 &wl_seat_interface, 1);
1235 wl_list_insert(c->inputs.prev, &input->link);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001236
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001237 wl_seat_add_listener(input->parent.seat, &seat_listener, input);
1238 wl_seat_set_user_data(input->parent.seat, input);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001239
1240 input->parent.cursor.surface =
1241 wl_compositor_create_surface(c->parent.compositor);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001242}
1243
1244static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001245registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
1246 const char *interface, uint32_t version)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001247{
1248 struct wayland_compositor *c = data;
1249
Benjamin Franzke080ab6c2011-04-30 10:41:27 +02001250 if (strcmp(interface, "wl_compositor") == 0) {
Kristian Høgsbergf790c792011-08-19 14:41:57 -04001251 c->parent.compositor =
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001252 wl_registry_bind(registry, name,
1253 &wl_compositor_interface, 1);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +02001254 } else if (strcmp(interface, "wl_output") == 0) {
Kristian Høgsbergf790c792011-08-19 14:41:57 -04001255 c->parent.output =
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001256 wl_registry_bind(registry, name,
1257 &wl_output_interface, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001258 wl_output_add_listener(c->parent.output, &output_listener, c);
Benjamin Franzke080ab6c2011-04-30 10:41:27 +02001259 } else if (strcmp(interface, "wl_shell") == 0) {
Kristian Høgsbergf790c792011-08-19 14:41:57 -04001260 c->parent.shell =
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001261 wl_registry_bind(registry, name,
1262 &wl_shell_interface, 1);
Daniel Stone725c2c32012-06-22 14:04:36 +01001263 } else if (strcmp(interface, "wl_seat") == 0) {
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001264 display_add_seat(c, name);
Jonas Ådahle5a12252013-04-05 23:07:11 +02001265 } else if (strcmp(interface, "wl_shm") == 0) {
1266 c->parent.shm =
1267 wl_registry_bind(registry, name, &wl_shm_interface, 1);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001268 }
1269}
1270
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001271static const struct wl_registry_listener registry_listener = {
1272 registry_handle_global
1273};
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001274
Kristian Høgsberg95d843d2011-04-22 13:01:26 -04001275static int
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001276wayland_compositor_handle_event(int fd, uint32_t mask, void *data)
1277{
1278 struct wayland_compositor *c = data;
Kristian Høgsbergfeb3c1d2012-10-15 12:56:11 -04001279 int count = 0;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001280
Kristian Høgsberg453de7a2013-10-30 23:15:44 -07001281 if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
1282 wl_display_terminate(c->base.wl_display);
1283 return 0;
1284 }
1285
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001286 if (mask & WL_EVENT_READABLE)
Kristian Høgsbergfeb3c1d2012-10-15 12:56:11 -04001287 count = wl_display_dispatch(c->parent.wl_display);
Kristian Høgsbergf258a312011-12-28 22:51:20 -05001288 if (mask & WL_EVENT_WRITABLE)
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001289 wl_display_flush(c->parent.wl_display);
Kristian Høgsberg95d843d2011-04-22 13:01:26 -04001290
Kristian Høgsbergfeb3c1d2012-10-15 12:56:11 -04001291 if (mask == 0) {
1292 count = wl_display_dispatch_pending(c->parent.wl_display);
1293 wl_display_flush(c->parent.wl_display);
1294 }
1295
1296 return count;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001297}
1298
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05001299static void
Kristian Høgsberg7b884bc2012-07-31 14:32:01 -04001300wayland_restore(struct weston_compositor *ec)
1301{
1302}
1303
1304static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001305wayland_destroy(struct weston_compositor *ec)
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05001306{
Jonas Ådahle5a12252013-04-05 23:07:11 +02001307 struct wayland_compositor *c = (struct wayland_compositor *) ec;
1308
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001309 ec->renderer->destroy(ec);
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001310
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001311 weston_compositor_shutdown(ec);
Matt Roper361d2ad2011-08-29 13:52:23 -07001312
Jonas Ådahle5a12252013-04-05 23:07:11 +02001313 if (c->parent.shm)
1314 wl_shm_destroy(c->parent.shm);
1315
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05001316 free(ec);
1317}
1318
Jason Ekstrand7744f712013-10-27 22:24:55 -05001319static const char *left_ptrs[] = {
1320 "left_ptr",
1321 "default",
1322 "top_left_arrow",
1323 "left-arrow"
1324};
1325
1326static void
1327create_cursor(struct wayland_compositor *c, struct weston_config *config)
1328{
1329 struct weston_config_section *s;
1330 int size;
1331 char *theme = NULL;
1332 unsigned int i;
1333
1334 s = weston_config_get_section(config, "shell", NULL, NULL);
1335 weston_config_section_get_string(s, "cursor-theme", &theme, NULL);
1336 weston_config_section_get_int(s, "cursor-size", &size, 32);
1337
1338 c->cursor_theme = wl_cursor_theme_load(theme, size, c->parent.shm);
1339
1340 c->cursor = NULL;
1341 for (i = 0; !c->cursor && i < ARRAY_LENGTH(left_ptrs); ++i)
1342 c->cursor = wl_cursor_theme_get_cursor(c->cursor_theme,
1343 left_ptrs[i]);
1344 if (!c->cursor) {
1345 fprintf(stderr, "could not load left cursor\n");
1346 return;
1347 }
1348}
1349
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001350static struct weston_compositor *
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001351wayland_compositor_create(struct wl_display *display,
1352 struct wayland_backend_options *options,
Kristian Høgsberg14e438c2013-05-26 21:48:14 -04001353 int *argc, char *argv[],
1354 struct weston_config *config)
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001355{
1356 struct wayland_compositor *c;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001357 struct wayland_output *wo;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001358 struct wl_event_loop *loop;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001359 struct weston_config_section *section;
1360 struct weston_output *output;
1361 char *name;
1362 const char *section_name;
1363 int fd, x, count, width, height;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001364
Peter Huttererf3d62272013-08-08 11:57:05 +10001365 c = zalloc(sizeof *c);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001366 if (c == NULL)
1367 return NULL;
1368
Daniel Stone725c2c32012-06-22 14:04:36 +01001369 if (weston_compositor_init(&c->base, display, argc, argv,
Kristian Høgsberg14e438c2013-05-26 21:48:14 -04001370 config) < 0)
Martin Olssonc5db50f2012-07-08 03:03:43 +02001371 goto err_free;
Daniel Stone725c2c32012-06-22 14:04:36 +01001372
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001373 c->parent.wl_display = wl_display_connect(options->display_name);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001374
Kristian Høgsberg362b6722012-06-18 15:13:51 -04001375 if (c->parent.wl_display == NULL) {
Martin Minarik6d118362012-06-07 18:01:59 +02001376 weston_log("failed to create display: %m\n");
Martin Olssonc5db50f2012-07-08 03:03:43 +02001377 goto err_compositor;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001378 }
1379
Jason Ekstrand8f89fcb2013-10-27 22:24:53 -05001380 wl_list_init(&c->inputs);
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001381 c->parent.registry = wl_display_get_registry(c->parent.wl_display);
1382 wl_registry_add_listener(c->parent.registry, &registry_listener, c);
Jason Ekstrand7744f712013-10-27 22:24:55 -05001383 wl_display_roundtrip(c->parent.wl_display);
1384
1385 create_cursor(c, config);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001386
1387 c->base.wl_display = display;
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001388
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001389 c->use_pixman = options->use_pixman;
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001390
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001391 if (!c->use_pixman) {
1392 gl_renderer = weston_load_module("gl-renderer.so",
1393 "gl_renderer_interface");
1394 if (!gl_renderer)
1395 c->use_pixman = 1;
1396 }
1397
1398 if (!c->use_pixman) {
Jason Ekstrandff2fd462013-10-27 22:24:58 -05001399 if (gl_renderer->create(&c->base, c->parent.wl_display,
1400 gl_renderer->alpha_attribs,
1401 NULL) < 0) {
1402 weston_log("Failed to initialize the GL renderer; "
1403 "falling back to pixman.\n");
1404 c->use_pixman = 1;
1405 }
1406 }
1407
1408 if (c->use_pixman) {
1409 if (pixman_renderer_init(&c->base) < 0) {
1410 weston_log("Failed to initialize pixman renderer\n");
1411 goto err_display;
1412 }
1413 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001414
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +01001415 c->base.destroy = wayland_destroy;
Kristian Høgsberg7b884bc2012-07-31 14:32:01 -04001416 c->base.restore = wayland_restore;
Benjamin Franzkeecfb2b92011-01-15 12:34:48 +01001417
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001418 section = NULL;
1419 x = 0;
1420 count = 0;
1421 while (weston_config_next_section(config, &section, &section_name)) {
1422 if (!section_name || strcmp(section_name, "output") != 0)
1423 continue;
1424 weston_config_section_get_string(section, "name", &name, NULL);
1425 if (name == NULL)
1426 continue;
1427
1428 if (name[0] != 'W' || name[1] != 'L') {
1429 free(name);
1430 continue;
1431 }
1432 free(name);
1433
1434 wo = wayland_output_create_for_config(c, options, section, x, 0);
1435 if (!wo)
1436 goto err_outputs;
1437 x += wo->base.width;
1438 ++count;
1439 }
1440
1441
1442 width = options->width > 0 ? options->width : 1024;
1443 height = options->height > 0 ? options->height : 640;
1444 while (count < options->count) {
1445 if (!wayland_output_create(c, x, 0, width, height,
1446 WINDOW_TITLE, 0, 1))
1447 goto err_outputs;
1448 x += width;
1449 ++count;
1450 }
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001451
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001452 loop = wl_display_get_event_loop(c->base.wl_display);
1453
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001454 fd = wl_display_get_fd(c->parent.wl_display);
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001455 c->parent.wl_source =
Kristian Høgsbergfa80e112012-10-10 21:34:26 -04001456 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001457 wayland_compositor_handle_event, c);
1458 if (c->parent.wl_source == NULL)
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001459 goto err_outputs;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001460
Kristian Høgsbergfeb3c1d2012-10-15 12:56:11 -04001461 wl_event_source_check(c->parent.wl_source);
1462
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001463 return &c->base;
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001464err_outputs:
1465 wl_list_for_each(output, &c->base.output_list, link)
1466 wayland_output_destroy(output);
Martin Olssonc5db50f2012-07-08 03:03:43 +02001467
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001468 c->base.renderer->destroy(&c->base);
Martin Olssonc5db50f2012-07-08 03:03:43 +02001469err_display:
1470 wl_display_disconnect(c->parent.wl_display);
1471err_compositor:
1472 weston_compositor_shutdown(&c->base);
1473err_free:
1474 free(c);
1475 return NULL;
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001476}
Kristian Høgsberg1c562182011-05-02 22:09:20 -04001477
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001478WL_EXPORT struct weston_compositor *
Kristian Høgsberg4172f662013-02-20 15:27:49 -05001479backend_init(struct wl_display *display, int *argc, char *argv[],
Kristian Høgsberg14e438c2013-05-26 21:48:14 -04001480 struct weston_config *config)
Kristian Høgsberg1c562182011-05-02 22:09:20 -04001481{
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001482 struct wayland_backend_options options;
1483 memset(&options, 0, sizeof options);
Kristian Høgsberg1c562182011-05-02 22:09:20 -04001484
Kristian Høgsbergbcacef12012-03-11 21:05:57 -04001485 const struct weston_option wayland_options[] = {
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001486 { WESTON_OPTION_INTEGER, "width", 0, &options.width },
1487 { WESTON_OPTION_INTEGER, "height", 0, &options.height },
1488 { WESTON_OPTION_STRING, "display", 0, &options.display_name },
1489 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &options.use_pixman },
1490 { WESTON_OPTION_INTEGER, "output-count", 0, &options.count },
Kristian Høgsbergbcacef12012-03-11 21:05:57 -04001491 };
1492
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001493 options.count = 1;
1494
Kristian Høgsbergbcacef12012-03-11 21:05:57 -04001495 parse_options(wayland_options,
1496 ARRAY_LENGTH(wayland_options), argc, argv);
Kristian Høgsberg1c562182011-05-02 22:09:20 -04001497
Jason Ekstrand48ce4212013-10-27 22:25:02 -05001498 return wayland_compositor_create(display, &options,
1499 argc, argv, config);
Kristian Høgsberg1c562182011-05-02 22:09:20 -04001500}