compositor: Dont repick for grabbed surfaces
[profile/ivi/weston.git] / compositor / compositor.c
1 /*
2  * Copyright © 2010-2011 Intel Corporation
3  * Copyright © 2008-2011 Kristian Høgsberg
4  *
5  * 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.
14  *
15  * 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.
22  */
23
24 #define _GNU_SOURCE
25
26 #include "config.h"
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdint.h>
32 #include <limits.h>
33 #include <stdarg.h>
34 #include <assert.h>
35 #include <sys/ioctl.h>
36 #include <sys/wait.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39 #include <math.h>
40 #include <linux/input.h>
41 #include <dlfcn.h>
42 #include <getopt.h>
43 #include <signal.h>
44
45 #include "wayland-server.h"
46 #include "compositor.h"
47
48 /* The plan here is to generate a random anonymous socket name and
49  * advertise that through a service on the session dbus.
50  */
51 static const char *option_socket_name = NULL;
52 static int option_idle_time = 300;
53
54 static struct wl_list child_process_list;
55
56 static int
57 sigchld_handler(int signal_number, void *data)
58 {
59         struct wlsc_process *p;
60         int status;
61         pid_t pid;
62
63         pid = wait(&status);
64         wl_list_for_each(p, &child_process_list, link) {
65                 if (p->pid == pid)
66                         break;
67         }
68
69         if (&p->link == &child_process_list) {
70                 fprintf(stderr, "unknown child process exited\n");
71                 return 1;
72         }
73
74         wl_list_remove(&p->link);
75         p->cleanup(p, status);
76
77         return 1;
78 }
79
80 WL_EXPORT void
81 wlsc_watch_process(struct wlsc_process *process)
82 {
83         wl_list_insert(&child_process_list, &process->link);
84 }
85
86 WL_EXPORT void
87 wlsc_matrix_init(struct wlsc_matrix *matrix)
88 {
89         static const struct wlsc_matrix identity = {
90                 { 1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  0, 0, 0, 1 }
91         };
92
93         memcpy(matrix, &identity, sizeof identity);
94 }
95
96 static void
97 wlsc_matrix_multiply(struct wlsc_matrix *m, const struct wlsc_matrix *n)
98 {
99         struct wlsc_matrix tmp;
100         const GLfloat *row, *column;
101         div_t d;
102         int i, j;
103
104         for (i = 0; i < 16; i++) {
105                 tmp.d[i] = 0;
106                 d = div(i, 4);
107                 row = m->d + d.quot * 4;
108                 column = n->d + d.rem;
109                 for (j = 0; j < 4; j++)
110                         tmp.d[i] += row[j] * column[j * 4];
111         }
112         memcpy(m, &tmp, sizeof tmp);
113 }
114
115 WL_EXPORT void
116 wlsc_matrix_translate(struct wlsc_matrix *matrix, GLfloat x, GLfloat y, GLfloat z)
117 {
118         struct wlsc_matrix translate = {
119                 { 1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  x, y, z, 1 }
120         };
121
122         wlsc_matrix_multiply(matrix, &translate);
123 }
124
125 WL_EXPORT void
126 wlsc_matrix_scale(struct wlsc_matrix *matrix, GLfloat x, GLfloat y, GLfloat z)
127 {
128         struct wlsc_matrix scale = {
129                 { x, 0, 0, 0,  0, y, 0, 0,  0, 0, z, 0,  0, 0, 0, 1 }
130         };
131
132         wlsc_matrix_multiply(matrix, &scale);
133 }
134
135 static void
136 wlsc_matrix_transform(struct wlsc_matrix *matrix, struct wlsc_vector *v)
137 {
138         int i, j;
139         struct wlsc_vector t;
140
141         for (i = 0; i < 4; i++) {
142                 t.f[i] = 0;
143                 for (j = 0; j < 4; j++)
144                         t.f[i] += v->f[j] * matrix->d[i + j * 4];
145         }
146
147         *v = t;
148 }
149
150 WL_EXPORT void
151 wlsc_spring_init(struct wlsc_spring *spring,
152                  double k, double current, double target)
153 {
154         spring->k = k;
155         spring->friction = 100.0;
156         spring->current = current;
157         spring->previous = current;
158         spring->target = target;
159 }
160
161 WL_EXPORT void
162 wlsc_spring_update(struct wlsc_spring *spring, uint32_t msec)
163 {
164         double force, v, current, step;
165
166         step = (msec - spring->timestamp) / 300.0;
167         spring->timestamp = msec;
168
169         current = spring->current;
170         v = current - spring->previous;
171         force = spring->k * (spring->target - current) / 10.0 +
172                 (spring->previous - current) - v * spring->friction;
173
174         spring->current =
175                 current + (current - spring->previous) + force * step * step;
176         spring->previous = current;
177
178 #if 0
179         if (spring->current >= 1.0) {
180 #ifdef TWEENER_BOUNCE
181                 spring->current = 2.0 - spring->current;
182                 spring->previous = 2.0 - spring->previous;
183 #else
184                 spring->current = 1.0;
185                 spring->previous = 1.0;
186 #endif
187         }
188
189         if (spring->current <= 0.0) {
190                 spring->current = 0.0;
191                 spring->previous = 0.0;
192         }
193 #endif
194 }
195
196 WL_EXPORT int
197 wlsc_spring_done(struct wlsc_spring *spring)
198 {
199         return fabs(spring->previous - spring->target) < 0.0002 &&
200                 fabs(spring->current - spring->target) < 0.0002;
201 }
202
203 static void
204 surface_handle_buffer_destroy(struct wl_listener *listener,
205                               struct wl_resource *resource, uint32_t time)
206 {
207         struct wlsc_surface *es = container_of(listener, struct wlsc_surface,
208                                                buffer_destroy_listener);
209         struct wl_buffer *buffer = (struct wl_buffer *) resource;
210
211         if (es->buffer == buffer)
212                 es->buffer = NULL;
213 }
214
215 static void
216 output_handle_scanout_buffer_destroy(struct wl_listener *listener,
217                                      struct wl_resource *resource,
218                                      uint32_t time)
219 {
220         struct wlsc_output *output =
221                 container_of(listener, struct wlsc_output,
222                              scanout_buffer_destroy_listener);
223         struct wl_buffer *buffer = (struct wl_buffer *) resource;
224
225         if (output->scanout_buffer == buffer)
226                 output->scanout_buffer = NULL;
227 }
228
229 WL_EXPORT struct wlsc_surface *
230 wlsc_surface_create(struct wlsc_compositor *compositor,
231                     int32_t x, int32_t y, int32_t width, int32_t height)
232 {
233         struct wlsc_surface *surface;
234
235         surface = malloc(sizeof *surface);
236         if (surface == NULL)
237                 return NULL;
238
239         wl_list_init(&surface->link);
240         wl_list_init(&surface->buffer_link);
241         surface->map_type = WLSC_SURFACE_MAP_UNMAPPED;
242
243         glGenTextures(1, &surface->texture);
244         glBindTexture(GL_TEXTURE_2D, surface->texture);
245         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
246         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
247
248         surface->surface.resource.client = NULL;
249
250         surface->compositor = compositor;
251         surface->visual = WLSC_NONE_VISUAL;
252         surface->image = EGL_NO_IMAGE_KHR;
253         surface->saved_texture = 0;
254         surface->x = x;
255         surface->y = y;
256         surface->width = width;
257         surface->height = height;
258
259         surface->buffer = NULL;
260         surface->output = NULL;
261
262         pixman_region32_init(&surface->damage);
263         pixman_region32_init(&surface->opaque);
264
265         surface->buffer_destroy_listener.func = surface_handle_buffer_destroy;
266         wl_list_init(&surface->buffer_destroy_listener.link);
267
268         surface->transform = NULL;
269
270         return surface;
271 }
272
273 WL_EXPORT void
274 wlsc_surface_damage_rectangle(struct wlsc_surface *surface,
275                               int32_t x, int32_t y,
276                               int32_t width, int32_t height)
277 {
278         struct wlsc_compositor *compositor = surface->compositor;
279
280         pixman_region32_union_rect(&surface->damage,
281                                    &surface->damage,
282                                    surface->x + x, surface->y + y,
283                                    width, height);
284         wlsc_compositor_schedule_repaint(compositor);
285 }
286
287 WL_EXPORT void
288 wlsc_surface_damage(struct wlsc_surface *surface)
289 {
290         wlsc_surface_damage_rectangle(surface, 0, 0,
291                                       surface->width, surface->height);
292 }
293
294 WL_EXPORT void
295 wlsc_surface_damage_below(struct wlsc_surface *surface)
296 {
297         struct wlsc_surface *below;
298
299         if (surface->link.next == &surface->compositor->surface_list)
300                 return;
301
302         below = container_of(surface->link.next, struct wlsc_surface, link);
303
304         pixman_region32_union_rect(&below->damage,
305                                    &below->damage,
306                                    surface->x, surface->y,
307                                    surface->width, surface->height);
308         wlsc_compositor_schedule_repaint(surface->compositor);
309 }
310
311 WL_EXPORT void
312 wlsc_surface_configure(struct wlsc_surface *surface,
313                        int x, int y, int width, int height)
314 {
315         wlsc_surface_damage_below(surface);
316
317         surface->x = x;
318         surface->y = y;
319         surface->width = width;
320         surface->height = height;
321
322         wlsc_surface_assign_output(surface);
323         wlsc_surface_damage(surface);
324
325         pixman_region32_fini(&surface->opaque);
326         if (surface->visual == WLSC_RGB_VISUAL)
327                 pixman_region32_init_rect(&surface->opaque,
328                                           surface->x, surface->y,
329                                           surface->width, surface->height);
330         else
331                 pixman_region32_init(&surface->opaque);
332 }
333
334 WL_EXPORT uint32_t
335 wlsc_compositor_get_time(void)
336 {
337         struct timeval tv;
338
339         gettimeofday(&tv, NULL);
340
341         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
342 }
343
344 static void
345 wlsc_compositor_repick(struct wlsc_compositor *compositor)
346 {
347         struct wlsc_input_device *device;
348         struct wlsc_surface *surface;
349         int32_t sx, sy;
350         uint32_t time;
351
352         time = wlsc_compositor_get_time();
353         wl_list_for_each(device, &compositor->input_device_list, link) {
354                 if (device->input_device.grab)
355                         continue;
356                 surface = pick_surface(&device->input_device, &sx, &sy);
357                 wl_input_device_set_pointer_focus(&device->input_device,
358                                                   &surface->surface,
359                                                   time,
360                                                   device->input_device.x,
361                                                   device->input_device.y,
362                                                   sx, sy);
363         }
364 }
365
366 static void
367 destroy_surface(struct wl_resource *resource)
368 {
369         struct wlsc_surface *surface =
370                 container_of(resource, struct wlsc_surface, surface.resource);
371         struct wlsc_compositor *compositor = surface->compositor;
372
373         wlsc_surface_damage_below(surface);
374
375         wl_list_remove(&surface->link);
376         wlsc_compositor_repick(compositor);
377
378         if (surface->saved_texture == 0)
379                 glDeleteTextures(1, &surface->texture);
380         else
381                 glDeleteTextures(1, &surface->saved_texture);
382
383         if (surface->buffer)
384                 wl_list_remove(&surface->buffer_destroy_listener.link);
385
386         if (surface->image != EGL_NO_IMAGE_KHR)
387                 compositor->destroy_image(compositor->display,
388                                           surface->image);
389
390         wl_list_remove(&surface->buffer_link);
391
392         free(surface);
393 }
394
395 static void
396 wlsc_buffer_attach(struct wl_buffer *buffer, struct wl_surface *surface)
397 {
398         struct wlsc_surface *es = (struct wlsc_surface *) surface;
399         struct wlsc_compositor *ec = es->compositor;
400         struct wl_list *surfaces_attached_to;
401
402         if (es->saved_texture != 0)
403                 es->texture = es->saved_texture;
404
405         glBindTexture(GL_TEXTURE_2D, es->texture);
406
407         if (wl_buffer_is_shm(buffer)) {
408                 /* Unbind any EGLImage texture that may be bound, so we don't
409                  * overwrite it.*/
410                 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
411                              0, 0, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
412                 es->pitch = wl_shm_buffer_get_stride(buffer) / 4;
413                 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
414                              es->pitch, buffer->height, 0,
415                              GL_BGRA_EXT, GL_UNSIGNED_BYTE,
416                              wl_shm_buffer_get_data(buffer));
417
418                 switch (wl_shm_buffer_get_format(buffer)) {
419                 case WL_SHM_FORMAT_ARGB32:
420                         es->visual = WLSC_ARGB_VISUAL;
421                         break;
422                 case WL_SHM_FORMAT_PREMULTIPLIED_ARGB32:
423                         es->visual = WLSC_PREMUL_ARGB_VISUAL;
424                         break;
425                 case WL_SHM_FORMAT_XRGB32:
426                         es->visual = WLSC_RGB_VISUAL;
427                         break;
428                 }
429
430                 surfaces_attached_to = buffer->user_data;
431
432                 wl_list_remove(&es->buffer_link);
433                 wl_list_insert(surfaces_attached_to, &es->buffer_link);
434         } else {
435                 if (es->image != EGL_NO_IMAGE_KHR)
436                         ec->destroy_image(ec->display, es->image);
437                 es->image = ec->create_image(ec->display, NULL,
438                                              EGL_WAYLAND_BUFFER_WL,
439                                              buffer, NULL);
440                 
441                 ec->image_target_texture_2d(GL_TEXTURE_2D, es->image);
442
443                 /* FIXME: we need to get the visual from the wl_buffer */
444                 es->visual = WLSC_PREMUL_ARGB_VISUAL;
445                 es->pitch = es->width;
446         }
447 }
448
449 static void
450 wlsc_sprite_attach(struct wlsc_sprite *sprite, struct wl_surface *surface)
451 {
452         struct wlsc_surface *es = (struct wlsc_surface *) surface;
453         struct wlsc_compositor *ec = es->compositor;
454
455         es->pitch = es->width;
456         es->image = sprite->image;
457         if (sprite->image != EGL_NO_IMAGE_KHR) {
458                 glBindTexture(GL_TEXTURE_2D, es->texture);
459                 ec->image_target_texture_2d(GL_TEXTURE_2D, es->image);
460         } else {
461                 if (es->saved_texture == 0)
462                         es->saved_texture = es->texture;
463                 es->texture = sprite->texture;
464         }
465
466         es->visual = sprite->visual;
467
468         if (es->buffer)
469                 es->buffer = NULL;
470 }
471
472 enum sprite_usage {
473         SPRITE_USE_CURSOR = (1 << 0),
474 };
475
476 static struct wlsc_sprite *
477 create_sprite_from_png(struct wlsc_compositor *ec,
478                        const char *filename, uint32_t usage)
479 {
480         uint32_t *pixels;
481         struct wlsc_sprite *sprite;
482         int32_t width, height;
483         uint32_t stride;
484
485         pixels = wlsc_load_image(filename, &width, &height, &stride);
486         if (pixels == NULL)
487                 return NULL;
488
489         sprite = malloc(sizeof *sprite);
490         if (sprite == NULL) {
491                 free(pixels);
492                 return NULL;
493         }
494
495         sprite->visual = WLSC_PREMUL_ARGB_VISUAL;
496         sprite->width = width;
497         sprite->height = height;
498         sprite->image = EGL_NO_IMAGE_KHR;
499
500         if (usage & SPRITE_USE_CURSOR && ec->create_cursor_image != NULL)
501                 sprite->image = ec->create_cursor_image(ec, width, height);
502
503         glGenTextures(1, &sprite->texture);
504         glBindTexture(GL_TEXTURE_2D, sprite->texture);
505         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
506         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
507         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
508         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
509
510         if (sprite->image != EGL_NO_IMAGE_KHR) {
511                 ec->image_target_texture_2d(GL_TEXTURE_2D, sprite->image);
512                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
513                                 GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
514         } else {
515                 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
516                              GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
517         }
518
519         free(pixels);
520
521         return sprite;
522 }
523
524 static const struct {
525         const char *filename;
526         int hotspot_x, hotspot_y;
527 } pointer_images[] = {
528         { DATADIR "/wayland/bottom_left_corner.png",     6, 30 },
529         { DATADIR "/wayland/bottom_right_corner.png",   28, 28 },
530         { DATADIR "/wayland/bottom_side.png",           16, 20 },
531         { DATADIR "/wayland/grabbing.png",              20, 17 },
532         { DATADIR "/wayland/left_ptr.png",              10,  5 },
533         { DATADIR "/wayland/left_side.png",             10, 20 },
534         { DATADIR "/wayland/right_side.png",            30, 19 },
535         { DATADIR "/wayland/top_left_corner.png",        8,  8 },
536         { DATADIR "/wayland/top_right_corner.png",      26,  8 },
537         { DATADIR "/wayland/top_side.png",              18,  8 },
538         { DATADIR "/wayland/xterm.png",                 15, 15 }
539 };
540
541 static void
542 create_pointer_images(struct wlsc_compositor *ec)
543 {
544         int i, count;
545
546         count = ARRAY_LENGTH(pointer_images);
547         ec->pointer_sprites = malloc(count * sizeof *ec->pointer_sprites);
548         for (i = 0; i < count; i++) {
549                 ec->pointer_sprites[i] =
550                         create_sprite_from_png(ec,
551                                                pointer_images[i].filename,
552                                                SPRITE_USE_CURSOR);
553         }
554 }
555
556 static int
557 texture_region(struct wlsc_surface *es, pixman_region32_t *region)
558 {
559         struct wlsc_compositor *ec = es->compositor;
560         GLfloat *v, inv_width, inv_height;
561         pixman_box32_t *rectangles;
562         unsigned int *p;
563         int i, n;
564
565         rectangles = pixman_region32_rectangles(region, &n);
566         v = wl_array_add(&ec->vertices, n * 16 * sizeof *v);
567         p = wl_array_add(&ec->indices, n * 6 * sizeof *p);
568         inv_width = 1.0 / es->pitch;
569         inv_height = 1.0 / es->height;
570
571         for (i = 0; i < n; i++, v += 16, p += 6) {
572                 v[ 0] = rectangles[i].x1;
573                 v[ 1] = rectangles[i].y1;
574                 v[ 2] = (GLfloat) (rectangles[i].x1 - es->x) * inv_width;
575                 v[ 3] = (GLfloat) (rectangles[i].y1 - es->y) * inv_height;
576
577                 v[ 4] = rectangles[i].x1;
578                 v[ 5] = rectangles[i].y2;
579                 v[ 6] = v[ 2];
580                 v[ 7] = (GLfloat) (rectangles[i].y2 - es->y) * inv_height;
581
582                 v[ 8] = rectangles[i].x2;
583                 v[ 9] = rectangles[i].y1;
584                 v[10] = (GLfloat) (rectangles[i].x2 - es->x) * inv_width;
585                 v[11] = v[ 3];
586
587                 v[12] = rectangles[i].x2;
588                 v[13] = rectangles[i].y2;
589                 v[14] = v[10];
590                 v[15] = v[ 7];
591
592                 p[0] = i * 4 + 0;
593                 p[1] = i * 4 + 1;
594                 p[2] = i * 4 + 2;
595                 p[3] = i * 4 + 2;
596                 p[4] = i * 4 + 1;
597                 p[5] = i * 4 + 3;
598         }
599
600         return n;
601 }
602
603 static void
604 transform_vertex(struct wlsc_surface *surface,
605                  GLfloat x, GLfloat y, GLfloat u, GLfloat v, GLfloat *r)
606 {
607         struct wlsc_vector t;
608
609         t.f[0] = x;
610         t.f[1] = y;
611         t.f[2] = 0.0;
612         t.f[3] = 1.0;
613
614         wlsc_matrix_transform(&surface->transform->matrix, &t);
615
616         r[ 0] = t.f[0];
617         r[ 1] = t.f[1];
618         r[ 2] = u;
619         r[ 3] = v;
620 }
621
622 static int
623 texture_transformed_surface(struct wlsc_surface *es)
624 {
625         struct wlsc_compositor *ec = es->compositor;
626         GLfloat *v;
627         unsigned int *p;
628
629         v = wl_array_add(&ec->vertices, 16 * sizeof *v);
630         p = wl_array_add(&ec->indices, 6 * sizeof *p);
631
632         transform_vertex(es, es->x, es->y, 0.0, 0.0, &v[0]);
633         transform_vertex(es, es->x, es->y + es->height, 0.0, 1.0, &v[4]);
634         transform_vertex(es, es->x + es->width, es->y, 1.0, 0.0, &v[8]);
635         transform_vertex(es, es->x + es->width, es->y + es->height,
636                          1.0, 1.0, &v[12]);
637
638         p[0] = 0;
639         p[1] = 1;
640         p[2] = 2;
641         p[3] = 2;
642         p[4] = 1;
643         p[5] = 3;
644
645         return 1;
646 }
647
648 static void
649 wlsc_surface_draw(struct wlsc_surface *es,
650                   struct wlsc_output *output, pixman_region32_t *clip)
651 {
652         struct wlsc_compositor *ec = es->compositor;
653         GLfloat *v;
654         pixman_region32_t repaint;
655         GLint filter;
656         int n;
657
658         pixman_region32_init_rect(&repaint,
659                                   es->x, es->y, es->width, es->height);
660         pixman_region32_intersect(&repaint, &repaint, clip);
661         if (!pixman_region32_not_empty(&repaint))
662                 return;
663
664         switch (es->visual) {
665         case WLSC_ARGB_VISUAL:
666                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
667                 glEnable(GL_BLEND);
668                 break;
669         case WLSC_PREMUL_ARGB_VISUAL:
670                 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
671                 glEnable(GL_BLEND);
672                 break;
673         case WLSC_RGB_VISUAL:
674                 glDisable(GL_BLEND);
675                 break;
676         default:
677                 fprintf(stderr, "bogus visual\n");
678                 break;
679         }
680
681         if (es->transform == NULL) {
682                 filter = GL_NEAREST;
683                 n = texture_region(es, &repaint);
684         } else {
685                 filter = GL_LINEAR;
686                 n = texture_transformed_surface(es);
687         }
688
689         glBindTexture(GL_TEXTURE_2D, es->texture);
690         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
691         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
692
693         v = ec->vertices.data;
694         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
695         glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
696         glEnableVertexAttribArray(0);
697         glEnableVertexAttribArray(1);
698         glDrawElements(GL_TRIANGLES, n * 6, GL_UNSIGNED_INT, ec->indices.data);
699
700         ec->vertices.size = 0;
701         ec->indices.size = 0;
702         pixman_region32_fini(&repaint);
703 }
704
705 static void
706 wlsc_surface_raise(struct wlsc_surface *surface)
707 {
708         struct wlsc_compositor *compositor = surface->compositor;
709
710         wl_list_remove(&surface->link);
711         wl_list_insert(&compositor->surface_list, &surface->link);
712         wlsc_compositor_repick(compositor);
713         wlsc_surface_damage(surface);
714 }
715
716 WL_EXPORT void
717 wlsc_compositor_damage_all(struct wlsc_compositor *compositor)
718 {
719         struct wlsc_output *output;
720
721         wl_list_for_each(output, &compositor->output_list, link)
722                 wlsc_output_damage(output);
723 }
724
725 static inline void
726 wlsc_buffer_post_release(struct wl_buffer *buffer)
727 {
728         if (buffer == NULL || --buffer->busy_count > 0)
729                 return;
730
731         assert(buffer->resource.client != NULL);
732         wl_resource_post_event(&buffer->resource, WL_BUFFER_RELEASE);
733 }
734
735 WL_EXPORT void
736 wlsc_output_damage(struct wlsc_output *output)
737 {
738         struct wlsc_compositor *compositor = output->compositor;
739
740         pixman_region32_union(&compositor->damage,
741                               &compositor->damage, &output->region);
742         wlsc_compositor_schedule_repaint(compositor);
743 }
744
745 static void
746 fade_frame(struct wlsc_animation *animation,
747            struct wlsc_output *output, uint32_t msecs)
748 {
749         struct wlsc_compositor *compositor =
750                 container_of(animation,
751                              struct wlsc_compositor, fade.animation);
752
753         wlsc_spring_update(&compositor->fade.spring, msecs);
754         if (wlsc_spring_done(&compositor->fade.spring)) {
755                 if (compositor->fade.spring.current > 0.999) {
756                         compositor->state = WLSC_COMPOSITOR_SLEEPING;
757                         compositor->shell->lock(compositor->shell);
758                 }
759                 compositor->fade.spring.current =
760                         compositor->fade.spring.target;
761                 wl_list_remove(&animation->link);
762                 wl_list_init(&animation->link);
763         }
764
765         wlsc_output_damage(output);
766 }
767
768 static void
769 fade_output(struct wlsc_output *output,
770             GLfloat tint, pixman_region32_t *region)
771 {
772         struct wlsc_compositor *compositor = output->compositor;
773         struct wlsc_surface surface;
774         GLfloat color[4] = { 0.0, 0.0, 0.0, tint };
775
776         surface.compositor = compositor;
777         surface.x = output->x;
778         surface.y = output->y;
779         surface.pitch = output->current->width;
780         surface.width = output->current->width;
781         surface.height = output->current->height;
782         surface.texture = GL_NONE;
783         surface.transform = NULL;
784
785         if (tint <= 1.0)
786                 surface.visual = WLSC_PREMUL_ARGB_VISUAL;
787         else
788                 surface.visual = WLSC_RGB_VISUAL;
789
790         glUseProgram(compositor->solid_shader.program);
791         glUniformMatrix4fv(compositor->solid_shader.proj_uniform,
792                            1, GL_FALSE, output->matrix.d);
793         glUniform4fv(compositor->solid_shader.color_uniform, 1, color);
794         wlsc_surface_draw(&surface, output, region);
795 }
796
797 static void
798 wlsc_output_set_cursor(struct wlsc_output *output,
799                        struct wl_input_device *dev, int force_sw)
800 {
801         struct wlsc_compositor *ec = output->compositor;
802         struct wlsc_input_device *device = (struct wlsc_input_device *) dev;
803         pixman_region32_t cursor_region;
804         int use_hardware_cursor = 1, prior_was_hardware;
805
806         pixman_region32_init_rect(&cursor_region,
807                                   device->sprite->x, device->sprite->y,
808                                   device->sprite->width,
809                                   device->sprite->height);
810
811         pixman_region32_intersect(&cursor_region, &cursor_region, &output->region);
812
813         if (!pixman_region32_not_empty(&cursor_region)) {
814                 output->set_hardware_cursor(output, NULL);
815                 goto out;
816         }
817
818         prior_was_hardware = wl_list_empty(&device->sprite->link);
819         if (force_sw || output->set_hardware_cursor(output, device) < 0) {
820                 if (prior_was_hardware) {
821                         wlsc_surface_damage(device->sprite);
822                         output->set_hardware_cursor(output, NULL);
823                 }
824                 use_hardware_cursor = 0;
825         } else if (!prior_was_hardware) {
826                 wlsc_surface_damage_below(device->sprite);
827         }
828
829         /* Remove always to be on top. */
830         wl_list_remove(&device->sprite->link);
831         if (!use_hardware_cursor && ec->focus)
832                 wl_list_insert(&ec->surface_list, &device->sprite->link);
833         else
834                 wl_list_init(&device->sprite->link);
835
836 out:
837         pixman_region32_fini(&cursor_region);
838 }
839
840 static void
841 wlsc_output_repaint(struct wlsc_output *output)
842 {
843         struct wlsc_compositor *ec = output->compositor;
844         struct wlsc_surface *es;
845         pixman_region32_t opaque, new_damage, total_damage, repaint;
846
847         output->prepare_render(output);
848
849         glViewport(0, 0, output->current->width, output->current->height);
850
851         glUseProgram(ec->texture_shader.program);
852         glUniformMatrix4fv(ec->texture_shader.proj_uniform,
853                            1, GL_FALSE, output->matrix.d);
854         glUniform1i(ec->texture_shader.tex_uniform, 0);
855
856         wlsc_output_set_cursor(output, ec->input_device,
857                                ec->fade.spring.current >= 0.001);
858
859         pixman_region32_init(&new_damage);
860         pixman_region32_copy(&new_damage, &ec->damage);
861         pixman_region32_init(&opaque);
862                                 
863         wl_list_for_each(es, &ec->surface_list, link) {
864                 pixman_region32_subtract(&es->damage, &es->damage, &opaque);
865                 pixman_region32_union(&new_damage, &new_damage, &es->damage);
866                 pixman_region32_union(&opaque, &opaque, &es->opaque);
867         }
868
869         pixman_region32_subtract(&ec->damage, &ec->damage, &output->region);
870
871         pixman_region32_init(&total_damage);
872         pixman_region32_union(&total_damage, &new_damage,
873                               &output->previous_damage);
874         pixman_region32_intersect(&output->previous_damage,
875                                   &new_damage, &output->region);
876
877         pixman_region32_fini(&opaque);
878         pixman_region32_fini(&new_damage);
879
880         es = container_of(ec->surface_list.next, struct wlsc_surface, link);
881
882         if (es->visual == WLSC_RGB_VISUAL &&
883             output->prepare_scanout_surface(output, es) == 0) {
884                 /* We're drawing nothing now,
885                  * draw the damaged regions later. */
886                 pixman_region32_union(&ec->damage, &ec->damage, &total_damage);
887
888                 output->scanout_buffer = es->buffer;
889                 output->scanout_buffer->busy_count++;
890
891                 wl_list_remove(&output->scanout_buffer_destroy_listener.link);
892                 wl_list_insert(output->scanout_buffer->resource.destroy_listener_list.prev,
893                                &output->scanout_buffer_destroy_listener.link);
894
895                 return;
896         }
897
898         if (es->fullscreen_output == output) {
899                 if (es->width < output->current->width ||
900                     es->height < output->current->height)
901                         glClear(GL_COLOR_BUFFER_BIT);
902                 wlsc_surface_draw(es, output, &total_damage);
903         } else {
904                 wl_list_for_each(es, &ec->surface_list, link) {
905                         pixman_region32_copy(&es->damage, &total_damage);
906                         pixman_region32_subtract(&total_damage, &total_damage, &es->opaque);
907                 }
908
909                 wl_list_for_each_reverse(es, &ec->surface_list, link) {
910                         pixman_region32_init(&repaint);
911                         pixman_region32_intersect(&repaint, &output->region,
912                                                   &es->damage);
913                         wlsc_surface_draw(es, output, &repaint);
914                         pixman_region32_subtract(&es->damage,
915                                                  &es->damage, &output->region);
916                 }
917         }
918
919         if (ec->fade.spring.current > 0.001)
920                 fade_output(output, ec->fade.spring.current, &total_damage);
921 }
922
923 struct wlsc_frame_callback {
924         struct wl_resource resource;
925         struct wl_list link;
926 };
927
928 static void
929 repaint(void *data, int msecs)
930 {
931         struct wlsc_output *output = data;
932         struct wlsc_compositor *compositor = output->compositor;
933         struct wlsc_animation *animation, *next;
934         struct wlsc_frame_callback *cb, *cnext;
935
936         wlsc_output_repaint(output);
937         output->repaint_needed = 0;
938         output->repaint_scheduled = 1;
939         output->present(output);
940
941         wl_list_for_each_safe(cb, cnext, &output->frame_callback_list, link) {
942                 wl_resource_post_event(&cb->resource, WL_CALLBACK_DONE, msecs);
943                 wl_resource_destroy(&cb->resource, 0);
944         }
945
946         wl_list_for_each_safe(animation, next,
947                               &compositor->animation_list, link)
948                 animation->frame(animation, output, msecs);
949 }
950
951 static void
952 idle_repaint(void *data)
953 {
954         repaint(data, wlsc_compositor_get_time());
955 }
956
957 WL_EXPORT void
958 wlsc_output_finish_frame(struct wlsc_output *output, int msecs)
959 {
960         wlsc_buffer_post_release(output->scanout_buffer);
961         output->scanout_buffer = NULL;
962         output->repaint_scheduled = 0;
963
964         if (output->repaint_needed)
965                 repaint(output, msecs);
966 }
967
968 WL_EXPORT void
969 wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor)
970 {
971         struct wlsc_output *output;
972         struct wl_event_loop *loop;
973
974         if (compositor->state == WLSC_COMPOSITOR_SLEEPING)
975                 return;
976
977         loop = wl_display_get_event_loop(compositor->wl_display);
978         wl_list_for_each(output, &compositor->output_list, link) {
979                 output->repaint_needed = 1;
980                 if (output->repaint_scheduled)
981                         continue;
982
983                 wl_event_loop_add_idle(loop, idle_repaint, output);
984                 output->repaint_scheduled = 1;
985         }
986 }
987
988 WL_EXPORT void
989 wlsc_compositor_fade(struct wlsc_compositor *compositor, float tint)
990 {
991         int done;
992
993         done = wlsc_spring_done(&compositor->fade.spring);
994         compositor->fade.spring.target = tint;
995         if (wlsc_spring_done(&compositor->fade.spring))
996                 return;
997
998         if (done)
999                 compositor->fade.spring.timestamp =
1000                         wlsc_compositor_get_time();
1001
1002         wlsc_compositor_damage_all(compositor);
1003         if (wl_list_empty(&compositor->fade.animation.link))
1004                 wl_list_insert(compositor->animation_list.prev,
1005                                &compositor->fade.animation.link);
1006 }
1007
1008 static void
1009 surface_destroy(struct wl_client *client, struct wl_resource *resource)
1010 {
1011         wl_resource_destroy(resource, wlsc_compositor_get_time());
1012 }
1013
1014 WL_EXPORT void
1015 wlsc_surface_assign_output(struct wlsc_surface *es)
1016 {
1017         struct wlsc_compositor *ec = es->compositor;
1018         struct wlsc_output *output;
1019         pixman_region32_t region;
1020         uint32_t max, area;
1021         pixman_box32_t *e;
1022
1023         max = 0;
1024         wl_list_for_each(output, &ec->output_list, link) {
1025                 pixman_region32_init_rect(&region,
1026                                           es->x, es->y, es->width, es->height);
1027                 pixman_region32_intersect(&region, &region, &output->region);
1028
1029                 e = pixman_region32_extents(&region);
1030                 area = (e->x2 - e->x1) * (e->y2 - e->y1);
1031
1032                 if (area >= max) {
1033                         es->output = output;
1034                         max = area;
1035                 }
1036         }
1037 }
1038
1039 static void
1040 surface_attach(struct wl_client *client,
1041                struct wl_resource *resource,
1042                struct wl_resource *buffer_resource, int32_t x, int32_t y)
1043 {
1044         struct wlsc_surface *es = resource->data;
1045         struct wl_buffer *buffer = buffer_resource->data;
1046         int repick = 0;
1047
1048         buffer->busy_count++;
1049         wlsc_buffer_post_release(es->buffer);
1050
1051         es->buffer = buffer;
1052         wl_list_remove(&es->buffer_destroy_listener.link);
1053         wl_list_insert(es->buffer->resource.destroy_listener_list.prev,
1054                        &es->buffer_destroy_listener.link);
1055
1056         if (es->visual == WLSC_NONE_VISUAL) {
1057                 wl_list_insert(&es->compositor->surface_list, &es->link);
1058                 repick = 1;
1059         }
1060
1061         if (x != 0 || y != 0 ||
1062             es->width != buffer->width || es->height != buffer->height) {
1063                 wlsc_surface_configure(es, es->x + x, es->y + y,
1064                                        buffer->width, buffer->height);
1065                 repick = 1;
1066         }
1067
1068         wlsc_buffer_attach(buffer, &es->surface);
1069
1070         es->compositor->shell->attach(es->compositor->shell, es);
1071
1072         if (repick)
1073                 wlsc_compositor_repick(es->compositor);
1074 }
1075
1076 static void
1077 surface_damage(struct wl_client *client,
1078                struct wl_resource *resource,
1079                int32_t x, int32_t y, int32_t width, int32_t height)
1080 {
1081         struct wlsc_surface *es = resource->data;
1082
1083         wlsc_surface_damage_rectangle(es, x, y, width, height);
1084 }
1085
1086 static void
1087 destroy_frame_callback(struct wl_resource *resource)
1088 {
1089         struct wlsc_frame_callback *cb = resource->data;
1090
1091         wl_list_remove(&cb->link);
1092         free(resource);
1093 }
1094
1095 static void
1096 surface_frame(struct wl_client *client,
1097               struct wl_resource *resource, uint32_t callback)
1098 {
1099         struct wlsc_frame_callback *cb;
1100         struct wlsc_surface *es = resource->data;
1101
1102         cb = malloc(sizeof *cb);
1103         if (cb == NULL) {
1104                 wl_resource_post_no_memory(resource);
1105                 return;
1106         }
1107                 
1108         cb->resource.object.interface = &wl_callback_interface;
1109         cb->resource.object.id = callback;
1110         cb->resource.destroy = destroy_frame_callback;
1111         cb->resource.client = client;
1112         cb->resource.data = cb;
1113
1114         wl_client_add_resource(client, &cb->resource);
1115
1116         if (es->output) {
1117                 wl_list_insert(es->output->frame_callback_list.prev,
1118                                &cb->link);
1119         } else {
1120                 wl_list_init(&cb->link);
1121                 wl_resource_destroy(&cb->resource, 0);
1122         }
1123 }
1124
1125 const static struct wl_surface_interface surface_interface = {
1126         surface_destroy,
1127         surface_attach,
1128         surface_damage,
1129         surface_frame
1130 };
1131
1132 static void
1133 wlsc_input_device_attach(struct wlsc_input_device *device,
1134                          int x, int y, int width, int height)
1135 {
1136         wlsc_surface_damage_below(device->sprite);
1137
1138         device->hotspot_x = x;
1139         device->hotspot_y = y;
1140
1141         device->sprite->x = device->input_device.x - device->hotspot_x;
1142         device->sprite->y = device->input_device.y - device->hotspot_y;
1143         device->sprite->width = width;
1144         device->sprite->height = height;
1145
1146         wlsc_surface_damage(device->sprite);
1147 }
1148
1149 static void
1150 wlsc_input_device_attach_buffer(struct wlsc_input_device *device,
1151                                 struct wl_buffer *buffer, int x, int y)
1152 {
1153         wlsc_buffer_attach(buffer, &device->sprite->surface);
1154         wlsc_input_device_attach(device, x, y, buffer->width, buffer->height);
1155 }
1156
1157 static void
1158 wlsc_input_device_attach_sprite(struct wlsc_input_device *device,
1159                                 struct wlsc_sprite *sprite, int x, int y)
1160 {
1161         wlsc_sprite_attach(sprite, &device->sprite->surface);
1162         wlsc_input_device_attach(device, x, y, sprite->width, sprite->height);
1163 }
1164
1165 WL_EXPORT void
1166 wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
1167                                     enum wlsc_pointer_type type)
1168 {
1169         struct wlsc_compositor *compositor =
1170                 (struct wlsc_compositor *) device->input_device.compositor;
1171
1172         wlsc_input_device_attach_sprite(device,
1173                                         compositor->pointer_sprites[type],
1174                                         pointer_images[type].hotspot_x,
1175                                         pointer_images[type].hotspot_y);
1176 }
1177
1178 static void
1179 compositor_create_surface(struct wl_client *client,
1180                           struct wl_resource *resource, uint32_t id)
1181 {
1182         struct wlsc_compositor *ec = resource->data;
1183         struct wlsc_surface *surface;
1184
1185         surface = wlsc_surface_create(ec, 0, 0, 0, 0);
1186         if (surface == NULL) {
1187                 wl_resource_post_no_memory(resource);
1188                 return;
1189         }
1190
1191         surface->surface.resource.destroy = destroy_surface;
1192
1193         surface->surface.resource.object.id = id;
1194         surface->surface.resource.object.interface = &wl_surface_interface;
1195         surface->surface.resource.object.implementation =
1196                 (void (**)(void)) &surface_interface;
1197         surface->surface.resource.data = surface;
1198
1199         wl_client_add_resource(client, &surface->surface.resource);
1200 }
1201
1202 const static struct wl_compositor_interface compositor_interface = {
1203         compositor_create_surface,
1204 };
1205
1206 static void
1207 wlsc_surface_transform(struct wlsc_surface *surface,
1208                        int32_t x, int32_t y, int32_t *sx, int32_t *sy)
1209 {
1210         *sx = x - surface->x;
1211         *sy = y - surface->y;
1212 }
1213
1214 WL_EXPORT struct wlsc_surface *
1215 pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy)
1216 {
1217         struct wlsc_compositor *ec =
1218                 (struct wlsc_compositor *) device->compositor;
1219         struct wlsc_surface *es;
1220
1221         wl_list_for_each(es, &ec->surface_list, link) {
1222                 if (es->surface.resource.client == NULL)
1223                         continue;
1224                 wlsc_surface_transform(es, device->x, device->y, sx, sy);
1225                 if (0 <= *sx && *sx < es->width &&
1226                     0 <= *sy && *sy < es->height)
1227                         return es;
1228         }
1229
1230         return NULL;
1231 }
1232
1233
1234 static void
1235 implicit_grab_motion(struct wl_grab *grab,
1236                      uint32_t time, int32_t x, int32_t y)
1237 {
1238         struct wlsc_input_device *device =
1239                 (struct wlsc_input_device *) grab->input_device;
1240         struct wlsc_surface *es =
1241                 (struct wlsc_surface *) device->input_device.pointer_focus;
1242         int32_t sx, sy;
1243         struct wl_resource *resource;
1244
1245         resource = grab->input_device->pointer_focus_resource;
1246         if (resource) {
1247                 wlsc_surface_transform(es, x, y, &sx, &sy);
1248                 wl_resource_post_event(resource, WL_INPUT_DEVICE_MOTION,
1249                                        time, x, y, sx, sy);
1250         }
1251 }
1252
1253 static void
1254 implicit_grab_button(struct wl_grab *grab,
1255                      uint32_t time, int32_t button, int32_t state)
1256 {
1257         struct wl_resource *resource;
1258
1259         resource = grab->input_device->pointer_focus_resource;
1260         if (resource)
1261                 wl_resource_post_event(resource, WL_INPUT_DEVICE_BUTTON,
1262                                        time, button, state);
1263 }
1264
1265 static void
1266 implicit_grab_end(struct wl_grab *grab, uint32_t time)
1267 {
1268 }
1269
1270 static const struct wl_grab_interface implicit_grab_interface = {
1271         implicit_grab_motion,
1272         implicit_grab_button,
1273         implicit_grab_end
1274 };
1275
1276 WL_EXPORT void
1277 wlsc_compositor_wake(struct wlsc_compositor *compositor)
1278 {
1279         if (compositor->idle_inhibit)
1280                 return;
1281
1282         wlsc_compositor_fade(compositor, 0.0);
1283         compositor->state = WLSC_COMPOSITOR_ACTIVE;
1284
1285         wl_event_source_timer_update(compositor->idle_source,
1286                                      option_idle_time * 1000);
1287 }
1288
1289 static void
1290 wlsc_compositor_idle_inhibit(struct wlsc_compositor *compositor)
1291 {
1292         wlsc_compositor_wake(compositor);
1293         compositor->idle_inhibit++;
1294 }
1295
1296 static void
1297 wlsc_compositor_idle_release(struct wlsc_compositor *compositor)
1298 {
1299         compositor->idle_inhibit--;
1300         wlsc_compositor_wake(compositor);
1301 }
1302
1303 static int
1304 idle_handler(void *data)
1305 {
1306         struct wlsc_compositor *compositor = data;
1307
1308         if (compositor->idle_inhibit)
1309                 return 1;
1310
1311         wlsc_compositor_fade(compositor, 1.0);
1312
1313         return 1;
1314 }
1315
1316 WL_EXPORT void
1317 notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
1318 {
1319         struct wlsc_surface *es;
1320         struct wlsc_compositor *ec =
1321                 (struct wlsc_compositor *) device->compositor;
1322         struct wlsc_output *output;
1323         const struct wl_grab_interface *interface;
1324         struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
1325         int32_t sx, sy;
1326         int x_valid = 0, y_valid = 0;
1327         int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN;
1328
1329         wlsc_compositor_wake(ec);
1330
1331         wl_list_for_each(output, &ec->output_list, link) {
1332                 if (output->x <= x && x <= output->x + output->current->width)
1333                         x_valid = 1;
1334
1335                 if (output->y <= y && y <= output->y + output->current->height)
1336                         y_valid = 1;
1337
1338                 /* FIXME: calculate this only on output addition/deletion */
1339                 if (output->x < min_x)
1340                         min_x = output->x;
1341                 if (output->y < min_y)
1342                         min_y = output->y;
1343
1344                 if (output->x + output->current->width > max_x)
1345                         max_x = output->x + output->current->width;
1346                 if (output->y + output->current->height > max_y)
1347                         max_y = output->y + output->current->height;
1348         }
1349         
1350         if (!x_valid) {
1351                 if (x < min_x)
1352                         x = min_x;
1353                 else if (x >= max_x)
1354                         x = max_x;
1355         }
1356         if (!y_valid) {
1357                 if (y < min_y)
1358                         y = min_y;
1359                 else  if (y >= max_y)
1360                         y = max_y;
1361         }
1362
1363         device->x = x;
1364         device->y = y;
1365
1366         if (device->grab) {
1367                 interface = device->grab->interface;
1368                 interface->motion(device->grab, time, x, y);
1369         } else {
1370                 es = pick_surface(device, &sx, &sy);
1371                 wl_input_device_set_pointer_focus(device,
1372                                                   &es->surface,
1373                                                   time, x, y, sx, sy);
1374                 if (device->pointer_focus_resource)
1375                         wl_resource_post_event(device->pointer_focus_resource,
1376                                                WL_INPUT_DEVICE_MOTION,
1377                                                time, x, y, sx, sy);
1378         }
1379
1380         wlsc_surface_damage_below(wd->sprite);
1381
1382         wd->sprite->x = device->x - wd->hotspot_x;
1383         wd->sprite->y = device->y - wd->hotspot_y;
1384
1385         wlsc_surface_damage(wd->sprite);
1386 }
1387
1388 WL_EXPORT void
1389 wlsc_surface_activate(struct wlsc_surface *surface,
1390                       struct wlsc_input_device *device, uint32_t time)
1391 {
1392         struct wlsc_shell *shell = surface->compositor->shell;
1393
1394         wlsc_surface_raise(surface);
1395         if (device->selection)
1396                 shell->set_selection_focus(shell,
1397                                            device->selection,
1398                                            &surface->surface, time);
1399
1400         wl_input_device_set_keyboard_focus(&device->input_device,
1401                                            &surface->surface,
1402                                            time);
1403 }
1404
1405 struct wlsc_binding {
1406         uint32_t key;
1407         uint32_t button;
1408         uint32_t modifier;
1409         wlsc_binding_handler_t handler;
1410         void *data;
1411         struct wl_list link;
1412 };
1413
1414 WL_EXPORT void
1415 notify_button(struct wl_input_device *device,
1416               uint32_t time, int32_t button, int32_t state)
1417 {
1418         struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
1419         struct wlsc_compositor *compositor =
1420                 (struct wlsc_compositor *) device->compositor;
1421         struct wlsc_binding *b;
1422         struct wlsc_surface *surface =
1423                 (struct wlsc_surface *) device->pointer_focus;
1424         int32_t sx, sy;
1425
1426         if (state)
1427                 wlsc_compositor_idle_inhibit(compositor);
1428         else
1429                 wlsc_compositor_idle_release(compositor);
1430
1431         if (state && surface && device->grab == NULL) {
1432                 compositor->shell->activate(compositor->shell,
1433                                             surface, wd, time);
1434                 wl_input_device_start_grab(device,
1435                                            &device->implicit_grab,
1436                                            button, time);
1437         }
1438
1439         wl_list_for_each(b, &compositor->binding_list, link) {
1440                 if (b->button == button &&
1441                     b->modifier == wd->modifier_state && state) {
1442                         b->handler(&wd->input_device,
1443                                    time, 0, button, state, b->data);
1444                         break;
1445                 }
1446         }
1447
1448         if (device->grab)
1449                 device->grab->interface->button(device->grab, time,
1450                                                 button, state);
1451
1452         if (!state && device->grab && device->grab_button == button) {
1453                 wl_input_device_end_grab(device, time);
1454                 surface = pick_surface(device, &sx, &sy);
1455                 wl_input_device_set_pointer_focus(device, &surface->surface,
1456                                                   time, device->x, device->y,
1457                                                   sx, sy);
1458         }
1459 }
1460
1461 static void
1462 terminate_binding(struct wl_input_device *device, uint32_t time,
1463                   uint32_t key, uint32_t button, uint32_t state, void *data)
1464 {
1465         struct wlsc_compositor *compositor = data;
1466
1467         if (state)
1468                 wl_display_terminate(compositor->wl_display);
1469 }
1470
1471 WL_EXPORT struct wlsc_binding *
1472 wlsc_compositor_add_binding(struct wlsc_compositor *compositor,
1473                             uint32_t key, uint32_t button, uint32_t modifier,
1474                             wlsc_binding_handler_t handler, void *data)
1475 {
1476         struct wlsc_binding *binding;
1477
1478         binding = malloc(sizeof *binding);
1479         if (binding == NULL)
1480                 return NULL;
1481
1482         binding->key = key;
1483         binding->button = button;
1484         binding->modifier = modifier;
1485         binding->handler = handler;
1486         binding->data = data;
1487         wl_list_insert(compositor->binding_list.prev, &binding->link);
1488
1489         return binding;
1490 }
1491
1492 WL_EXPORT void
1493 wlsc_binding_destroy(struct wlsc_binding *binding)
1494 {
1495         wl_list_remove(&binding->link);
1496         free(binding);
1497 }
1498
1499 static void
1500 update_modifier_state(struct wlsc_input_device *device,
1501                       uint32_t key, uint32_t state)
1502 {
1503         uint32_t modifier;
1504
1505         switch (key) {
1506         case KEY_LEFTCTRL:
1507         case KEY_RIGHTCTRL:
1508                 modifier = MODIFIER_CTRL;
1509                 break;
1510
1511         case KEY_LEFTALT:
1512         case KEY_RIGHTALT:
1513                 modifier = MODIFIER_ALT;
1514                 break;
1515
1516         case KEY_LEFTMETA:
1517         case KEY_RIGHTMETA:
1518                 modifier = MODIFIER_SUPER;
1519                 break;
1520
1521         default:
1522                 modifier = 0;
1523                 break;
1524         }
1525
1526         if (state)
1527                 device->modifier_state |= modifier;
1528         else
1529                 device->modifier_state &= ~modifier;
1530 }
1531
1532 WL_EXPORT void
1533 notify_key(struct wl_input_device *device,
1534            uint32_t time, uint32_t key, uint32_t state)
1535 {
1536         struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
1537         struct wlsc_compositor *compositor =
1538                 (struct wlsc_compositor *) device->compositor;
1539         uint32_t *k, *end;
1540         struct wlsc_binding *b;
1541
1542         if (state)
1543                 wlsc_compositor_idle_inhibit(compositor);
1544         else
1545                 wlsc_compositor_idle_release(compositor);
1546
1547         wl_list_for_each(b, &compositor->binding_list, link) {
1548                 if (b->key == key &&
1549                     b->modifier == wd->modifier_state) {
1550                         b->handler(&wd->input_device,
1551                                    time, key, 0, state, b->data);
1552                         break;
1553                 }
1554         }
1555
1556         update_modifier_state(wd, key, state);
1557         end = device->keys.data + device->keys.size;
1558         for (k = device->keys.data; k < end; k++) {
1559                 if (*k == key)
1560                         *k = *--end;
1561         }
1562         device->keys.size = (void *) end - device->keys.data;
1563         if (state) {
1564                 k = wl_array_add(&device->keys, sizeof *k);
1565                 *k = key;
1566         }
1567
1568         if (device->keyboard_focus_resource)
1569                 wl_resource_post_event(device->keyboard_focus_resource,
1570                                        WL_INPUT_DEVICE_KEY, time, key, state);
1571 }
1572
1573 WL_EXPORT void
1574 notify_pointer_focus(struct wl_input_device *device,
1575                      uint32_t time, struct wlsc_output *output,
1576                      int32_t x, int32_t y)
1577 {
1578         struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
1579         struct wlsc_compositor *compositor =
1580                 (struct wlsc_compositor *) device->compositor;
1581         struct wlsc_surface *es;
1582         int32_t sx, sy;
1583
1584         if (output) {
1585                 device->x = x;
1586                 device->y = y;
1587                 es = pick_surface(device, &sx, &sy);
1588                 wl_input_device_set_pointer_focus(device,
1589                                                   &es->surface,
1590                                                   time, x, y, sx, sy);
1591
1592                 compositor->focus = 1;
1593
1594                 wd->sprite->x = device->x - wd->hotspot_x;
1595                 wd->sprite->y = device->y - wd->hotspot_y;
1596         } else {
1597                 wl_input_device_set_pointer_focus(device, NULL,
1598                                                   time, 0, 0, 0, 0);
1599                 compositor->focus = 0;
1600         }
1601
1602         wlsc_surface_damage(wd->sprite);
1603 }
1604
1605 WL_EXPORT void
1606 notify_keyboard_focus(struct wl_input_device *device,
1607                       uint32_t time, struct wlsc_output *output,
1608                       struct wl_array *keys)
1609 {
1610         struct wlsc_input_device *wd =
1611                 (struct wlsc_input_device *) device;
1612         struct wlsc_compositor *compositor =
1613                 (struct wlsc_compositor *) device->compositor;
1614         struct wlsc_surface *es;
1615         uint32_t *k, *end;
1616
1617         if (!wl_list_empty(&compositor->surface_list))
1618                 es = container_of(compositor->surface_list.next,
1619                                   struct wlsc_surface, link);
1620         else
1621                 es = NULL;
1622
1623         if (output) {
1624                 wl_array_copy(&wd->input_device.keys, keys);
1625                 wd->modifier_state = 0;
1626                 end = device->keys.data + device->keys.size;
1627                 for (k = device->keys.data; k < end; k++) {
1628                         wlsc_compositor_idle_inhibit(compositor);
1629                         update_modifier_state(wd, *k, 1);
1630                 }
1631
1632                 if (es && es->surface.resource.client)
1633                         wl_input_device_set_keyboard_focus(&wd->input_device,
1634                                                            &es->surface, time);
1635         } else {
1636                 end = device->keys.data + device->keys.size;
1637                 for (k = device->keys.data; k < end; k++)
1638                         wlsc_compositor_idle_release(compositor);
1639
1640                 wd->modifier_state = 0;
1641                 wl_input_device_set_keyboard_focus(&wd->input_device,
1642                                                    NULL, time);
1643         }
1644 }
1645
1646
1647 static void
1648 input_device_attach(struct wl_client *client,
1649                     struct wl_resource *resource,
1650                     uint32_t time,
1651                     struct wl_resource *buffer_resource, int32_t x, int32_t y)
1652 {
1653         struct wlsc_input_device *device = resource->data;
1654         struct wl_buffer *buffer;
1655
1656         if (time < device->input_device.pointer_focus_time)
1657                 return;
1658         if (device->input_device.pointer_focus == NULL)
1659                 return;
1660         if (device->input_device.pointer_focus->resource.client != client)
1661                 return;
1662
1663         if (buffer_resource) {
1664                 buffer = buffer_resource->data;
1665                 wlsc_input_device_attach_buffer(device, buffer, x, y);
1666         } else {
1667                 wlsc_input_device_set_pointer_image(device,
1668                                                     WLSC_POINTER_LEFT_PTR);
1669                 return;
1670         }
1671 }
1672
1673 const static struct wl_input_device_interface input_device_interface = {
1674         input_device_attach,
1675 };
1676
1677 static void unbind_input_device(struct wl_resource *resource)
1678 {
1679         wl_list_remove(&resource->link);
1680         free(resource);
1681 }
1682
1683 static void
1684 bind_input_device(struct wl_client *client,
1685                   void *data, uint32_t version, uint32_t id)
1686 {
1687         struct wl_input_device *device = data;
1688         struct wl_resource *resource;
1689
1690         resource = wl_client_add_object(client, &wl_input_device_interface,
1691                                         &input_device_interface, id, data);
1692         wl_list_insert(&device->resource_list, &resource->link);
1693         resource->destroy = unbind_input_device;
1694 }
1695
1696 WL_EXPORT void
1697 wlsc_input_device_init(struct wlsc_input_device *device,
1698                        struct wlsc_compositor *ec)
1699 {
1700         wl_input_device_init(&device->input_device, &ec->compositor);
1701
1702         wl_display_add_global(ec->wl_display, &wl_input_device_interface,
1703                               device, bind_input_device);
1704
1705         device->sprite = wlsc_surface_create(ec,
1706                                              device->input_device.x,
1707                                              device->input_device.y, 32, 32);
1708         wl_list_insert(&ec->surface_list, &device->sprite->link);
1709
1710         device->hotspot_x = 16;
1711         device->hotspot_y = 16;
1712         device->modifier_state = 0;
1713
1714         device->input_device.implicit_grab.interface = &implicit_grab_interface;
1715
1716         wl_list_insert(ec->input_device_list.prev, &device->link);
1717
1718         wlsc_input_device_set_pointer_image(device, WLSC_POINTER_LEFT_PTR);
1719 }
1720
1721 static void
1722 bind_output(struct wl_client *client,
1723             void *data, uint32_t version, uint32_t id)
1724 {
1725         struct wlsc_output *output = data;
1726         struct wlsc_mode *mode;
1727         struct wl_resource *resource;
1728
1729         resource = wl_client_add_object(client,
1730                                         &wl_output_interface, NULL, id, data);
1731
1732         wl_resource_post_event(resource,
1733                                WL_OUTPUT_GEOMETRY,
1734                                output->x,
1735                                output->y,
1736                                output->mm_width,
1737                                output->mm_height,
1738                                output->subpixel,
1739                                output->make, output->model);
1740
1741         wl_list_for_each (mode, &output->mode_list, link) {
1742                 wl_resource_post_event(resource,
1743                                        WL_OUTPUT_MODE,
1744                                        mode->flags,
1745                                        mode->width,
1746                                        mode->height,
1747                                        mode->refresh);
1748         }
1749 }
1750
1751 static const char vertex_shader[] =
1752         "uniform mat4 proj;\n"
1753         "attribute vec2 position;\n"
1754         "attribute vec2 texcoord;\n"
1755         "varying vec2 v_texcoord;\n"
1756         "void main()\n"
1757         "{\n"
1758         "   gl_Position = proj * vec4(position, 0.0, 1.0);\n"
1759         "   v_texcoord = texcoord;\n"
1760         "}\n";
1761
1762 static const char texture_fragment_shader[] =
1763         "precision mediump float;\n"
1764         "varying vec2 v_texcoord;\n"
1765         "uniform sampler2D tex;\n"
1766         "void main()\n"
1767         "{\n"
1768         "   gl_FragColor = texture2D(tex, v_texcoord)\n;"
1769         "}\n";
1770
1771 static const char solid_fragment_shader[] =
1772         "precision mediump float;\n"
1773         "uniform vec4 color;\n"
1774         "void main()\n"
1775         "{\n"
1776         "   gl_FragColor = color\n;"
1777         "}\n";
1778
1779 static int
1780 compile_shader(GLenum type, const char *source)
1781 {
1782         GLuint s;
1783         char msg[512];
1784         GLint status;
1785
1786         s = glCreateShader(type);
1787         glShaderSource(s, 1, &source, NULL);
1788         glCompileShader(s);
1789         glGetShaderiv(s, GL_COMPILE_STATUS, &status);
1790         if (!status) {
1791                 glGetShaderInfoLog(s, sizeof msg, NULL, msg);
1792                 fprintf(stderr, "shader info: %s\n", msg);
1793                 return GL_NONE;
1794         }
1795
1796         return s;
1797 }
1798
1799 static int
1800 wlsc_shader_init(struct wlsc_shader *shader,
1801                  const char *vertex_source, const char *fragment_source)
1802 {
1803         char msg[512];
1804         GLint status;
1805
1806         shader->vertex_shader =
1807                 compile_shader(GL_VERTEX_SHADER, vertex_source);
1808         shader->fragment_shader =
1809                 compile_shader(GL_FRAGMENT_SHADER, fragment_source);
1810
1811         shader->program = glCreateProgram();
1812         glAttachShader(shader->program, shader->vertex_shader);
1813         glAttachShader(shader->program, shader->fragment_shader);
1814         glBindAttribLocation(shader->program, 0, "position");
1815         glBindAttribLocation(shader->program, 1, "texcoord");
1816
1817         glLinkProgram(shader->program);
1818         glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
1819         if (!status) {
1820                 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
1821                 fprintf(stderr, "link info: %s\n", msg);
1822                 return -1;
1823         }
1824
1825         shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
1826         shader->tex_uniform = glGetUniformLocation(shader->program, "tex");
1827
1828         return 0;
1829 }
1830
1831 static int
1832 init_solid_shader(struct wlsc_shader *shader,
1833                   GLuint vertex_shader, const char *fragment_source)
1834 {
1835         GLint status;
1836         char msg[512];
1837
1838         shader->vertex_shader = vertex_shader;
1839         shader->fragment_shader =
1840                 compile_shader(GL_FRAGMENT_SHADER, fragment_source);
1841
1842         shader->program = glCreateProgram();
1843         glAttachShader(shader->program, shader->vertex_shader);
1844         glAttachShader(shader->program, shader->fragment_shader);
1845         glBindAttribLocation(shader->program, 0, "position");
1846         glBindAttribLocation(shader->program, 1, "texcoord");
1847
1848         glLinkProgram(shader->program);
1849         glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
1850         if (!status) {
1851                 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
1852                 fprintf(stderr, "link info: %s\n", msg);
1853                 return -1;
1854         }
1855  
1856         shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
1857         shader->color_uniform = glGetUniformLocation(shader->program, "color");
1858
1859         return 0;
1860 }
1861
1862 WL_EXPORT void
1863 wlsc_output_destroy(struct wlsc_output *output)
1864 {
1865         pixman_region32_fini(&output->region);
1866         pixman_region32_fini(&output->previous_damage);
1867 }
1868
1869 WL_EXPORT void
1870 wlsc_output_move(struct wlsc_output *output, int x, int y)
1871 {
1872         struct wlsc_compositor *c = output->compositor;
1873         int flip;
1874
1875         output->x = x;
1876         output->y = y;
1877
1878         pixman_region32_init(&output->previous_damage);
1879         pixman_region32_init_rect(&output->region, x, y, 
1880                                   output->current->width,
1881                                   output->current->height);
1882
1883         wlsc_matrix_init(&output->matrix);
1884         wlsc_matrix_translate(&output->matrix,
1885                               -output->x - output->current->width / 2.0,
1886                               -output->y - output->current->height / 2.0, 0);
1887
1888         flip = (output->flags & WL_OUTPUT_FLIPPED) ? -1 : 1;
1889         wlsc_matrix_scale(&output->matrix,
1890                           2.0 / output->current->width,
1891                           flip * 2.0 / output->current->height, 1);
1892
1893         pixman_region32_union(&c->damage, &c->damage, &output->region);
1894 }
1895
1896 WL_EXPORT void
1897 wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
1898                  int x, int y, int width, int height, uint32_t flags)
1899 {
1900         output->compositor = c;
1901         output->x = x;
1902         output->y = y;
1903         output->mm_width = width;
1904         output->mm_height = height;
1905
1906         output->flags = flags;
1907         wlsc_output_move(output, x, y);
1908
1909         output->scanout_buffer_destroy_listener.func =
1910                 output_handle_scanout_buffer_destroy;
1911         wl_list_init(&output->scanout_buffer_destroy_listener.link);
1912         wl_list_init(&output->frame_callback_list);
1913
1914         output->resource.object.interface = &wl_output_interface;
1915         wl_display_add_global(c->wl_display,
1916                               &wl_output_interface, output, bind_output);
1917 }
1918
1919 static void
1920 shm_buffer_created(struct wl_buffer *buffer)
1921 {
1922         struct wl_list *surfaces_attached_to;
1923
1924         surfaces_attached_to = malloc(sizeof *surfaces_attached_to);
1925         if (!surfaces_attached_to) {
1926                 buffer->user_data = NULL;
1927                 return;
1928         }
1929
1930         wl_list_init(surfaces_attached_to);
1931
1932         buffer->user_data = surfaces_attached_to;
1933 }
1934
1935 static void
1936 shm_buffer_damaged(struct wl_buffer *buffer,
1937                    int32_t x, int32_t y, int32_t width, int32_t height)
1938 {
1939         struct wl_list *surfaces_attached_to = buffer->user_data;
1940         struct wlsc_surface *es;
1941         GLsizei tex_width = wl_shm_buffer_get_stride(buffer) / 4;
1942
1943         wl_list_for_each(es, surfaces_attached_to, buffer_link) {
1944                 glBindTexture(GL_TEXTURE_2D, es->texture);
1945                 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1946                              tex_width, buffer->height, 0,
1947                              GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1948                              wl_shm_buffer_get_data(buffer));
1949                 /* Hmm, should use glTexSubImage2D() here but GLES2 doesn't
1950                  * support any unpack attributes except GL_UNPACK_ALIGNMENT. */
1951         }
1952 }
1953
1954 static void
1955 shm_buffer_destroyed(struct wl_buffer *buffer)
1956 {
1957         struct wl_list *surfaces_attached_to = buffer->user_data;
1958         struct wlsc_surface *es, *next;
1959
1960         wl_list_for_each_safe(es, next, surfaces_attached_to, buffer_link) {
1961                 wl_list_remove(&es->buffer_link);
1962                 wl_list_init(&es->buffer_link);
1963         }
1964
1965         free(surfaces_attached_to);
1966 }
1967
1968 const static struct wl_shm_callbacks shm_callbacks = {
1969         shm_buffer_created,
1970         shm_buffer_damaged,
1971         shm_buffer_destroyed
1972 };
1973
1974 WL_EXPORT int
1975 wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display)
1976 {
1977         struct wl_event_loop *loop;
1978         const char *extensions;
1979
1980         ec->wl_display = display;
1981
1982         wl_compositor_init(&ec->compositor, &compositor_interface, display);
1983
1984         ec->shm = wl_shm_init(display, &shm_callbacks);
1985
1986         ec->image_target_texture_2d =
1987                 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
1988         ec->image_target_renderbuffer_storage = (void *)
1989                 eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
1990         ec->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
1991         ec->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
1992         ec->bind_display =
1993                 (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
1994         ec->unbind_display =
1995                 (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
1996
1997         extensions = (const char *) glGetString(GL_EXTENSIONS);
1998         if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
1999                 fprintf(stderr,
2000                         "GL_EXT_texture_format_BGRA8888 not available\n");
2001                 return -1;
2002         }
2003
2004         extensions =
2005                 (const char *) eglQueryString(ec->display, EGL_EXTENSIONS);
2006         if (strstr(extensions, "EGL_WL_bind_wayland_display"))
2007                 ec->has_bind_display = 1;
2008         if (ec->has_bind_display)
2009                 ec->bind_display(ec->display, ec->wl_display);
2010
2011         wl_list_init(&ec->surface_list);
2012         wl_list_init(&ec->input_device_list);
2013         wl_list_init(&ec->output_list);
2014         wl_list_init(&ec->binding_list);
2015         wl_list_init(&ec->animation_list);
2016         wlsc_spring_init(&ec->fade.spring, 0.8, 0.0, 0.0);
2017         ec->fade.animation.frame = fade_frame;
2018         wl_list_init(&ec->fade.animation.link);
2019
2020         wlsc_compositor_add_binding(ec, KEY_BACKSPACE, 0,
2021                                     MODIFIER_CTRL | MODIFIER_ALT,
2022                                     terminate_binding, ec);
2023
2024         create_pointer_images(ec);
2025
2026         screenshooter_create(ec);
2027
2028         glActiveTexture(GL_TEXTURE0);
2029
2030         if (wlsc_shader_init(&ec->texture_shader,
2031                              vertex_shader, texture_fragment_shader) < 0)
2032                 return -1;
2033         if (init_solid_shader(&ec->solid_shader,
2034                               ec->texture_shader.vertex_shader,
2035                               solid_fragment_shader) < 0)
2036                 return -1;
2037
2038         loop = wl_display_get_event_loop(ec->wl_display);
2039         ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec);
2040         wl_event_source_timer_update(ec->idle_source, option_idle_time * 1000);
2041
2042         pixman_region32_init(&ec->damage);
2043         wlsc_compositor_schedule_repaint(ec);
2044
2045         return 0;
2046 }
2047
2048 WL_EXPORT void
2049 wlsc_compositor_shutdown(struct wlsc_compositor *ec)
2050 {
2051         struct wlsc_output *output;
2052
2053         /* Destroy all outputs associated with this compositor */
2054         wl_list_for_each(output, &ec->output_list, link)
2055                 output->destroy(output);
2056 }
2057
2058 static int on_term_signal(int signal_number, void *data)
2059 {
2060         struct wl_display *display = data;
2061
2062         fprintf(stderr, "caught signal %d\n", signal_number);
2063         wl_display_terminate(display);
2064
2065         return 1;
2066 }
2067
2068 static void *
2069 load_module(const char *name, const char *entrypoint, void **handle)
2070 {
2071         char path[PATH_MAX];
2072         void *module, *init;
2073
2074         if (name[0] != '/')
2075                 snprintf(path, sizeof path, MODULEDIR "/%s", name);
2076         else
2077                 snprintf(path, sizeof path, "%s", name);
2078
2079         module = dlopen(path, RTLD_LAZY);
2080         if (!module) {
2081                 fprintf(stderr,
2082                         "failed to load module: %s\n", dlerror());
2083                 return NULL;
2084         }
2085
2086         init = dlsym(module, entrypoint);
2087         if (!init) {
2088                 fprintf(stderr,
2089                         "failed to lookup init function: %s\n", dlerror());
2090                 return NULL;
2091         }
2092
2093         return init;
2094 }
2095
2096 int main(int argc, char *argv[])
2097 {
2098         struct wl_display *display;
2099         struct wlsc_compositor *ec;
2100         struct wl_event_loop *loop;
2101         int o, xserver = 0;
2102         void *shell_module, *backend_module;
2103         int (*shell_init)(struct wlsc_compositor *ec);
2104         struct wlsc_compositor
2105                 *(*backend_init)(struct wl_display *display, char *options);
2106         char *backend = NULL;
2107         char *backend_options = "";
2108         char *shell = NULL;
2109         char *p;
2110
2111         static const char opts[] = "B:b:o:S:i:s:x";
2112         static const struct option longopts[ ] = {
2113                 { "backend", 1, NULL, 'B' },
2114                 { "backend-options", 1, NULL, 'o' },
2115                 { "socket", 1, NULL, 'S' },
2116                 { "idle-time", 1, NULL, 'i' },
2117                 { "shell", 1, NULL, 's' },
2118                 { "xserver", 0, NULL, 'x' },
2119                 { NULL, }
2120         };
2121
2122         while (o = getopt_long(argc, argv, opts, longopts, &o), o > 0) {
2123                 switch (o) {
2124                 case 'B':
2125                         backend = optarg;
2126                         break;
2127                 case 'o':
2128                         backend_options = optarg;
2129                         break;
2130                 case 'S':
2131                         option_socket_name = optarg;
2132                         break;
2133                 case 'i':
2134                         option_idle_time = strtol(optarg, &p, 0);
2135                         if (*p != '\0') {
2136                                 fprintf(stderr,
2137                                         "invalid idle time option: %s\n",
2138                                         optarg);
2139                                 exit(EXIT_FAILURE);
2140                         }
2141                         break;
2142                 case 's':
2143                         shell = optarg;
2144                         break;
2145                 case 'x':
2146                         xserver = 1;
2147                         break;
2148                 }
2149         }
2150
2151         display = wl_display_create();
2152
2153         loop = wl_display_get_event_loop(display);
2154         wl_event_loop_add_signal(loop, SIGTERM, on_term_signal, display);
2155         wl_event_loop_add_signal(loop, SIGINT, on_term_signal, display);
2156         wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal, display);
2157
2158         wl_list_init(&child_process_list);
2159         wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler, NULL);
2160
2161         if (!backend) {
2162                 if (getenv("WAYLAND_DISPLAY"))
2163                         backend = "wayland-backend.so";
2164                 else if (getenv("DISPLAY"))
2165                         backend = "x11-backend.so";
2166                 else if (getenv("OPENWFD"))
2167                         backend = "openwfd-backend.so";
2168                 else
2169                         backend = "drm-backend.so";
2170         }
2171
2172         if (!shell)
2173                 shell = "desktop-shell.so";
2174
2175         backend_init = load_module(backend, "backend_init", &backend_module);
2176         if (!backend_init)
2177                 exit(EXIT_FAILURE);
2178
2179         shell_init = load_module(shell, "shell_init", &shell_module);
2180         if (!shell_init)
2181                 exit(EXIT_FAILURE);
2182
2183         ec = backend_init(display, backend_options);
2184         if (ec == NULL) {
2185                 fprintf(stderr, "failed to create compositor\n");
2186                 exit(EXIT_FAILURE);
2187         }
2188
2189         if (shell_init(ec) < 0)
2190                 exit(EXIT_FAILURE);
2191
2192         if (xserver)
2193                 wlsc_xserver_init(ec);
2194
2195         if (wl_display_add_socket(display, option_socket_name)) {
2196                 fprintf(stderr, "failed to add socket: %m\n");
2197                 exit(EXIT_FAILURE);
2198         }
2199
2200         wl_display_run(display);
2201
2202         if (xserver)
2203                 wlsc_xserver_destroy(ec);
2204
2205         if (ec->has_bind_display)
2206                 ec->unbind_display(ec->display, display);
2207         wl_display_destroy(display);
2208
2209         ec->destroy(ec);
2210
2211         return 0;
2212 }