blob: 8856b7e10a13a0600ce631bcca87a90aed99a3de [file] [log] [blame]
Kristian Høgsbergffd710e2008-12-02 15:15:01 -05001/*
2 * Copyright © 2008 Kristian Høgsberg
3 *
Kristian Høgsberg82f6e8a2008-12-19 13:47:53 -05004 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
Kristian Høgsbergffd710e2008-12-02 15:15:01 -05008 *
Kristian Høgsberg82f6e8a2008-12-19 13:47:53 -05009 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Kristian Høgsbergffd710e2008-12-02 15:15:01 -050017 */
18
Kristian Høgsberg06bc2642010-12-01 09:50:16 -050019#define _GNU_SOURCE
20
Kristian Høgsberga9410222011-01-14 17:22:35 -050021#include "config.h"
22
Kristian Høgsberg16eb6752008-10-08 22:51:32 -040023#include <stdio.h>
24#include <string.h>
25#include <stdlib.h>
26#include <stdint.h>
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +010027#include <limits.h>
Kristian Høgsberg8d7ca6b2008-11-09 00:22:51 -050028#include <stdarg.h>
Kristian Høgsberg16eb6752008-10-08 22:51:32 -040029#include <sys/ioctl.h>
Kristian Høgsberg16eb6752008-10-08 22:51:32 -040030#include <fcntl.h>
31#include <unistd.h>
Kristian Høgsbergaa5b5be2008-11-21 21:31:54 -050032#include <gdk-pixbuf/gdk-pixbuf.h>
Kristian Høgsberg54879822008-11-23 17:07:32 -050033#include <math.h>
Kristian Høgsbergfc783d42010-06-11 12:56:24 -040034#include <linux/input.h>
Kristian Høgsberg890bc052008-12-30 14:31:33 -050035
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050036#include "wayland-server.h"
Kristian Høgsberg82863022010-06-04 21:52:02 -040037#include "compositor.h"
Kristian Høgsberg5ee1a602008-12-11 23:18:45 -050038
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010039/* The plan here is to generate a random anonymous socket name and
40 * advertise that through a service on the session dbus.
41 */
Kristian Høgsberg2bb3ebe2010-12-01 15:36:20 -050042static const char *option_socket_name = NULL;
Kristian Høgsberg61a82512010-10-26 11:26:44 -040043static const char *option_background = "background.jpg";
44static const char *option_geometry = "1024x640";
45static int option_connector = 0;
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -050046
47static const GOptionEntry option_entries[] = {
48 { "background", 'b', 0, G_OPTION_ARG_STRING,
49 &option_background, "Background image" },
Kristian Høgsbergf5878fa2009-09-18 17:02:41 -040050 { "connector", 'c', 0, G_OPTION_ARG_INT,
51 &option_connector, "KMS connector" },
Kristian Høgsberg61a82512010-10-26 11:26:44 -040052 { "geometry", 'g', 0, G_OPTION_ARG_STRING,
53 &option_geometry, "Geometry" },
Benjamin Franzkeec2e6422010-11-27 19:04:12 +010054 { "socket", 's', 0, G_OPTION_ARG_STRING,
55 &option_socket_name, "Socket Name" },
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -050056 { NULL }
57};
58
Kristian Høgsberg5c8c3282009-02-09 15:17:46 -050059static void
60wlsc_matrix_init(struct wlsc_matrix *matrix)
61{
62 static const struct wlsc_matrix identity = {
63 { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }
64 };
65
66 memcpy(matrix, &identity, sizeof identity);
67}
68
69static void
70wlsc_matrix_multiply(struct wlsc_matrix *m, const struct wlsc_matrix *n)
71{
72 struct wlsc_matrix tmp;
Kristian Høgsberg27803c62010-06-06 22:23:21 -040073 const GLfloat *row, *column;
Kristian Høgsberg5c8c3282009-02-09 15:17:46 -050074 div_t d;
75 int i, j;
76
77 for (i = 0; i < 16; i++) {
78 tmp.d[i] = 0;
79 d = div(i, 4);
80 row = m->d + d.quot * 4;
81 column = n->d + d.rem;
82 for (j = 0; j < 4; j++)
83 tmp.d[i] += row[j] * column[j * 4];
84 }
85 memcpy(m, &tmp, sizeof tmp);
86}
87
88static void
Kristian Høgsberg27803c62010-06-06 22:23:21 -040089wlsc_matrix_translate(struct wlsc_matrix *matrix, GLfloat x, GLfloat y, GLfloat z)
Kristian Høgsberg5c8c3282009-02-09 15:17:46 -050090{
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -050091 struct wlsc_matrix translate = {
Kristian Høgsberg5c8c3282009-02-09 15:17:46 -050092 { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 }
93 };
94
95 wlsc_matrix_multiply(matrix, &translate);
96}
97
98static void
Kristian Høgsberg27803c62010-06-06 22:23:21 -040099wlsc_matrix_scale(struct wlsc_matrix *matrix, GLfloat x, GLfloat y, GLfloat z)
Kristian Høgsberg5c8c3282009-02-09 15:17:46 -0500100{
101 struct wlsc_matrix scale = {
102 { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 }
103 };
104
105 wlsc_matrix_multiply(matrix, &scale);
106}
107
108static void
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400109wlsc_matrix_transform(struct wlsc_matrix *matrix, struct wlsc_vector *v)
110{
111 int i, j;
Kristian Høgsberg0b8646b2010-06-08 15:29:14 -0400112 struct wlsc_vector t;
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400113
114 for (i = 0; i < 4; i++) {
Kristian Høgsberg0b8646b2010-06-08 15:29:14 -0400115 t.f[i] = 0;
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400116 for (j = 0; j < 4; j++)
Kristian Høgsberg0b8646b2010-06-08 15:29:14 -0400117 t.f[i] += v->f[j] * matrix->d[i + j * 4];
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400118 }
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -0500119
Kristian Høgsberg0b8646b2010-06-08 15:29:14 -0400120 *v = t;
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400121}
122
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200123struct wlsc_surface *
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400124wlsc_surface_create(struct wlsc_compositor *compositor,
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400125 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg1a208d52009-02-10 14:20:26 -0500126{
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400127 struct wlsc_surface *surface;
128
129 surface = malloc(sizeof *surface);
130 if (surface == NULL)
131 return NULL;
132
Kristian Høgsbergc551bd22010-12-06 16:43:16 -0500133 wl_list_init(&surface->surface.destroy_listener_list);
Kristian Høgsbergf6b14712011-01-06 15:32:14 -0500134 wl_list_init(&surface->link);
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500135 surface->map_type = WLSC_SURFACE_MAP_UNMAPPED;
Kristian Høgsbergc551bd22010-12-06 16:43:16 -0500136
Kristian Høgsberg1a208d52009-02-10 14:20:26 -0500137 glGenTextures(1, &surface->texture);
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400138 glBindTexture(GL_TEXTURE_2D, surface->texture);
139 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
140 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
141 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
142 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
143
Kristian Høgsberg1a208d52009-02-10 14:20:26 -0500144 surface->compositor = compositor;
Kristian Høgsbergc5d6be92011-01-14 16:22:37 -0500145 surface->visual = NULL;
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200146 surface->image = EGL_NO_IMAGE_KHR;
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200147 surface->saved_texture = 0;
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400148 surface->x = x;
149 surface->y = y;
150 surface->width = width;
151 surface->height = height;
Kristian Høgsberg8da19ac2009-03-17 16:12:51 -0400152 wlsc_matrix_init(&surface->matrix);
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400153 wlsc_matrix_scale(&surface->matrix, width, height, 1);
154 wlsc_matrix_translate(&surface->matrix, x, y, 0);
155
156 wlsc_matrix_init(&surface->matrix_inv);
157 wlsc_matrix_translate(&surface->matrix_inv, -x, -y, 0);
158 wlsc_matrix_scale(&surface->matrix_inv, 1.0 / width, 1.0 / height, 1);
Kristian Høgsberg1e4b86a2008-11-23 23:41:08 -0500159
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400160 return surface;
Kristian Høgsberg54879822008-11-23 17:07:32 -0500161}
162
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -0500163void
164wlsc_surface_damage_rectangle(struct wlsc_surface *surface,
165 int32_t x, int32_t y,
166 int32_t width, int32_t height)
167{
168 struct wlsc_compositor *compositor = surface->compositor;
169
170 pixman_region32_union_rect(&compositor->damage_region,
171 &compositor->damage_region,
172 surface->x + x, surface->y + y,
173 width, height);
174 wlsc_compositor_schedule_repaint(compositor);
175}
176
177void
178wlsc_surface_damage(struct wlsc_surface *surface)
179{
180 wlsc_surface_damage_rectangle(surface, 0, 0,
181 surface->width, surface->height);
182}
183
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500184uint32_t
Kristian Høgsberg7132a9a2010-12-06 21:41:10 -0500185get_time(void)
186{
187 struct timeval tv;
188
189 gettimeofday(&tv, NULL);
190
191 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
192}
193
Kristian Høgsberg54879822008-11-23 17:07:32 -0500194static void
Kristian Høgsberg5fcd0aa2010-08-09 14:43:33 -0400195destroy_surface(struct wl_resource *resource, struct wl_client *client)
Kristian Høgsberg54879822008-11-23 17:07:32 -0500196{
Kristian Høgsberg5fcd0aa2010-08-09 14:43:33 -0400197 struct wlsc_surface *surface =
Kristian Høgsbergb313b022010-12-01 17:07:41 -0500198 container_of(resource, struct wlsc_surface, surface.resource);
Kristian Høgsbergc551bd22010-12-06 16:43:16 -0500199 struct wl_listener *l, *next;
Kristian Høgsberg4685fa32010-12-06 21:38:50 -0500200 uint32_t time;
Kristian Høgsberg4fa48732009-03-10 23:17:00 -0400201
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -0500202 wlsc_surface_damage(surface);
203
Kristian Høgsberg3f8f39c2009-09-18 17:05:13 -0400204 wl_list_remove(&surface->link);
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200205 if (surface->saved_texture == 0)
206 glDeleteTextures(1, &surface->texture);
207 else
208 glDeleteTextures(1, &surface->saved_texture);
209
Kristian Høgsberg3f8f39c2009-09-18 17:05:13 -0400210
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200211 if (surface->image != EGL_NO_IMAGE_KHR)
212 eglDestroyImageKHR(surface->compositor->display,
213 surface->image);
214
Kristian Høgsberg7132a9a2010-12-06 21:41:10 -0500215 time = get_time();
Kristian Høgsbergc551bd22010-12-06 16:43:16 -0500216 wl_list_for_each_safe(l, next,
217 &surface->surface.destroy_listener_list, link)
Kristian Høgsberg4685fa32010-12-06 21:38:50 -0500218 l->func(l, &surface->surface, time);
Kristian Høgsberg4fa48732009-03-10 23:17:00 -0400219
Kristian Høgsberg4fa48732009-03-10 23:17:00 -0400220 free(surface);
Kristian Høgsberg54879822008-11-23 17:07:32 -0500221}
222
Kristian Høgsbergf58d8ca2011-01-26 14:37:07 -0500223uint32_t *
224wlsc_load_image(const char *filename, int width, int height)
Kristian Høgsberg4c9f2c92008-11-21 19:25:44 -0500225{
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400226 GdkPixbuf *pixbuf;
227 GError *error = NULL;
Kristian Høgsberg8525a502011-01-14 16:20:21 -0500228 int stride, i, n_channels;
229 unsigned char *pixels, *end, *argb_pixels, *s, *d;
Kristian Høgsberg4c9f2c92008-11-21 19:25:44 -0500230
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400231 pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
232 width, height,
233 FALSE, &error);
Kristian Høgsbergf58d8ca2011-01-26 14:37:07 -0500234 if (error != NULL) {
235 fprintf(stderr, "failed to load image: %s\n", error->message);
236 g_error_free(error);
Kristian Høgsberg8525a502011-01-14 16:20:21 -0500237 return NULL;
Kristian Høgsbergf58d8ca2011-01-26 14:37:07 -0500238 }
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400239
Kristian Høgsberg8525a502011-01-14 16:20:21 -0500240 stride = gdk_pixbuf_get_rowstride(pixbuf);
241 pixels = gdk_pixbuf_get_pixels(pixbuf);
242 n_channels = gdk_pixbuf_get_n_channels(pixbuf);
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400243
Kristian Høgsberg8525a502011-01-14 16:20:21 -0500244 argb_pixels = malloc (height * width * 4);
245 if (argb_pixels == NULL) {
Darxus@chaosreigns.comc4df99c2011-01-25 15:00:56 -0500246 g_object_unref(pixbuf);
Kristian Høgsberg8525a502011-01-14 16:20:21 -0500247 return NULL;
248 }
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400249
Kristian Høgsberg8525a502011-01-14 16:20:21 -0500250 if (n_channels == 4) {
251 for (i = 0; i < height; i++) {
252 s = pixels + i * stride;
253 end = s + width * 4;
254 d = argb_pixels + i * width * 4;
255 while (s < end) {
256 unsigned int t;
257
258#define MULT(_d,c,a,t) \
259 do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
260
261 MULT(d[0], s[2], s[3], t);
262 MULT(d[1], s[1], s[3], t);
263 MULT(d[2], s[0], s[3], t);
264 d[3] = s[3];
265 s += 4;
266 d += 4;
267 }
268 }
269 } else if (n_channels == 3) {
270 for (i = 0; i < height; i++) {
271 s = pixels + i * stride;
272 end = s + width * 3;
273 d = argb_pixels + i * width * 4;
274 while (s < end) {
275 d[0] = s[2];
276 d[1] = s[1];
277 d[2] = s[0];
278 d[3] = 0xff;
279 s += 3;
280 d += 4;
281 }
282 }
283 }
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400284
Darxus@chaosreigns.comc4df99c2011-01-25 15:00:56 -0500285 g_object_unref(pixbuf);
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400286
Kristian Høgsbergf58d8ca2011-01-26 14:37:07 -0500287 return (uint32_t *) argb_pixels;
288}
289
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +0100290static void
291wlsc_buffer_attach(struct wl_buffer *buffer, struct wl_surface *surface)
292{
293 struct wlsc_surface *es = (struct wlsc_surface *) surface;
294 struct wlsc_compositor *ec = es->compositor;
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +0100295
296 if (buffer->attach) {
297 buffer->attach(buffer, surface);
298 } else {
Kristian Høgsbergdf2f1972011-04-21 23:48:13 -0400299 es->image = eglCreateImageKHR(ec->display, NULL,
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200300 EGL_WAYLAND_BUFFER_WL,
301 buffer, NULL);
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +0100302
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200303 if (es->saved_texture != 0)
304 es->texture = es->saved_texture;
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +0100305 glBindTexture(GL_TEXTURE_2D, es->texture);
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200306 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, es->image);
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +0100307 es->visual = buffer->visual;
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +0100308 }
309}
310
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200311static void
312wlsc_sprite_attach(struct wlsc_sprite *sprite, struct wl_surface *surface)
313{
314 struct wlsc_surface *es = (struct wlsc_surface *) surface;
315
316 es->image = sprite->image;
317 if (sprite->image != EGL_NO_IMAGE_KHR) {
318 glBindTexture(GL_TEXTURE_2D, es->texture);
319 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, es->image);
320 } else {
321 if (es->saved_texture == 0)
322 es->saved_texture = es->texture;
323 es->texture = sprite->texture;
324 }
325
326 es->visual = sprite->visual;
327}
328
329enum sprite_usage {
330 SPRITE_USE_CURSOR = (1 << 0),
331};
332
333static struct wlsc_sprite *
334create_sprite_from_png(struct wlsc_compositor *ec,
335 const char *filename, int width, int height,
336 uint32_t usage)
Kristian Høgsbergf58d8ca2011-01-26 14:37:07 -0500337{
338 uint32_t *pixels;
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200339 struct wlsc_sprite *sprite;
Kristian Høgsbergf58d8ca2011-01-26 14:37:07 -0500340
341 pixels = wlsc_load_image(filename, width, height);
Tim Wiederhakeac5c5e72011-01-27 01:32:36 +0100342 if(pixels == NULL)
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200343 return NULL;
Kristian Høgsbergf58d8ca2011-01-26 14:37:07 -0500344
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200345 sprite = malloc(sizeof *sprite);
346 if (sprite == NULL) {
347 free(pixels);
348 return NULL;
349 }
350
351 sprite->visual = &ec->compositor.premultiplied_argb_visual;
352 sprite->width = width;
353 sprite->height = height;
354 sprite->image = EGL_NO_IMAGE_KHR;
355
356 if (usage & SPRITE_USE_CURSOR && ec->create_cursor_image != NULL)
357 sprite->image = ec->create_cursor_image(ec, width, height);
358
359 glGenTextures(1, &sprite->texture);
360 glBindTexture(GL_TEXTURE_2D, sprite->texture);
361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
362 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
364 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
365
366 if (sprite->image != EGL_NO_IMAGE_KHR) {
367 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, sprite->image);
368 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
369 GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
370 } else {
371 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
372 GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
373 }
Kristian Høgsberg8525a502011-01-14 16:20:21 -0500374
Kristian Høgsbergf58d8ca2011-01-26 14:37:07 -0500375 free(pixels);
Kristian Høgsberg8525a502011-01-14 16:20:21 -0500376
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200377 return sprite;
Kristian Høgsberg4c9f2c92008-11-21 19:25:44 -0500378}
379
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400380static const struct {
381 const char *filename;
382 int hotspot_x, hotspot_y;
383} pointer_images[] = {
Kristian Høgsberg4219a402010-08-16 16:43:03 -0400384 { DATADIR "/wayland/bottom_left_corner.png", 6, 30 },
385 { DATADIR "/wayland/bottom_right_corner.png", 28, 28 },
386 { DATADIR "/wayland/bottom_side.png", 16, 20 },
387 { DATADIR "/wayland/grabbing.png", 20, 17 },
388 { DATADIR "/wayland/left_ptr.png", 10, 5 },
389 { DATADIR "/wayland/left_side.png", 10, 20 },
390 { DATADIR "/wayland/right_side.png", 30, 19 },
391 { DATADIR "/wayland/top_left_corner.png", 8, 8 },
392 { DATADIR "/wayland/top_right_corner.png", 26, 8 },
393 { DATADIR "/wayland/top_side.png", 18, 8 },
394 { DATADIR "/wayland/xterm.png", 15, 15 }
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400395};
396
397static void
398create_pointer_images(struct wlsc_compositor *ec)
Kristian Høgsberg4c9f2c92008-11-21 19:25:44 -0500399{
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400400 int i, count;
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400401 const int width = 32, height = 32;
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400402
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400403 count = ARRAY_LENGTH(pointer_images);
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200404 ec->pointer_sprites = malloc(count * sizeof *ec->pointer_sprites);
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400405 for (i = 0; i < count; i++) {
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200406 ec->pointer_sprites[i] =
407 create_sprite_from_png(ec,
Kristian Høgsberg8525a502011-01-14 16:20:21 -0500408 pointer_images[i].filename,
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200409 width, height,
410 SPRITE_USE_CURSOR);
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400411 }
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400412}
413
Kristian Høgsberg8e438622009-01-26 23:07:00 -0500414static struct wlsc_surface *
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -0500415background_create(struct wlsc_output *output, const char *filename)
Kristian Høgsbergaa5b5be2008-11-21 21:31:54 -0500416{
Kristian Høgsberg8e438622009-01-26 23:07:00 -0500417 struct wlsc_surface *background;
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200418 struct wlsc_sprite *sprite;
Kristian Høgsbergaa5b5be2008-11-21 21:31:54 -0500419
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400420 background = wlsc_surface_create(output->compositor,
Kristian Høgsberg77fb1672010-08-16 10:38:29 -0400421 output->x, output->y,
422 output->width, output->height);
Kristian Høgsbergaa5b5be2008-11-21 21:31:54 -0500423 if (background == NULL)
424 return NULL;
Kristian Høgsbergaa5b5be2008-11-21 21:31:54 -0500425
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200426 sprite = create_sprite_from_png(output->compositor, filename,
427 output->width, output->height, 0);
428 if (sprite == NULL) {
Benjamin Franzked3b023e2011-01-15 12:34:49 +0100429 free(background);
430 return NULL;
431 }
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +0100432
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200433 wlsc_sprite_attach(sprite, &background->surface);
Kristian Høgsbergaa5b5be2008-11-21 21:31:54 -0500434
Kristian Høgsbergaa5b5be2008-11-21 21:31:54 -0500435 return background;
Kristian Høgsberg4c9f2c92008-11-21 19:25:44 -0500436}
437
438static void
Kristian Høgsberg525e4c02011-02-14 10:39:54 -0500439wlsc_surface_draw(struct wlsc_surface *es,
440 struct wlsc_output *output, pixman_region32_t *clip)
Kristian Høgsberg4c9f2c92008-11-21 19:25:44 -0500441{
Kristian Høgsberg8e438622009-01-26 23:07:00 -0500442 struct wlsc_compositor *ec = es->compositor;
Kristian Høgsberg525e4c02011-02-14 10:39:54 -0500443 GLfloat *v, inv_width, inv_height;
444 unsigned int *p;
445 pixman_region32_t repaint;
446 pixman_box32_t *rectangles;
447 int i, n;
448
449 pixman_region32_init_rect(&repaint,
450 es->x, es->y, es->width, es->height);
451 pixman_region32_intersect(&repaint, &repaint, clip);
452 if (!pixman_region32_not_empty(&repaint))
453 return;
Kristian Høgsberg4c9f2c92008-11-21 19:25:44 -0500454
Kristian Høgsbergc5c510e2010-12-08 15:12:58 -0500455 if (es->visual == &ec->compositor.argb_visual) {
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500456 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
457 glEnable(GL_BLEND);
Kristian Høgsbergc5c510e2010-12-08 15:12:58 -0500458 } else if (es->visual == &ec->compositor.premultiplied_argb_visual) {
Kristian Høgsbergde31d5c2008-12-18 17:55:33 -0500459 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
460 glEnable(GL_BLEND);
461 } else {
462 glDisable(GL_BLEND);
463 }
464
Kristian Høgsberg525e4c02011-02-14 10:39:54 -0500465 rectangles = pixman_region32_rectangles(&repaint, &n);
466 v = wl_array_add(&ec->vertices, n * 16 * sizeof *v);
467 p = wl_array_add(&ec->indices, n * 6 * sizeof *p);
468 inv_width = 1.0 / es->width;
469 inv_height = 1.0 / es->height;
470 for (i = 0; i < n; i++, v += 16, p += 6) {
471 v[ 0] = rectangles[i].x1;
472 v[ 1] = rectangles[i].y1;
473 v[ 2] = (GLfloat) (rectangles[i].x1 - es->x) * inv_width;
474 v[ 3] = (GLfloat) (rectangles[i].y1 - es->y) * inv_height;
Kristian Høgsbergfa4e2a72011-02-13 13:44:55 -0500475
Kristian Høgsberg525e4c02011-02-14 10:39:54 -0500476 v[ 4] = rectangles[i].x1;
477 v[ 5] = rectangles[i].y2;
478 v[ 6] = v[ 2];
479 v[ 7] = (GLfloat) (rectangles[i].y2 - es->y) * inv_height;
Kristian Høgsbergfa4e2a72011-02-13 13:44:55 -0500480
Kristian Høgsberg525e4c02011-02-14 10:39:54 -0500481 v[ 8] = rectangles[i].x2;
482 v[ 9] = rectangles[i].y1;
483 v[10] = (GLfloat) (rectangles[i].x2 - es->x) * inv_width;
484 v[11] = v[ 3];
Kristian Høgsbergfa4e2a72011-02-13 13:44:55 -0500485
Kristian Høgsberg525e4c02011-02-14 10:39:54 -0500486 v[12] = rectangles[i].x2;
487 v[13] = rectangles[i].y2;
488 v[14] = v[10];
489 v[15] = v[ 7];
490
491 p[0] = i * 4 + 0;
492 p[1] = i * 4 + 1;
493 p[2] = i * 4 + 2;
494 p[3] = i * 4 + 2;
495 p[4] = i * 4 + 1;
496 p[5] = i * 4 + 3;
497 }
Kristian Høgsbergfa4e2a72011-02-13 13:44:55 -0500498
Kristian Høgsbergaa5b5be2008-11-21 21:31:54 -0500499 glBindTexture(GL_TEXTURE_2D, es->texture);
Kristian Høgsberg525e4c02011-02-14 10:39:54 -0500500 v = ec->vertices.data;
501 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
502 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400503 glEnableVertexAttribArray(0);
504 glEnableVertexAttribArray(1);
Kristian Høgsberg525e4c02011-02-14 10:39:54 -0500505 glDrawElements(GL_TRIANGLES, n * 6, GL_UNSIGNED_INT, ec->indices.data);
506
507 ec->vertices.size = 0;
508 ec->indices.size = 0;
509 pixman_region32_fini(&repaint);
Kristian Høgsberg4c9f2c92008-11-21 19:25:44 -0500510}
511
512static void
Kristian Høgsberg8da19ac2009-03-17 16:12:51 -0400513wlsc_surface_raise(struct wlsc_surface *surface)
514{
515 struct wlsc_compositor *compositor = surface->compositor;
516
517 wl_list_remove(&surface->link);
Kristian Høgsberg747638b2010-07-12 17:06:06 -0400518 wl_list_insert(&compositor->surface_list, &surface->link);
Kristian Høgsberg8da19ac2009-03-17 16:12:51 -0400519}
520
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500521void
Kristian Høgsberg83fc0612010-08-04 22:44:55 -0400522wlsc_surface_update_matrix(struct wlsc_surface *es)
523{
524 wlsc_matrix_init(&es->matrix);
525 wlsc_matrix_scale(&es->matrix, es->width, es->height, 1);
526 wlsc_matrix_translate(&es->matrix, es->x, es->y, 0);
527
528 wlsc_matrix_init(&es->matrix_inv);
529 wlsc_matrix_translate(&es->matrix_inv, -es->x, -es->y, 0);
530 wlsc_matrix_scale(&es->matrix_inv,
531 1.0 / es->width, 1.0 / es->height, 1);
532}
533
Kristian Høgsbergfc783d42010-06-11 12:56:24 -0400534void
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100535wlsc_output_finish_frame(struct wlsc_output *output, int msecs)
Kristian Høgsberg01f941b2009-05-27 17:47:15 -0400536{
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100537 struct wlsc_compositor *compositor = output->compositor;
538 struct wlsc_surface *es;
539
540 wl_list_for_each(es, &compositor->surface_list, link) {
541 if (es->output == output) {
542 wl_display_post_frame(compositor->wl_display,
543 &es->surface, msecs);
544 }
545 }
546
547 output->finished = 1;
548
Kristian Høgsberg5d312db2009-09-12 16:57:02 -0400549 wl_event_source_timer_update(compositor->timer_source, 5);
Kristian Høgsbergf30c67e2011-02-06 12:58:44 -0500550 compositor->repaint_on_timeout = 1;
Kristian Høgsberg01f941b2009-05-27 17:47:15 -0400551}
552
553static void
Kristian Høgsbergfc783d42010-06-11 12:56:24 -0400554wlsc_output_repaint(struct wlsc_output *output)
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -0400555{
Kristian Høgsberg1a208d52009-02-10 14:20:26 -0500556 struct wlsc_compositor *ec = output->compositor;
Kristian Høgsberg8e438622009-01-26 23:07:00 -0500557 struct wlsc_surface *es;
Kristian Høgsberg82f6e8a2008-12-19 13:47:53 -0500558 struct wlsc_input_device *eid;
Kristian Høgsbergcfc6d272011-04-11 13:34:24 -0400559 pixman_region32_t new_damage, total_damage, repaint;
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200560 int using_hardware_cursor = 1;
Kristian Høgsbergfbdbbdc2008-11-28 17:06:06 -0500561
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100562 output->prepare_render(output);
563
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -0500564 glViewport(0, 0, output->width, output->height);
Kristian Høgsbergfdec2362001-01-01 22:23:51 -0500565
Kristian Høgsbergfa4e2a72011-02-13 13:44:55 -0500566 glUniformMatrix4fv(ec->proj_uniform, 1, GL_FALSE, output->matrix.d);
567 glUniform1i(ec->tex_uniform, 0);
568
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -0500569 pixman_region32_init(&new_damage);
570 pixman_region32_init(&total_damage);
571 pixman_region32_intersect_rect(&new_damage,
572 &ec->damage_region,
573 output->x, output->y,
574 output->width, output->height);
575 pixman_region32_subtract(&ec->damage_region,
576 &ec->damage_region, &new_damage);
577 pixman_region32_union(&total_damage, &new_damage,
578 &output->previous_damage_region);
579 pixman_region32_copy(&output->previous_damage_region, &new_damage);
580
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200581 if (ec->focus)
582 if (output->set_hardware_cursor(output, ec->input_device) < 0)
583 using_hardware_cursor = 0;
584
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500585 es = container_of(ec->surface_list.next, struct wlsc_surface, link);
586 if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN &&
587 es->fullscreen_output == output) {
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200588 if (es->visual == &ec->compositor.rgb_visual &&
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200589 using_hardware_cursor) {
590 if (output->prepare_scanout_surface(output, es) == 0) {
591 /* We're drawing nothing now,
592 * draw the damaged regions later. */
593 pixman_region32_union(&ec->damage_region,
594 &ec->damage_region,
595 &total_damage);
596 return;
597 }
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200598 }
Benjamin Franzke66aa2352011-04-20 17:06:13 +0200599
600 if (es->width < output->width ||
601 es->height < output->height)
602 glClear(GL_COLOR_BUFFER_BIT);
603 wlsc_surface_draw(es, output, &total_damage);
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500604 } else {
Kristian Høgsbergcfc6d272011-04-11 13:34:24 -0400605 wl_list_for_each(es, &ec->surface_list, link) {
606 if (es->visual != &ec->compositor.rgb_visual)
607 continue;
608
609 pixman_region32_init_rect(&repaint,
610 es->x, es->y,
611 es->width, es->height);
612 wlsc_surface_draw(es, output, &total_damage);
613 pixman_region32_subtract(&total_damage,
614 &total_damage, &repaint);
615 }
616
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500617 if (output->background)
Kristian Høgsberg525e4c02011-02-14 10:39:54 -0500618 wlsc_surface_draw(output->background,
619 output, &total_damage);
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500620 else
621 glClear(GL_COLOR_BUFFER_BIT);
622
Kristian Høgsbergc9824dd2011-02-06 16:54:59 -0500623 wl_list_for_each_reverse(es, &ec->surface_list, link) {
Kristian Høgsberg547cadf2011-04-12 22:23:30 -0400624 if (ec->overlay == es)
Kristian Høgsbergc9824dd2011-02-06 16:54:59 -0500625 continue;
626
Kristian Høgsbergcfc6d272011-04-11 13:34:24 -0400627 if (es->visual == &ec->compositor.rgb_visual) {
628 pixman_region32_union_rect(&total_damage,
629 &total_damage,
630 es->x, es->y,
631 es->width, es->height);
632 continue;
633 }
634
Kristian Høgsberg525e4c02011-02-14 10:39:54 -0500635 wlsc_surface_draw(es, output, &total_damage);
Kristian Høgsbergc9824dd2011-02-06 16:54:59 -0500636 }
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500637 }
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -0400638
Kristian Høgsberg547cadf2011-04-12 22:23:30 -0400639 if (ec->overlay)
640 wlsc_surface_draw(ec->overlay, output, &total_damage);
Kristian Høgsbergc9824dd2011-02-06 16:54:59 -0500641
Kristian Høgsberg86e09892010-07-07 09:51:11 -0400642 if (ec->focus)
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200643 wl_list_for_each(eid, &ec->input_device_list, link) {
644 if (&eid->input_device != ec->input_device ||
645 !using_hardware_cursor)
646 wlsc_surface_draw(eid->sprite, output,
647 &total_damage);
648 }
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -0500649}
650
651static void
652repaint(void *data)
653{
Kristian Høgsberg8e438622009-01-26 23:07:00 -0500654 struct wlsc_compositor *ec = data;
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -0500655 struct wlsc_output *output;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100656 int repainted_all_outputs = 1;
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -0500657
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100658 wl_list_for_each(output, &ec->output_list, link) {
659 if (!output->repaint_needed)
660 continue;
661
662 if (!output->finished) {
663 repainted_all_outputs = 0;
664 continue;
665 }
666
667 wlsc_output_repaint(output);
668 output->finished = 0;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100669 output->repaint_needed = 0;
Kristian Høgsberg11e28282011-04-11 16:47:50 -0400670 output->present(output);
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -0500671 }
672
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100673 if (repainted_all_outputs)
674 ec->repaint_on_timeout = 0;
675 else
676 wl_event_source_timer_update(ec->timer_source, 1);
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -0400677}
678
Kristian Høgsberg86e09892010-07-07 09:51:11 -0400679void
Kristian Høgsberg8da19ac2009-03-17 16:12:51 -0400680wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor)
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -0400681{
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100682 struct wlsc_output *output;
683
684 wl_list_for_each(output, &compositor->output_list, link)
685 output->repaint_needed = 1;
686
Kristian Høgsbergb0a167c2009-08-14 11:15:18 -0400687 if (compositor->repaint_on_timeout)
688 return;
689
Kristian Høgsbergfc783d42010-06-11 12:56:24 -0400690 wl_event_source_timer_update(compositor->timer_source, 1);
691 compositor->repaint_on_timeout = 1;
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -0400692}
Kristian Høgsberg5c8c3282009-02-09 15:17:46 -0500693
Kristian Høgsberg5503bf82008-11-06 10:38:17 -0500694static void
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500695surface_destroy(struct wl_client *client,
696 struct wl_surface *surface)
Kristian Høgsberg16eb6752008-10-08 22:51:32 -0400697{
Kristian Høgsbergb313b022010-12-01 17:07:41 -0500698 wl_resource_destroy(&surface->resource, client);
Kristian Høgsberg16eb6752008-10-08 22:51:32 -0400699}
700
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100701void
702wlsc_surface_assign_output(struct wlsc_surface *es)
703{
704 struct wlsc_compositor *ec = es->compositor;
705 struct wlsc_output *output;
706
707 struct wlsc_output *tmp = es->output;
708 es->output = NULL;
709
710 wl_list_for_each(output, &ec->output_list, link) {
711 if (output->x < es->x && es->x < output->x + output->width &&
712 output->y < es->y && es->y < output->y + output->height) {
713 if (output != tmp)
714 printf("assiging surface %p to output %p\n",
715 es, output);
716 es->output = output;
717 }
718 }
719
720 if (es->output == NULL) {
721 printf("no output found\n");
722 es->output = container_of(ec->output_list.next,
723 struct wlsc_output, link);
724 }
725}
726
Kristian Høgsberg5503bf82008-11-06 10:38:17 -0500727static void
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500728surface_attach(struct wl_client *client,
Kristian Høgsberg82da52b2010-12-17 09:53:12 -0500729 struct wl_surface *surface, struct wl_buffer *buffer,
730 int32_t x, int32_t y)
Kristian Høgsberg16eb6752008-10-08 22:51:32 -0400731{
Kristian Høgsberg8e438622009-01-26 23:07:00 -0500732 struct wlsc_surface *es = (struct wlsc_surface *) surface;
Kristian Høgsberg16eb6752008-10-08 22:51:32 -0400733
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -0500734 /* FIXME: This damages the entire old surface, but we should
735 * really just damage the part that's no longer covered by the
736 * surface. Anything covered by the new surface will be
737 * damaged by the client. */
738 wlsc_surface_damage(es);
739
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +0100740 wlsc_buffer_attach(buffer, surface);
741
Kristian Høgsberg3d5bae02010-10-06 21:17:40 -0400742 es->buffer = buffer;
Kristian Høgsberg82da52b2010-12-17 09:53:12 -0500743 es->x += x;
744 es->y += y;
745 es->width = buffer->width;
746 es->height = buffer->height;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100747 if (x != 0 || y != 0)
748 wlsc_surface_assign_output(es);
Kristian Høgsberg82da52b2010-12-17 09:53:12 -0500749 wlsc_surface_update_matrix(es);
Kristian Høgsbergf9212892008-10-11 18:40:23 -0400750}
751
Kristian Høgsberg5503bf82008-11-06 10:38:17 -0500752static void
Kristian Høgsberg82da52b2010-12-17 09:53:12 -0500753surface_map_toplevel(struct wl_client *client,
754 struct wl_surface *surface)
Kristian Høgsberg16eb6752008-10-08 22:51:32 -0400755{
Kristian Høgsberg8e438622009-01-26 23:07:00 -0500756 struct wlsc_surface *es = (struct wlsc_surface *) surface;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100757 struct wlsc_compositor *ec = es->compositor;
Kristian Høgsberg16eb6752008-10-08 22:51:32 -0400758
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500759 switch (es->map_type) {
760 case WLSC_SURFACE_MAP_UNMAPPED:
761 es->x = 10 + random() % 400;
762 es->y = 10 + random() % 400;
763 wlsc_surface_update_matrix(es);
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100764 /* assign to first output */
765 es->output = container_of(ec->output_list.next,
766 struct wlsc_output, link);
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500767 wl_list_insert(&es->compositor->surface_list, &es->link);
768 break;
769 case WLSC_SURFACE_MAP_TOPLEVEL:
Kristian Høgsberg8f66a572011-01-07 08:38:56 -0500770 return;
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500771 case WLSC_SURFACE_MAP_FULLSCREEN:
772 es->fullscreen_output = NULL;
773 es->x = es->saved_x;
774 es->y = es->saved_y;
775 wlsc_surface_update_matrix(es);
776 break;
777 default:
778 break;
779 }
Kristian Høgsberg8f66a572011-01-07 08:38:56 -0500780
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -0500781 wlsc_surface_damage(es);
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500782 es->map_type = WLSC_SURFACE_MAP_TOPLEVEL;
Kristian Høgsberg16eb6752008-10-08 22:51:32 -0400783}
784
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500785static void
Kristian Høgsberg8dc378f2011-01-21 18:02:24 -0500786surface_map_transient(struct wl_client *client,
787 struct wl_surface *surface, struct wl_surface *parent,
788 int x, int y, uint32_t flags)
789{
790 struct wlsc_surface *es = (struct wlsc_surface *) surface;
791 struct wlsc_surface *pes = (struct wlsc_surface *) parent;
792
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500793 switch (es->map_type) {
794 case WLSC_SURFACE_MAP_UNMAPPED:
795 wl_list_insert(&es->compositor->surface_list, &es->link);
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100796 /* assign to parents output */
797 es->output = pes->output;
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500798 break;
799 case WLSC_SURFACE_MAP_FULLSCREEN:
800 es->fullscreen_output = NULL;
801 break;
802 default:
803 break;
804 }
Kristian Høgsberg8dc378f2011-01-21 18:02:24 -0500805
806 es->x = pes->x + x;
807 es->y = pes->y + y;
808
809 wlsc_surface_update_matrix(es);
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -0500810 wlsc_surface_damage(es);
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500811 es->map_type = WLSC_SURFACE_MAP_TRANSIENT;
812}
813
814static void
815surface_map_fullscreen(struct wl_client *client, struct wl_surface *surface)
816{
817 struct wlsc_surface *es = (struct wlsc_surface *) surface;
818 struct wlsc_output *output;
819
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100820 /* FIXME: Fullscreen on first output */
821 /* FIXME: Handle output going away */
822 output = container_of(es->compositor->output_list.next,
823 struct wlsc_output, link);
824
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500825 switch (es->map_type) {
826 case WLSC_SURFACE_MAP_UNMAPPED:
827 es->x = 10 + random() % 400;
828 es->y = 10 + random() % 400;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100829 /* assign to first output */
830 es->output = output;
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500831 wl_list_insert(&es->compositor->surface_list, &es->link);
832 break;
833 case WLSC_SURFACE_MAP_FULLSCREEN:
834 return;
835 default:
836 break;
837 }
838
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500839 es->saved_x = es->x;
840 es->saved_y = es->y;
841 es->x = (output->width - es->width) / 2;
842 es->y = (output->height - es->height) / 2;
843 es->fullscreen_output = output;
844 wlsc_surface_update_matrix(es);
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -0500845 wlsc_surface_damage(es);
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500846 es->map_type = WLSC_SURFACE_MAP_FULLSCREEN;
Kristian Høgsberg8dc378f2011-01-21 18:02:24 -0500847}
848
849static void
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500850surface_damage(struct wl_client *client,
851 struct wl_surface *surface,
852 int32_t x, int32_t y, int32_t width, int32_t height)
Kristian Høgsberg7f77bd82008-11-07 08:39:37 -0500853{
Kristian Høgsberg9d69f8e2010-09-03 14:46:38 -0400854 struct wlsc_surface *es = (struct wlsc_surface *) surface;
855
Kristian Høgsberg3d5bae02010-10-06 21:17:40 -0400856 es->buffer->damage(es->buffer, surface, x, y, width, height);
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -0500857
858 wlsc_surface_damage_rectangle(es, x, y, width, height);
Kristian Høgsbergfbdbbdc2008-11-28 17:06:06 -0500859}
860
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500861const static struct wl_surface_interface surface_interface = {
862 surface_destroy,
863 surface_attach,
Kristian Høgsberg82da52b2010-12-17 09:53:12 -0500864 surface_map_toplevel,
Kristian Høgsberg8dc378f2011-01-21 18:02:24 -0500865 surface_map_transient,
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500866 surface_map_fullscreen,
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500867 surface_damage
868};
869
870static void
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400871wlsc_input_device_attach(struct wlsc_input_device *device,
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200872 int x, int y, int width, int height)
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400873{
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -0500874 wlsc_surface_damage(device->sprite);
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400875
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400876 device->hotspot_x = x;
877 device->hotspot_y = y;
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400878
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -0500879 device->sprite->x = device->input_device.x - device->hotspot_x;
880 device->sprite->y = device->input_device.y - device->hotspot_y;
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200881 device->sprite->width = width;
882 device->sprite->height = height;
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400883 wlsc_surface_update_matrix(device->sprite);
884
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -0500885 wlsc_surface_damage(device->sprite);
Kristian Høgsberg1db21f12010-08-16 16:08:12 -0400886}
887
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200888static void
889wlsc_input_device_attach_buffer(struct wlsc_input_device *device,
890 struct wl_buffer *buffer, int x, int y)
891{
892 wlsc_buffer_attach(buffer, &device->sprite->surface);
893 wlsc_input_device_attach(device, x, y, buffer->width, buffer->height);
894}
895
896static void
897wlsc_input_device_attach_sprite(struct wlsc_input_device *device,
898 struct wlsc_sprite *sprite, int x, int y)
899{
900 wlsc_sprite_attach(sprite, &device->sprite->surface);
901 wlsc_input_device_attach(device, x, y, sprite->width, sprite->height);
902}
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400903
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500904void
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400905wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
906 enum wlsc_pointer_type type)
907{
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -0500908 struct wlsc_compositor *compositor =
909 (struct wlsc_compositor *) device->input_device.compositor;
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400910
Benjamin Franzke431da9a2011-04-20 11:02:58 +0200911 wlsc_input_device_attach_sprite(device,
912 compositor->pointer_sprites[type],
913 pointer_images[type].hotspot_x,
914 pointer_images[type].hotspot_y);
Kristian Høgsbergeef08fb2010-08-17 21:23:10 -0400915}
916
Kristian Høgsberg83fc0612010-08-04 22:44:55 -0400917static void
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500918compositor_create_surface(struct wl_client *client,
919 struct wl_compositor *compositor, uint32_t id)
920{
Kristian Høgsberg8e438622009-01-26 23:07:00 -0500921 struct wlsc_compositor *ec = (struct wlsc_compositor *) compositor;
Kristian Høgsberg8da19ac2009-03-17 16:12:51 -0400922 struct wlsc_surface *surface;
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500923
Kristian Høgsbergc5d6be92011-01-14 16:22:37 -0500924 surface = wlsc_surface_create(ec, 0, 0, 0, 0);
Kristian Høgsberg5fcd0aa2010-08-09 14:43:33 -0400925 if (surface == NULL) {
Kristian Høgsberg13b8ae42010-09-02 20:55:16 -0400926 wl_client_post_no_memory(client);
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500927 return;
Kristian Høgsberg5fcd0aa2010-08-09 14:43:33 -0400928 }
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500929
Kristian Høgsbergb313b022010-12-01 17:07:41 -0500930 surface->surface.resource.destroy = destroy_surface;
Kristian Høgsbergf66d0f42010-09-02 20:27:16 -0400931
Kristian Høgsbergb313b022010-12-01 17:07:41 -0500932 surface->surface.resource.object.id = id;
933 surface->surface.resource.object.interface = &wl_surface_interface;
934 surface->surface.resource.object.implementation =
Kristian Høgsbergf66d0f42010-09-02 20:27:16 -0400935 (void (**)(void)) &surface_interface;
Kristian Høgsbergb313b022010-12-01 17:07:41 -0500936 surface->surface.client = client;
Kristian Høgsbergf66d0f42010-09-02 20:27:16 -0400937
Kristian Høgsbergb313b022010-12-01 17:07:41 -0500938 wl_client_add_resource(client, &surface->surface.resource);
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500939}
940
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500941const static struct wl_compositor_interface compositor_interface = {
942 compositor_create_surface,
Kristian Høgsbergd2412e22008-12-15 20:35:24 -0500943};
944
Kristian Høgsberg7b6907f2009-02-14 17:47:55 -0500945static void
946wlsc_surface_transform(struct wlsc_surface *surface,
947 int32_t x, int32_t y, int32_t *sx, int32_t *sy)
948{
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400949 struct wlsc_vector v = { { x, y, 0, 1 } };
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -0500950
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400951 wlsc_matrix_transform(&surface->matrix_inv, &v);
Kristian Høgsberg0b8646b2010-06-08 15:29:14 -0400952 *sx = v.f[0] * surface->width;
953 *sy = v.f[1] * surface->height;
Kristian Høgsberg7b6907f2009-02-14 17:47:55 -0500954}
955
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500956struct wlsc_surface *
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -0500957pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy)
Kristian Høgsberg201a9042008-12-10 00:40:50 -0500958{
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -0500959 struct wlsc_compositor *ec =
960 (struct wlsc_compositor *) device->compositor;
Kristian Høgsberg8e438622009-01-26 23:07:00 -0500961 struct wlsc_surface *es;
Kristian Høgsberg201a9042008-12-10 00:40:50 -0500962
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400963 wl_list_for_each(es, &ec->surface_list, link) {
964 wlsc_surface_transform(es, device->x, device->y, sx, sy);
965 if (0 <= *sx && *sx < es->width &&
966 0 <= *sy && *sy < es->height)
Kristian Høgsberg201a9042008-12-10 00:40:50 -0500967 return es;
Kristian Høgsberg27803c62010-06-06 22:23:21 -0400968 }
Kristian Høgsberg201a9042008-12-10 00:40:50 -0500969
Kristian Høgsberg201a9042008-12-10 00:40:50 -0500970 return NULL;
971}
972
Kristian Høgsberg8321e692010-12-07 17:06:15 -0500973
974static void
975motion_grab_motion(struct wl_grab *grab,
976 uint32_t time, int32_t x, int32_t y)
977{
978 struct wlsc_input_device *device =
979 (struct wlsc_input_device *) grab->input_device;
980 struct wlsc_surface *es =
981 (struct wlsc_surface *) device->input_device.pointer_focus;
982 int32_t sx, sy;
983
984 wlsc_surface_transform(es, x, y, &sx, &sy);
985 wl_client_post_event(es->surface.client,
986 &device->input_device.object,
987 WL_INPUT_DEVICE_MOTION,
988 time, x, y, sx, sy);
989}
990
991static void
Kristian Høgsbergb3fc7572010-12-08 11:07:57 -0500992motion_grab_button(struct wl_grab *grab,
993 uint32_t time, int32_t button, int32_t state)
994{
995 wl_client_post_event(grab->input_device->pointer_focus->client,
996 &grab->input_device->object,
997 WL_INPUT_DEVICE_BUTTON,
998 time, button, state);
999}
1000
1001static void
Kristian Høgsberg8321e692010-12-07 17:06:15 -05001002motion_grab_end(struct wl_grab *grab, uint32_t time)
1003{
1004}
1005
1006static const struct wl_grab_interface motion_grab_interface = {
1007 motion_grab_motion,
Kristian Høgsbergb3fc7572010-12-08 11:07:57 -05001008 motion_grab_button,
Kristian Høgsberg8321e692010-12-07 17:06:15 -05001009 motion_grab_end
1010};
1011
Kristian Høgsberg5ee1a602008-12-11 23:18:45 -05001012void
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001013notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
Kristian Høgsberg715a0812008-12-10 10:42:04 -05001014{
Kristian Høgsberg8e438622009-01-26 23:07:00 -05001015 struct wlsc_surface *es;
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001016 struct wlsc_compositor *ec =
1017 (struct wlsc_compositor *) device->compositor;
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05001018 struct wlsc_output *output;
Kristian Høgsberg6d65d5f2010-12-07 13:30:18 -05001019 const struct wl_grab_interface *interface;
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001020 struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
Kristian Høgsbergfc9c28a2010-12-07 13:04:43 -05001021 int32_t sx, sy;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +01001022 int x_valid = 0, y_valid = 0;
1023 int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN;
Kristian Høgsberg715a0812008-12-10 10:42:04 -05001024
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +01001025 wl_list_for_each(output, &ec->output_list, link) {
1026 if (output->x <= x && x <= output->x + output->width)
1027 x_valid = 1;
1028
1029 if (output->y <= y && y <= output->y + output->height)
1030 y_valid = 1;
1031
1032 /* FIXME: calculate this only on output addition/deletion */
1033 if (output->x < min_x)
1034 min_x = output->x;
1035 if (output->y < min_y)
1036 min_y = output->y;
1037
1038 if (output->x + output->width > max_x)
1039 max_x = output->x + output->width;
1040 if (output->y + output->height > max_y)
1041 max_y = output->y + output->height;
1042 }
1043
1044 if (!x_valid) {
1045 if (x < min_x)
1046 x = min_x;
1047 else if (x >= max_x)
1048 x = max_x;
1049 }
1050 if (!y_valid) {
1051 if (y < min_y)
1052 y = min_y;
1053 else if (y >= max_y)
1054 y = max_y;
1055 }
Ray Strode90e701d2008-12-18 23:05:43 -05001056
Kristian Høgsberge3ef3e52008-12-21 19:30:01 -05001057 device->x = x;
1058 device->y = y;
Kristian Høgsbergdb6c2f32009-02-22 21:51:24 -05001059
Kristian Høgsberg8321e692010-12-07 17:06:15 -05001060 if (device->grab) {
1061 interface = device->grab->interface;
1062 interface->motion(device->grab, time, x, y);
1063 } else {
Kristian Høgsberg83fc0612010-08-04 22:44:55 -04001064 es = pick_surface(device, &sx, &sy);
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001065 wl_input_device_set_pointer_focus(device,
Kristian Høgsbergb313b022010-12-01 17:07:41 -05001066 &es->surface,
Kristian Høgsberg26437072010-12-01 10:17:47 -05001067 time, x, y, sx, sy);
Kristian Høgsberg83fc0612010-08-04 22:44:55 -04001068 if (es)
Kristian Høgsbergb313b022010-12-01 17:07:41 -05001069 wl_client_post_event(es->surface.client,
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001070 &device->object,
Kristian Høgsberg50038e42010-09-07 21:08:59 -04001071 WL_INPUT_DEVICE_MOTION,
1072 time, x, y, sx, sy);
Kristian Høgsberg83fc0612010-08-04 22:44:55 -04001073 }
Kristian Høgsberg715a0812008-12-10 10:42:04 -05001074
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -05001075 wlsc_surface_damage(wd->sprite);
1076
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001077 wd->sprite->x = device->x - wd->hotspot_x;
1078 wd->sprite->y = device->y - wd->hotspot_y;
1079 wlsc_surface_update_matrix(wd->sprite);
Kristian Høgsberg5ee1a602008-12-11 23:18:45 -05001080
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -05001081 wlsc_surface_damage(wd->sprite);
Kristian Høgsberg715a0812008-12-10 10:42:04 -05001082}
1083
Kristian Høgsberg30021d72011-04-12 17:42:30 -04001084void
Kristian Høgsbergc9824dd2011-02-06 16:54:59 -05001085wlsc_surface_activate(struct wlsc_surface *surface,
1086 struct wlsc_input_device *device, uint32_t time)
1087{
1088 wlsc_surface_raise(surface);
1089 if (device->selection)
1090 wlsc_selection_set_focus(device->selection,
1091 &surface->surface, time);
1092
1093 wl_input_device_set_keyboard_focus(&device->input_device,
1094 &surface->surface,
1095 time);
1096}
1097
Kristian Høgsberga8ec8632011-04-12 17:22:49 -04001098struct wlsc_binding {
1099 uint32_t key;
1100 uint32_t button;
1101 uint32_t modifier;
1102 wlsc_binding_handler_t handler;
1103 void *data;
1104 struct wl_list link;
1105};
1106
Kristian Høgsberg5ee1a602008-12-11 23:18:45 -05001107void
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001108notify_button(struct wl_input_device *device,
Kristian Høgsberg808fd412010-07-20 17:06:19 -04001109 uint32_t time, int32_t button, int32_t state)
Kristian Høgsbergeac149a2008-12-10 00:24:18 -05001110{
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001111 struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001112 struct wlsc_compositor *compositor =
1113 (struct wlsc_compositor *) device->compositor;
Kristian Høgsberga8ec8632011-04-12 17:22:49 -04001114 struct wlsc_binding *b;
1115 struct wlsc_surface *surface =
1116 (struct wlsc_surface *) device->pointer_focus;
Kristian Høgsbergea081152010-12-07 08:59:51 -05001117
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -05001118 if (state && surface && device->grab == NULL) {
Kristian Høgsbergc9824dd2011-02-06 16:54:59 -05001119 wlsc_surface_activate(surface, wd, time);
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001120 wl_input_device_start_grab(device,
1121 &device->motion_grab,
1122 button, time);
Kristian Høgsberg5ee1a602008-12-11 23:18:45 -05001123 }
Kristian Høgsbergdff2e3c2010-12-07 09:02:09 -05001124
Kristian Høgsberga8ec8632011-04-12 17:22:49 -04001125 wl_list_for_each(b, &compositor->binding_list, link) {
1126 if (b->button == button &&
1127 b->modifier == wd->modifier_state && state) {
1128 b->handler(&wd->input_device,
1129 time, 0, button, state, b->data);
1130 break;
1131 }
Benjamin Franzke5a2218a2011-02-01 16:30:31 +01001132 }
Kristian Høgsbergb3fc7572010-12-08 11:07:57 -05001133
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -05001134 if (device->grab)
1135 device->grab->interface->button(device->grab, time,
1136 button, state);
Kristian Høgsbergdff2e3c2010-12-07 09:02:09 -05001137
Kristian Høgsberg8321e692010-12-07 17:06:15 -05001138 if (!state && device->grab && device->grab_button == button)
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001139 wl_input_device_end_grab(device, time);
Kristian Høgsbergeac149a2008-12-10 00:24:18 -05001140}
1141
Kristian Høgsbergc9824dd2011-02-06 16:54:59 -05001142static void
Kristian Høgsberga8ec8632011-04-12 17:22:49 -04001143terminate_binding(struct wl_input_device *device, uint32_t time,
1144 uint32_t key, uint32_t button, uint32_t state, void *data)
Kristian Høgsberg3555d092011-04-11 13:58:13 -04001145{
1146 struct wlsc_compositor *compositor = data;
1147
1148 wl_display_terminate(compositor->wl_display);
1149}
1150
1151struct wlsc_binding *
1152wlsc_compositor_add_binding(struct wlsc_compositor *compositor,
Kristian Høgsberga8ec8632011-04-12 17:22:49 -04001153 uint32_t key, uint32_t button, uint32_t modifier,
Kristian Høgsberg3555d092011-04-11 13:58:13 -04001154 wlsc_binding_handler_t handler, void *data)
1155{
1156 struct wlsc_binding *binding;
1157
1158 binding = malloc(sizeof *binding);
1159 if (binding == NULL)
1160 return NULL;
1161
1162 binding->key = key;
Kristian Høgsberga8ec8632011-04-12 17:22:49 -04001163 binding->button = button;
Kristian Høgsberg3555d092011-04-11 13:58:13 -04001164 binding->modifier = modifier;
1165 binding->handler = handler;
1166 binding->data = data;
1167 wl_list_insert(compositor->binding_list.prev, &binding->link);
1168
1169 return binding;
1170}
1171
1172void
1173wlsc_binding_destroy(struct wlsc_binding *binding)
1174{
1175 wl_list_remove(&binding->link);
1176 free(binding);
1177}
1178
Kristian Høgsbergf512d072011-04-12 17:16:00 -04001179static void
1180update_modifier_state(struct wlsc_input_device *device,
1181 uint32_t key, uint32_t state)
Kristian Høgsbergcddc0ad2008-11-24 00:31:49 -05001182{
Kristian Høgsberg2cbedd12009-09-18 17:29:49 -04001183 uint32_t modifier;
Kristian Høgsbergab909ae2001-01-01 22:24:24 -05001184
Kristian Høgsberg2cbedd12009-09-18 17:29:49 -04001185 switch (key) {
1186 case KEY_LEFTCTRL:
1187 case KEY_RIGHTCTRL:
1188 modifier = MODIFIER_CTRL;
1189 break;
1190
1191 case KEY_LEFTALT:
1192 case KEY_RIGHTALT:
1193 modifier = MODIFIER_ALT;
1194 break;
1195
Kristian Høgsberg5b75f1b2010-08-04 23:21:41 -04001196 case KEY_LEFTMETA:
1197 case KEY_RIGHTMETA:
1198 modifier = MODIFIER_SUPER;
1199 break;
1200
Kristian Høgsberg2cbedd12009-09-18 17:29:49 -04001201 default:
1202 modifier = 0;
1203 break;
1204 }
1205
1206 if (state)
Kristian Høgsbergf512d072011-04-12 17:16:00 -04001207 device->modifier_state |= modifier;
Kristian Høgsberg2cbedd12009-09-18 17:29:49 -04001208 else
Kristian Høgsbergf512d072011-04-12 17:16:00 -04001209 device->modifier_state &= ~modifier;
1210}
Kristian Høgsberg2cbedd12009-09-18 17:29:49 -04001211
Kristian Høgsbergf512d072011-04-12 17:16:00 -04001212void
1213notify_key(struct wl_input_device *device,
1214 uint32_t time, uint32_t key, uint32_t state)
1215{
1216 struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
1217 struct wlsc_compositor *compositor =
1218 (struct wlsc_compositor *) device->compositor;
1219 uint32_t *k, *end;
1220 struct wlsc_binding *b;
1221
1222 wl_list_for_each(b, &compositor->binding_list, link) {
1223 if (b->key == key &&
1224 b->modifier == wd->modifier_state && state) {
Kristian Høgsberga8ec8632011-04-12 17:22:49 -04001225 b->handler(&wd->input_device,
1226 time, key, 0, state, b->data);
Kristian Høgsbergf512d072011-04-12 17:16:00 -04001227 break;
1228 }
1229 }
1230
1231 update_modifier_state(wd, key, state);
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001232 end = device->keys.data + device->keys.size;
1233 for (k = device->keys.data; k < end; k++) {
Kristian Høgsberg3c38fa02009-02-23 22:30:29 -05001234 if (*k == key)
1235 *k = *--end;
1236 }
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001237 device->keys.size = (void *) end - device->keys.data;
Kristian Høgsberg3c38fa02009-02-23 22:30:29 -05001238 if (state) {
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001239 k = wl_array_add(&device->keys, sizeof *k);
Kristian Høgsberg3c38fa02009-02-23 22:30:29 -05001240 *k = key;
1241 }
Ray Strodee96dcb82008-12-20 02:00:49 -05001242
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001243 if (device->keyboard_focus != NULL)
1244 wl_client_post_event(device->keyboard_focus->client,
1245 &device->object,
Kristian Høgsberg50038e42010-09-07 21:08:59 -04001246 WL_INPUT_DEVICE_KEY, time, key, state);
Kristian Høgsberg808fd412010-07-20 17:06:19 -04001247}
1248
Kristian Høgsberg93331ff2011-01-26 20:35:07 -05001249void
1250notify_pointer_focus(struct wl_input_device *device,
1251 uint32_t time, struct wlsc_output *output,
1252 int32_t x, int32_t y)
1253{
1254 struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
1255 struct wlsc_compositor *compositor =
1256 (struct wlsc_compositor *) device->compositor;
1257 struct wlsc_surface *es;
1258 int32_t sx, sy;
1259
1260 if (output) {
1261 device->x = x;
1262 device->y = y;
1263 es = pick_surface(device, &sx, &sy);
1264 wl_input_device_set_pointer_focus(device,
1265 &es->surface,
1266 time, x, y, sx, sy);
1267
1268 compositor->focus = 1;
1269
1270 wd->sprite->x = device->x - wd->hotspot_x;
1271 wd->sprite->y = device->y - wd->hotspot_y;
1272 wlsc_surface_update_matrix(wd->sprite);
1273 } else {
1274 wl_input_device_set_pointer_focus(device, NULL,
1275 time, 0, 0, 0, 0);
1276 compositor->focus = 0;
1277 }
1278
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -05001279 wlsc_surface_damage(wd->sprite);
Kristian Høgsberg93331ff2011-01-26 20:35:07 -05001280}
1281
Kristian Høgsberg3ba48582011-01-27 11:57:19 -05001282void
Kristian Høgsbergf992b2f2011-01-28 15:53:07 -05001283notify_keyboard_focus(struct wl_input_device *device,
Kristian Høgsberg3ba48582011-01-27 11:57:19 -05001284 uint32_t time, struct wlsc_output *output,
1285 struct wl_array *keys)
1286{
Kristian Høgsbergf992b2f2011-01-28 15:53:07 -05001287 struct wlsc_input_device *wd =
1288 (struct wlsc_input_device *) device;
1289 struct wlsc_compositor *compositor =
1290 (struct wlsc_compositor *) device->compositor;
1291 struct wlsc_surface *es;
Kristian Høgsbergf512d072011-04-12 17:16:00 -04001292 uint32_t *k, *end;
Kristian Høgsbergf992b2f2011-01-28 15:53:07 -05001293
1294 if (!wl_list_empty(&compositor->surface_list))
1295 es = container_of(compositor->surface_list.next,
1296 struct wlsc_surface, link);
1297 else
1298 es = NULL;
Kristian Høgsberg3ba48582011-01-27 11:57:19 -05001299
1300 if (output) {
Kristian Høgsbergf992b2f2011-01-28 15:53:07 -05001301 wl_array_copy(&wd->input_device.keys, keys);
Kristian Høgsbergf512d072011-04-12 17:16:00 -04001302 wd->modifier_state = 0;
1303 end = device->keys.data + device->keys.size;
1304 for (k = device->keys.data; k < end; k++) {
1305 update_modifier_state(wd, *k, 1);
1306 }
1307
Kristian Høgsbergf992b2f2011-01-28 15:53:07 -05001308 wl_input_device_set_keyboard_focus(&wd->input_device,
1309 &es->surface, time);
Kristian Høgsberg3ba48582011-01-27 11:57:19 -05001310 } else {
Kristian Høgsbergf512d072011-04-12 17:16:00 -04001311 wd->modifier_state = 0;
Kristian Høgsbergf992b2f2011-01-28 15:53:07 -05001312 wl_input_device_set_keyboard_focus(&wd->input_device,
Kristian Høgsberg3ba48582011-01-27 11:57:19 -05001313 NULL, time);
1314 }
1315}
1316
1317
Kristian Høgsberg77fb1672010-08-16 10:38:29 -04001318static void
Kristian Høgsbergab1862d2010-12-09 11:29:40 -05001319input_device_attach(struct wl_client *client,
1320 struct wl_input_device *device_base,
1321 uint32_t time,
1322 struct wl_buffer *buffer, int32_t x, int32_t y)
1323{
1324 struct wlsc_input_device *device =
1325 (struct wlsc_input_device *) device_base;
1326
1327 if (time < device->input_device.pointer_focus_time)
1328 return;
1329 if (device->input_device.pointer_focus == NULL)
1330 return;
Kristian Høgsbergab1862d2010-12-09 11:29:40 -05001331 if (device->input_device.pointer_focus->client != client)
1332 return;
1333
1334 if (buffer == NULL) {
1335 wlsc_input_device_set_pointer_image(device,
1336 WLSC_POINTER_LEFT_PTR);
1337 return;
1338 }
1339
Benjamin Franzke431da9a2011-04-20 11:02:58 +02001340 wlsc_input_device_attach_buffer(device, buffer, x, y);
Kristian Høgsbergab1862d2010-12-09 11:29:40 -05001341}
1342
1343const static struct wl_input_device_interface input_device_interface = {
1344 input_device_attach,
1345};
1346
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04001347void
1348wlsc_input_device_init(struct wlsc_input_device *device,
1349 struct wlsc_compositor *ec)
Kristian Høgsbergcddc0ad2008-11-24 00:31:49 -05001350{
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001351 wl_input_device_init(&device->input_device, &ec->compositor);
Kristian Høgsberg02ef1c12010-12-06 21:35:19 -05001352
Kristian Høgsbergb313b022010-12-01 17:07:41 -05001353 device->input_device.object.interface = &wl_input_device_interface;
1354 device->input_device.object.implementation =
Kristian Høgsberg77fb1672010-08-16 10:38:29 -04001355 (void (**)(void)) &input_device_interface;
Kristian Høgsbergb313b022010-12-01 17:07:41 -05001356 wl_display_add_object(ec->wl_display, &device->input_device.object);
1357 wl_display_add_global(ec->wl_display, &device->input_device.object, NULL);
Kristian Høgsberg5fcd0aa2010-08-09 14:43:33 -04001358
Kristian Høgsbergc5d6be92011-01-14 16:22:37 -05001359 device->sprite = wlsc_surface_create(ec,
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001360 device->input_device.x,
1361 device->input_device.y, 32, 32);
Kristian Høgsberg77fb1672010-08-16 10:38:29 -04001362 device->hotspot_x = 16;
1363 device->hotspot_y = 16;
Kristian Høgsberga8ec8632011-04-12 17:22:49 -04001364 device->modifier_state = 0;
Kristian Høgsberg5ee1a602008-12-11 23:18:45 -05001365
Kristian Høgsberg9c3e8d72010-12-08 09:48:52 -05001366 device->input_device.motion_grab.interface = &motion_grab_interface;
Kristian Høgsberg8321e692010-12-07 17:06:15 -05001367
Kristian Høgsbergc492b482008-12-12 12:00:02 -05001368 wl_list_insert(ec->input_device_list.prev, &device->link);
Kristian Høgsberg1db21f12010-08-16 16:08:12 -04001369
1370 wlsc_input_device_set_pointer_image(device, WLSC_POINTER_LEFT_PTR);
Kristian Høgsberg5ee1a602008-12-11 23:18:45 -05001371}
1372
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05001373static void
Kristian Høgsberg91342c62011-04-14 14:44:58 -04001374wlsc_output_post_geometry(struct wl_client *client,
1375 struct wl_object *global, uint32_t version)
Kristian Høgsbergbf9541f2008-11-25 12:10:09 -05001376{
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05001377 struct wlsc_output *output =
Kristian Høgsbergb313b022010-12-01 17:07:41 -05001378 container_of(global, struct wlsc_output, object);
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05001379
1380 wl_client_post_event(client, global,
1381 WL_OUTPUT_GEOMETRY,
Kristian Høgsbergf8fc08f2010-12-01 20:10:10 -05001382 output->x, output->y,
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05001383 output->width, output->height);
1384}
1385
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001386static const char vertex_shader[] =
1387 "uniform mat4 proj;\n"
Kristian Høgsbergfa4e2a72011-02-13 13:44:55 -05001388 "attribute vec2 position;\n"
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001389 "attribute vec2 texcoord;\n"
1390 "varying vec2 v_texcoord;\n"
1391 "void main()\n"
1392 "{\n"
Kristian Høgsbergfa4e2a72011-02-13 13:44:55 -05001393 " gl_Position = proj * vec4(position, 0.0, 1.0);\n"
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001394 " v_texcoord = texcoord;\n"
1395 "}\n";
1396
1397static const char fragment_shader[] =
Kristian Høgsbergdfce71d2010-12-07 20:19:10 -05001398 "precision mediump float;\n"
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001399 "varying vec2 v_texcoord;\n"
1400 "uniform sampler2D tex;\n"
1401 "void main()\n"
1402 "{\n"
1403 " gl_FragColor = texture2D(tex, v_texcoord)\n;"
1404 "}\n";
1405
Kristian Høgsberga9468212010-06-14 21:03:11 -04001406static int
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001407init_shaders(struct wlsc_compositor *ec)
1408{
Kristian Høgsberg67a21bd2010-06-25 18:58:24 -04001409 GLuint v, f, program;
1410 const char *p;
1411 char msg[512];
Kristian Høgsberg67a21bd2010-06-25 18:58:24 -04001412 GLint status;
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001413
Kristian Høgsberg67a21bd2010-06-25 18:58:24 -04001414 p = vertex_shader;
1415 v = glCreateShader(GL_VERTEX_SHADER);
1416 glShaderSource(v, 1, &p, NULL);
1417 glCompileShader(v);
1418 glGetShaderiv(v, GL_COMPILE_STATUS, &status);
1419 if (!status) {
1420 glGetShaderInfoLog(v, sizeof msg, NULL, msg);
1421 fprintf(stderr, "vertex shader info: %s\n", msg);
1422 return -1;
1423 }
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001424
Kristian Høgsberg67a21bd2010-06-25 18:58:24 -04001425 p = fragment_shader;
1426 f = glCreateShader(GL_FRAGMENT_SHADER);
1427 glShaderSource(f, 1, &p, NULL);
1428 glCompileShader(f);
1429 glGetShaderiv(f, GL_COMPILE_STATUS, &status);
1430 if (!status) {
1431 glGetShaderInfoLog(f, sizeof msg, NULL, msg);
1432 fprintf(stderr, "fragment shader info: %s\n", msg);
1433 return -1;
1434 }
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001435
Kristian Høgsberg67a21bd2010-06-25 18:58:24 -04001436 program = glCreateProgram();
1437 glAttachShader(program, v);
1438 glAttachShader(program, f);
1439 glBindAttribLocation(program, 0, "position");
1440 glBindAttribLocation(program, 1, "texcoord");
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001441
Kristian Høgsberg67a21bd2010-06-25 18:58:24 -04001442 glLinkProgram(program);
1443 glGetProgramiv(program, GL_LINK_STATUS, &status);
1444 if (!status) {
1445 glGetProgramInfoLog(program, sizeof msg, NULL, msg);
1446 fprintf(stderr, "link info: %s\n", msg);
1447 return -1;
1448 }
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001449
Kristian Høgsberg67a21bd2010-06-25 18:58:24 -04001450 glUseProgram(program);
1451 ec->proj_uniform = glGetUniformLocation(program, "proj");
1452 ec->tex_uniform = glGetUniformLocation(program, "tex");
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001453
Kristian Høgsberg67a21bd2010-06-25 18:58:24 -04001454 return 0;
Kristian Høgsberg27803c62010-06-06 22:23:21 -04001455}
1456
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04001457void
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01001458wlsc_output_destroy(struct wlsc_output *output)
Kristian Høgsberg16eb6752008-10-08 22:51:32 -04001459{
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01001460 destroy_surface(&output->background->surface.resource, NULL);
1461}
1462
1463void
1464wlsc_output_move(struct wlsc_output *output, int x, int y)
1465{
1466 struct wlsc_compositor *c = output->compositor;
Benjamin Franzke1b765ff2011-02-18 16:51:37 +01001467 int flip;
1468
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04001469 output->x = x;
1470 output->y = y;
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01001471
Benjamin Franzke264b3f92011-03-16 13:48:42 +01001472 if (output->background) {
1473 output->background->x = x;
1474 output->background->y = y;
1475 wlsc_surface_update_matrix(output->background);
1476 }
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04001477
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -05001478 pixman_region32_init(&output->previous_damage_region);
1479
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04001480 wlsc_matrix_init(&output->matrix);
1481 wlsc_matrix_translate(&output->matrix,
1482 -output->x - output->width / 2.0,
1483 -output->y - output->height / 2.0, 0);
Benjamin Franzke1b765ff2011-02-18 16:51:37 +01001484
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01001485 flip = (output->flags & WL_OUTPUT_FLIPPED) ? -1 : 1;
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04001486 wlsc_matrix_scale(&output->matrix,
Benjamin Franzke1b765ff2011-02-18 16:51:37 +01001487 2.0 / output->width,
1488 flip * 2.0 / output->height, 1);
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04001489
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01001490 pixman_region32_union_rect(&c->damage_region,
1491 &c->damage_region,
1492 x, y, output->width, output->height);
1493}
1494
1495void
1496wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
1497 int x, int y, int width, int height, uint32_t flags)
1498{
1499 output->compositor = c;
1500 output->x = x;
1501 output->y = y;
1502 output->width = width;
1503 output->height = height;
1504
1505 output->background =
1506 background_create(output, option_background);
1507
1508 output->flags = flags;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +01001509 output->finished = 1;
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01001510 wlsc_output_move(output, x, y);
1511
Kristian Høgsbergb313b022010-12-01 17:07:41 -05001512 output->object.interface = &wl_output_interface;
1513 wl_display_add_object(c->wl_display, &output->object);
1514 wl_display_add_global(c->wl_display, &output->object,
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04001515 wlsc_output_post_geometry);
1516}
1517
1518int
1519wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display)
1520{
Kristian Høgsbergfbdbbdc2008-11-28 17:06:06 -05001521 struct wl_event_loop *loop;
Kristian Høgsbergd711d0c2011-01-14 17:28:21 -05001522 const char *extensions;
Kristian Høgsberg16eb6752008-10-08 22:51:32 -04001523
Kristian Høgsbergf9212892008-10-11 18:40:23 -04001524 ec->wl_display = display;
Kristian Høgsberg16eb6752008-10-08 22:51:32 -04001525
Kristian Høgsbergc5c510e2010-12-08 15:12:58 -05001526 wl_compositor_init(&ec->compositor, &compositor_interface, display);
Kristian Høgsbergee02ca62008-12-21 23:37:12 -05001527
Kristian Høgsberg3d5bae02010-10-06 21:17:40 -04001528 wlsc_shm_init(ec);
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +01001529 eglBindWaylandDisplayWL(ec->display, ec->wl_display);
Kristian Høgsberg3d5bae02010-10-06 21:17:40 -04001530
Kristian Høgsberg201a9042008-12-10 00:40:50 -05001531 wl_list_init(&ec->surface_list);
Kristian Høgsberg81ce09a2008-12-31 16:18:42 -05001532 wl_list_init(&ec->input_device_list);
1533 wl_list_init(&ec->output_list);
Kristian Høgsberg3555d092011-04-11 13:58:13 -04001534 wl_list_init(&ec->binding_list);
1535
Kristian Høgsberg07937562011-04-12 17:25:42 -04001536 wlsc_shell_init(ec);
Kristian Høgsberg30021d72011-04-12 17:42:30 -04001537 wlsc_switcher_init(ec);
Kristian Høgsberg07937562011-04-12 17:25:42 -04001538
Kristian Høgsberga8ec8632011-04-12 17:22:49 -04001539 wlsc_compositor_add_binding(ec, KEY_BACKSPACE, 0,
Kristian Høgsberg3555d092011-04-11 13:58:13 -04001540 MODIFIER_CTRL | MODIFIER_ALT,
1541 terminate_binding, ec);
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001542
Kristian Høgsberg1db21f12010-08-16 16:08:12 -04001543 create_pointer_images(ec);
1544
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001545 screenshooter_create(ec);
1546
Kristian Høgsbergd711d0c2011-01-14 17:28:21 -05001547 extensions = (const char *) glGetString(GL_EXTENSIONS);
1548 if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
1549 fprintf(stderr,
1550 "GL_EXT_texture_format_BGRA8888 not available\n");
1551 return -1;
1552 }
1553
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001554 glActiveTexture(GL_TEXTURE0);
Kristian Høgsberga9468212010-06-14 21:03:11 -04001555 if (init_shaders(ec) < 0)
1556 return -1;
Kristian Høgsberg8d7ca6b2008-11-09 00:22:51 -05001557
Kristian Høgsbergfbdbbdc2008-11-28 17:06:06 -05001558 loop = wl_display_get_event_loop(ec->wl_display);
Kristian Høgsberg4a298902008-11-28 18:35:25 -05001559 ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec);
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -05001560 pixman_region32_init(&ec->damage_region);
Kristian Høgsberg8da19ac2009-03-17 16:12:51 -04001561 wlsc_compositor_schedule_repaint(ec);
Kristian Høgsbergef7a9ca2008-10-11 21:21:39 -04001562
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04001563 return 0;
Kristian Høgsberg122912c2008-12-05 11:13:50 -05001564}
1565
Kristian Høgsberg50dc6982010-12-01 16:43:56 -05001566static void on_term_signal(int signal_number, void *data)
1567{
1568 struct wlsc_compositor *ec = data;
1569
1570 wl_display_terminate(ec->wl_display);
1571}
1572
Kristian Høgsberg122912c2008-12-05 11:13:50 -05001573int main(int argc, char *argv[])
1574{
1575 struct wl_display *display;
Kristian Høgsberg8e438622009-01-26 23:07:00 -05001576 struct wlsc_compositor *ec;
Kristian Høgsberg50dc6982010-12-01 16:43:56 -05001577 struct wl_event_loop *loop;
Kristian Høgsbergd6531262008-12-12 11:06:18 -05001578 GError *error = NULL;
1579 GOptionContext *context;
Kristian Høgsberg61a82512010-10-26 11:26:44 -04001580 int width, height;
Kristian Høgsbergd6531262008-12-12 11:06:18 -05001581
Kristian Høgsberg77fb1672010-08-16 10:38:29 -04001582 g_type_init(); /* GdkPixbuf needs this, it seems. */
1583
Kristian Høgsbergd6531262008-12-12 11:06:18 -05001584 context = g_option_context_new(NULL);
1585 g_option_context_add_main_entries(context, option_entries, "Wayland");
1586 if (!g_option_context_parse(context, &argc, &argv, &error)) {
1587 fprintf(stderr, "option parsing failed: %s\n", error->message);
1588 exit(EXIT_FAILURE);
1589 }
Kristian Høgsberg61a82512010-10-26 11:26:44 -04001590 if (sscanf(option_geometry, "%dx%d", &width, &height) != 2) {
1591 fprintf(stderr, "invalid geometry option: %s \n",
1592 option_geometry);
1593 exit(EXIT_FAILURE);
1594 }
Kristian Høgsberg122912c2008-12-05 11:13:50 -05001595
1596 display = wl_display_create();
1597
Kristian Høgsberga9410222011-01-14 17:22:35 -05001598 ec = NULL;
1599
1600#if BUILD_WAYLAND_COMPOSITOR
Benjamin Franzkeec2e6422010-11-27 19:04:12 +01001601 if (getenv("WAYLAND_DISPLAY"))
1602 ec = wayland_compositor_create(display, width, height);
Kristian Høgsberga9410222011-01-14 17:22:35 -05001603#endif
1604
1605#if BUILD_X11_COMPOSITOR
1606 if (ec == NULL && getenv("DISPLAY"))
Kristian Høgsberg61a82512010-10-26 11:26:44 -04001607 ec = x11_compositor_create(display, width, height);
Kristian Høgsberga9410222011-01-14 17:22:35 -05001608#endif
1609
Benjamin Franzke5d007092011-04-04 00:30:25 +02001610#if BUILD_OPENWFD_COMPOSITOR
1611 if (ec == NULL && getenv("OPENWFD"))
1612 ec = wfd_compositor_create(display, option_connector);
1613#endif
1614
Kristian Høgsberga9410222011-01-14 17:22:35 -05001615#if BUILD_DRM_COMPOSITOR
1616 if (ec == NULL)
Kristian Høgsberg61a82512010-10-26 11:26:44 -04001617 ec = drm_compositor_create(display, option_connector);
Kristian Høgsberga9410222011-01-14 17:22:35 -05001618#endif
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04001619
Kristian Høgsberg841883b2008-12-05 11:19:56 -05001620 if (ec == NULL) {
1621 fprintf(stderr, "failed to create compositor\n");
1622 exit(EXIT_FAILURE);
1623 }
Kristian Høgsberg61a82512010-10-26 11:26:44 -04001624
Kristian Høgsberg2bb3ebe2010-12-01 15:36:20 -05001625 if (wl_display_add_socket(display, option_socket_name)) {
Kristian Høgsberg122912c2008-12-05 11:13:50 -05001626 fprintf(stderr, "failed to add socket: %m\n");
1627 exit(EXIT_FAILURE);
1628 }
1629
Kristian Høgsberg50dc6982010-12-01 16:43:56 -05001630 loop = wl_display_get_event_loop(ec->wl_display);
1631 wl_event_loop_add_signal(loop, SIGTERM, on_term_signal, ec);
1632 wl_event_loop_add_signal(loop, SIGINT, on_term_signal, ec);
1633
Kristian Høgsberg122912c2008-12-05 11:13:50 -05001634 wl_display_run(display);
1635
Benjamin Franzkefaa0a9d2011-02-21 16:24:53 +01001636 eglUnbindWaylandDisplayWL(ec->display, display);
Kristian Høgsberg2bb3ebe2010-12-01 15:36:20 -05001637 wl_display_destroy(display);
1638
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05001639 ec->destroy(ec);
1640
Kristian Høgsberg122912c2008-12-05 11:13:50 -05001641 return 0;
Kristian Høgsberg16eb6752008-10-08 22:51:32 -04001642}