535b3f1a5b04effc0bf4079fd5b19339817537cd
[profile/ivi/wayland.git] / compositor / compositor.c
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  *
4  * 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.
8  *
9  * 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.
17  */
18
19 #define _GNU_SOURCE
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <stdarg.h>
28 #include <sys/ioctl.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <gdk-pixbuf/gdk-pixbuf.h>
32 #include <math.h>
33 #include <linux/input.h>
34
35 #include "wayland-server.h"
36 #include "compositor.h"
37
38 struct wlsc_switcher {
39         struct wlsc_compositor *compositor;
40         struct wlsc_surface *current;
41         struct wl_listener listener;
42 };
43
44 /* The plan here is to generate a random anonymous socket name and
45  * advertise that through a service on the session dbus.
46  */
47 static const char *option_socket_name = NULL;
48 static const char *option_background = "background.jpg";
49 static const char *option_geometry = "1024x640";
50 static int option_connector = 0;
51
52 static const GOptionEntry option_entries[] = {
53         { "background", 'b', 0, G_OPTION_ARG_STRING,
54           &option_background, "Background image" },
55         { "connector", 'c', 0, G_OPTION_ARG_INT,
56           &option_connector, "KMS connector" },
57         { "geometry", 'g', 0, G_OPTION_ARG_STRING,
58           &option_geometry, "Geometry" },
59         { "socket", 's', 0, G_OPTION_ARG_STRING,
60           &option_socket_name, "Socket Name" },
61         { NULL }
62 };
63
64 static void
65 wlsc_matrix_init(struct wlsc_matrix *matrix)
66 {
67         static const struct wlsc_matrix identity = {
68                 { 1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  0, 0, 0, 1 }
69         };
70
71         memcpy(matrix, &identity, sizeof identity);
72 }
73
74 static void
75 wlsc_matrix_multiply(struct wlsc_matrix *m, const struct wlsc_matrix *n)
76 {
77         struct wlsc_matrix tmp;
78         const GLfloat *row, *column;
79         div_t d;
80         int i, j;
81
82         for (i = 0; i < 16; i++) {
83                 tmp.d[i] = 0;
84                 d = div(i, 4);
85                 row = m->d + d.quot * 4;
86                 column = n->d + d.rem;
87                 for (j = 0; j < 4; j++)
88                         tmp.d[i] += row[j] * column[j * 4];
89         }
90         memcpy(m, &tmp, sizeof tmp);
91 }
92
93 static void
94 wlsc_matrix_translate(struct wlsc_matrix *matrix, GLfloat x, GLfloat y, GLfloat z)
95 {
96         struct wlsc_matrix translate = {
97                 { 1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  x, y, z, 1 }
98         };
99
100         wlsc_matrix_multiply(matrix, &translate);
101 }
102
103 static void
104 wlsc_matrix_scale(struct wlsc_matrix *matrix, GLfloat x, GLfloat y, GLfloat z)
105 {
106         struct wlsc_matrix scale = {
107                 { x, 0, 0, 0,  0, y, 0, 0,  0, 0, z, 0,  0, 0, 0, 1 }
108         };
109
110         wlsc_matrix_multiply(matrix, &scale);
111 }
112
113 static void
114 wlsc_matrix_transform(struct wlsc_matrix *matrix, struct wlsc_vector *v)
115 {
116         int i, j;
117         struct wlsc_vector t;
118
119         for (i = 0; i < 4; i++) {
120                 t.f[i] = 0;
121                 for (j = 0; j < 4; j++)
122                         t.f[i] += v->f[j] * matrix->d[i + j * 4];
123         }
124
125         *v = t;
126 }
127
128 static struct wlsc_surface *
129 wlsc_surface_create(struct wlsc_compositor *compositor,
130                     int32_t x, int32_t y, int32_t width, int32_t height)
131 {
132         struct wlsc_surface *surface;
133
134         surface = malloc(sizeof *surface);
135         if (surface == NULL)
136                 return NULL;
137
138         wl_list_init(&surface->surface.destroy_listener_list);
139         wl_list_init(&surface->link);
140         surface->map_type = WLSC_SURFACE_MAP_UNMAPPED;
141
142         glGenTextures(1, &surface->texture);
143         glBindTexture(GL_TEXTURE_2D, surface->texture);
144         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
145         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
146         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
147         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
148
149         surface->compositor = compositor;
150         surface->visual = NULL;
151         surface->x = x;
152         surface->y = y;
153         surface->width = width;
154         surface->height = height;
155         wlsc_matrix_init(&surface->matrix);
156         wlsc_matrix_scale(&surface->matrix, width, height, 1);
157         wlsc_matrix_translate(&surface->matrix, x, y, 0);
158
159         wlsc_matrix_init(&surface->matrix_inv);
160         wlsc_matrix_translate(&surface->matrix_inv, -x, -y, 0);
161         wlsc_matrix_scale(&surface->matrix_inv, 1.0 / width, 1.0 / height, 1);
162
163         return surface;
164 }
165
166 uint32_t
167 get_time(void)
168 {
169         struct timeval tv;
170
171         gettimeofday(&tv, NULL);
172
173         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
174 }
175
176 static void
177 destroy_surface(struct wl_resource *resource, struct wl_client *client)
178 {
179         struct wlsc_surface *surface =
180                 container_of(resource, struct wlsc_surface, surface.resource);
181         struct wlsc_compositor *compositor = surface->compositor;
182         struct wl_listener *l, *next;
183         uint32_t time;
184
185         wl_list_remove(&surface->link);
186         glDeleteTextures(1, &surface->texture);
187
188         time = get_time();
189         wl_list_for_each_safe(l, next,
190                               &surface->surface.destroy_listener_list, link)
191                 l->func(l, &surface->surface, time);
192
193         free(surface);
194
195         wlsc_compositor_schedule_repaint(compositor);
196 }
197
198 uint32_t *
199 wlsc_load_image(const char *filename, int width, int height)
200 {
201         GdkPixbuf *pixbuf;
202         GError *error = NULL;
203         int stride, i, n_channels;
204         unsigned char *pixels, *end, *argb_pixels, *s, *d;
205
206         pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
207                                                    width, height,
208                                                    FALSE, &error);
209         if (error != NULL) {
210                 fprintf(stderr, "failed to load image: %s\n", error->message);
211                 g_error_free(error);
212                 return NULL;
213         }
214
215         stride = gdk_pixbuf_get_rowstride(pixbuf);
216         pixels = gdk_pixbuf_get_pixels(pixbuf);
217         n_channels = gdk_pixbuf_get_n_channels(pixbuf);
218
219         argb_pixels = malloc (height * width * 4);
220         if (argb_pixels == NULL) {
221                 g_object_unref(pixbuf);
222                 return NULL;
223         }
224
225         if (n_channels == 4) {
226                 for (i = 0; i < height; i++) {
227                         s = pixels + i * stride;
228                         end = s + width * 4;
229                         d = argb_pixels + i * width * 4;
230                         while (s < end) {
231                                 unsigned int t;
232
233 #define MULT(_d,c,a,t) \
234         do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
235                                 
236                                 MULT(d[0], s[2], s[3], t);
237                                 MULT(d[1], s[1], s[3], t);
238                                 MULT(d[2], s[0], s[3], t);
239                                 d[3] = s[3];
240                                 s += 4;
241                                 d += 4;
242                         }
243                 }
244         } else if (n_channels == 3) {
245                 for (i = 0; i < height; i++) {
246                         s = pixels + i * stride;
247                         end = s + width * 3;
248                         d = argb_pixels + i * width * 4;
249                         while (s < end) {
250                                 d[0] = s[2];
251                                 d[1] = s[1];
252                                 d[2] = s[0];
253                                 d[3] = 0xff;
254                                 s += 3;
255                                 d += 4;
256                         }
257                 }
258         }
259
260         g_object_unref(pixbuf);
261
262         return (uint32_t *) argb_pixels;
263 }
264
265 static struct wl_buffer *
266 create_buffer_from_png(struct wlsc_compositor *ec,
267                        const char *filename, int width, int height)
268 {
269         uint32_t *pixels;
270         struct wl_buffer *buffer;
271
272         pixels = wlsc_load_image(filename, width, height);
273         if(pixels == NULL)
274             return NULL;
275
276         buffer = ec->create_buffer(ec, width, height,
277                                    &ec->compositor.premultiplied_argb_visual,
278                                    pixels);
279
280         free(pixels);
281
282         return buffer;
283 }
284
285 static const struct {
286         const char *filename;
287         int hotspot_x, hotspot_y;
288 } pointer_images[] = {
289         { DATADIR "/wayland/bottom_left_corner.png",     6, 30 },
290         { DATADIR "/wayland/bottom_right_corner.png",   28, 28 },
291         { DATADIR "/wayland/bottom_side.png",           16, 20 },
292         { DATADIR "/wayland/grabbing.png",              20, 17 },
293         { DATADIR "/wayland/left_ptr.png",              10,  5 },
294         { DATADIR "/wayland/left_side.png",             10, 20 },
295         { DATADIR "/wayland/right_side.png",            30, 19 },
296         { DATADIR "/wayland/top_left_corner.png",        8,  8 },
297         { DATADIR "/wayland/top_right_corner.png",      26,  8 },
298         { DATADIR "/wayland/top_side.png",              18,  8 },
299         { DATADIR "/wayland/xterm.png",                 15, 15 }
300 };
301
302 static void
303 create_pointer_images(struct wlsc_compositor *ec)
304 {
305         int i, count;
306         const int width = 32, height = 32;
307
308         count = ARRAY_LENGTH(pointer_images);
309         ec->pointer_buffers = malloc(count * sizeof *ec->pointer_buffers);
310         for (i = 0; i < count; i++) {
311                 ec->pointer_buffers[i] =
312                         create_buffer_from_png(ec,
313                                                pointer_images[i].filename,
314                                                width, height);
315         }
316 }
317
318 static struct wlsc_surface *
319 background_create(struct wlsc_output *output, const char *filename)
320 {
321         struct wlsc_surface *background;
322         struct wl_buffer *buffer;
323
324         background = wlsc_surface_create(output->compositor,
325                                          output->x, output->y,
326                                          output->width, output->height);
327         if (background == NULL)
328                 return NULL;
329
330         buffer = create_buffer_from_png(output->compositor,
331                                         filename,
332                                         output->width, output->height);
333         if (buffer == NULL) {
334                 free(background);
335                 return NULL;
336         }
337         buffer->attach(buffer, &background->surface);
338
339         return background;
340 }
341
342 static void
343 wlsc_surface_draw(struct wlsc_surface *es, struct wlsc_output *output)
344 {
345         struct wlsc_compositor *ec = es->compositor;
346         struct wlsc_matrix tmp;
347
348         tmp = es->matrix;
349         wlsc_matrix_multiply(&tmp, &output->matrix);
350         glUniformMatrix4fv(ec->proj_uniform, 1, GL_FALSE, tmp.d);
351         glUniform1i(ec->tex_uniform, 0);
352
353         if (es->visual == &ec->compositor.argb_visual) {
354                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
355                 glEnable(GL_BLEND);
356         } else if (es->visual == &ec->compositor.premultiplied_argb_visual) {
357                 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
358                 glEnable(GL_BLEND);
359         } else {
360                 glDisable(GL_BLEND);
361         }
362
363         glBindTexture(GL_TEXTURE_2D, es->texture);
364         glBindBuffer(GL_ARRAY_BUFFER, ec->vbo);
365         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
366                               5 * sizeof(GLfloat), NULL);
367         glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,
368                               5 * sizeof(GLfloat), (GLfloat *) 0 + 3);
369         glEnableVertexAttribArray(0);
370         glEnableVertexAttribArray(1);
371         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
372 }
373
374 static void
375 wlsc_surface_raise(struct wlsc_surface *surface)
376 {
377         struct wlsc_compositor *compositor = surface->compositor;
378
379         wl_list_remove(&surface->link);
380         wl_list_insert(&compositor->surface_list, &surface->link);
381 }
382
383 void
384 wlsc_surface_update_matrix(struct wlsc_surface *es)
385 {
386         wlsc_matrix_init(&es->matrix);
387         wlsc_matrix_scale(&es->matrix, es->width, es->height, 1);
388         wlsc_matrix_translate(&es->matrix, es->x, es->y, 0);
389
390         wlsc_matrix_init(&es->matrix_inv);
391         wlsc_matrix_translate(&es->matrix_inv, -es->x, -es->y, 0);
392         wlsc_matrix_scale(&es->matrix_inv,
393                           1.0 / es->width, 1.0 / es->height, 1);
394 }
395
396 void
397 wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs)
398 {
399         wl_display_post_frame(compositor->wl_display, msecs);
400         wl_event_source_timer_update(compositor->timer_source, 5);
401         compositor->repaint_on_timeout = 1;
402 }
403
404 static void
405 wlsc_output_repaint(struct wlsc_output *output)
406 {
407         struct wlsc_compositor *ec = output->compositor;
408         struct wlsc_surface *es;
409         struct wlsc_input_device *eid;
410
411         glViewport(0, 0, output->width, output->height);
412
413         es = container_of(ec->surface_list.next, struct wlsc_surface, link);
414         if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN &&
415             es->fullscreen_output == output) {
416                 if (es->width < output->width || es->height < output->height)
417                         glClear(GL_COLOR_BUFFER_BIT);
418                 wlsc_surface_draw(es, output);
419         } else {
420                 if (output->background)
421                         wlsc_surface_draw(output->background, output);
422                 else
423                         glClear(GL_COLOR_BUFFER_BIT);
424
425                 wl_list_for_each_reverse(es, &ec->surface_list, link) {
426                         if (ec->switcher &&
427                             ec->switcher->current == es)
428                                 continue;
429
430                         wlsc_surface_draw(es, output);
431                 }
432         }
433
434         if (ec->switcher)
435                 wlsc_surface_draw(ec->switcher->current, output);
436
437         if (ec->focus)
438                 wl_list_for_each(eid, &ec->input_device_list, link)
439                         wlsc_surface_draw(eid->sprite, output);
440 }
441
442 static void
443 repaint(void *data)
444 {
445         struct wlsc_compositor *ec = data;
446         struct wlsc_output *output;
447
448         if (!ec->repaint_needed) {
449                 ec->repaint_on_timeout = 0;
450                 return;
451         }
452
453         wl_list_for_each(output, &ec->output_list, link)
454                 wlsc_output_repaint(output);
455
456         ec->present(ec);
457
458         ec->repaint_needed = 0;
459 }
460
461 void
462 wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor)
463 {
464         compositor->repaint_needed = 1;
465         if (compositor->repaint_on_timeout)
466                 return;
467
468         wl_event_source_timer_update(compositor->timer_source, 1);
469         compositor->repaint_on_timeout = 1;
470 }
471
472 static void
473 surface_destroy(struct wl_client *client,
474                 struct wl_surface *surface)
475 {
476         wl_resource_destroy(&surface->resource, client);
477 }
478
479 static void
480 surface_attach(struct wl_client *client,
481                struct wl_surface *surface, struct wl_buffer *buffer,
482                int32_t x, int32_t y)
483 {
484         struct wlsc_surface *es = (struct wlsc_surface *) surface;
485
486         buffer->attach(buffer, surface);
487         es->buffer = buffer;
488         es->x += x;
489         es->y += y;
490         es->width = buffer->width;
491         es->height = buffer->height;
492         wlsc_surface_update_matrix(es);
493 }
494
495 static void
496 surface_map_toplevel(struct wl_client *client,
497                      struct wl_surface *surface)
498 {
499         struct wlsc_surface *es = (struct wlsc_surface *) surface;
500
501         switch (es->map_type) {
502         case WLSC_SURFACE_MAP_UNMAPPED:
503                 es->x = 10 + random() % 400;
504                 es->y = 10 + random() % 400;
505                 wlsc_surface_update_matrix(es);
506                 wl_list_insert(&es->compositor->surface_list, &es->link);
507                 break;
508         case WLSC_SURFACE_MAP_TOPLEVEL:
509                 return;
510         case WLSC_SURFACE_MAP_FULLSCREEN:
511                 es->fullscreen_output = NULL;
512                 es->x = es->saved_x;
513                 es->y = es->saved_y;
514                 wlsc_surface_update_matrix(es);
515                 break;
516         default:
517                 break;
518         }
519
520         wlsc_compositor_schedule_repaint(es->compositor);
521         es->map_type = WLSC_SURFACE_MAP_TOPLEVEL;
522 }
523
524 static void
525 surface_map_transient(struct wl_client *client,
526                       struct wl_surface *surface, struct wl_surface *parent,
527                       int x, int y, uint32_t flags)
528 {
529         struct wlsc_surface *es = (struct wlsc_surface *) surface;
530         struct wlsc_surface *pes = (struct wlsc_surface *) parent;
531
532         switch (es->map_type) {
533         case WLSC_SURFACE_MAP_UNMAPPED:
534                 wl_list_insert(&es->compositor->surface_list, &es->link);
535                 break;
536         case WLSC_SURFACE_MAP_FULLSCREEN:
537                 es->fullscreen_output = NULL;
538                 break;
539         default:
540                 break;
541         }
542
543         es->x = pes->x + x;
544         es->y = pes->y + y;
545
546         wlsc_surface_update_matrix(es);
547         wlsc_compositor_schedule_repaint(es->compositor);
548         es->map_type = WLSC_SURFACE_MAP_TRANSIENT;
549 }
550
551 static void
552 surface_map_fullscreen(struct wl_client *client, struct wl_surface *surface)
553 {
554         struct wlsc_surface *es = (struct wlsc_surface *) surface;
555         struct wlsc_output *output;
556
557         switch (es->map_type) {
558         case WLSC_SURFACE_MAP_UNMAPPED:
559                 es->x = 10 + random() % 400;
560                 es->y = 10 + random() % 400;
561                 wl_list_insert(&es->compositor->surface_list, &es->link);
562                 break;
563         case WLSC_SURFACE_MAP_FULLSCREEN:
564                 return;
565         default:
566                 break;
567         }
568
569         /* FIXME: Fullscreen on first output */
570         /* FIXME: Handle output going away */
571         output = container_of(es->compositor->output_list.next,
572                               struct wlsc_output, link);
573
574         es->saved_x = es->x;
575         es->saved_y = es->y;
576         es->x = (output->width - es->width) / 2;
577         es->y = (output->height - es->height) / 2;
578         es->fullscreen_output = output;
579         wlsc_surface_update_matrix(es);
580         wlsc_compositor_schedule_repaint(es->compositor);
581         es->map_type = WLSC_SURFACE_MAP_FULLSCREEN;
582 }
583
584 static void
585 surface_damage(struct wl_client *client,
586                struct wl_surface *surface,
587                int32_t x, int32_t y, int32_t width, int32_t height)
588 {
589         struct wlsc_surface *es = (struct wlsc_surface *) surface;
590
591         es->buffer->damage(es->buffer, surface, x, y, width, height);
592         wlsc_compositor_schedule_repaint(es->compositor);
593 }
594
595 const static struct wl_surface_interface surface_interface = {
596         surface_destroy,
597         surface_attach,
598         surface_map_toplevel,
599         surface_map_transient,
600         surface_map_fullscreen,
601         surface_damage
602 };
603
604 static void
605 wlsc_input_device_attach(struct wlsc_input_device *device,
606                          struct wl_buffer *buffer, int x, int y)
607 {
608         struct wlsc_compositor *ec =
609                 (struct wlsc_compositor *) device->input_device.compositor;
610
611         buffer->attach(buffer, &device->sprite->surface);
612         device->hotspot_x = x;
613         device->hotspot_y = y;
614
615         device->sprite->x = device->input_device.x - device->hotspot_x;
616         device->sprite->y = device->input_device.y - device->hotspot_y;
617         device->sprite->width = buffer->width;
618         device->sprite->height = buffer->height;
619         wlsc_surface_update_matrix(device->sprite);
620
621         wlsc_compositor_schedule_repaint(ec);
622 }
623
624
625 void
626 wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
627                                     enum wlsc_pointer_type type)
628 {
629         struct wlsc_compositor *compositor =
630                 (struct wlsc_compositor *) device->input_device.compositor;
631
632         wlsc_input_device_attach(device,
633                                  compositor->pointer_buffers[type],
634                                  pointer_images[type].hotspot_x,
635                                  pointer_images[type].hotspot_y);
636 }
637
638 static void
639 compositor_create_surface(struct wl_client *client,
640                           struct wl_compositor *compositor, uint32_t id)
641 {
642         struct wlsc_compositor *ec = (struct wlsc_compositor *) compositor;
643         struct wlsc_surface *surface;
644
645         surface = wlsc_surface_create(ec, 0, 0, 0, 0);
646         if (surface == NULL) {
647                 wl_client_post_no_memory(client);
648                 return;
649         }
650
651         surface->surface.resource.destroy = destroy_surface;
652
653         surface->surface.resource.object.id = id;
654         surface->surface.resource.object.interface = &wl_surface_interface;
655         surface->surface.resource.object.implementation =
656                 (void (**)(void)) &surface_interface;
657         surface->surface.client = client;
658
659         wl_client_add_resource(client, &surface->surface.resource);
660 }
661
662 const static struct wl_compositor_interface compositor_interface = {
663         compositor_create_surface,
664 };
665
666 static void
667 wlsc_surface_transform(struct wlsc_surface *surface,
668                        int32_t x, int32_t y, int32_t *sx, int32_t *sy)
669 {
670         struct wlsc_vector v = { { x, y, 0, 1 } };
671
672         wlsc_matrix_transform(&surface->matrix_inv, &v);
673         *sx = v.f[0] * surface->width;
674         *sy = v.f[1] * surface->height;
675 }
676
677 struct wlsc_surface *
678 pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy)
679 {
680         struct wlsc_compositor *ec =
681                 (struct wlsc_compositor *) device->compositor;
682         struct wlsc_surface *es;
683
684         wl_list_for_each(es, &ec->surface_list, link) {
685                 wlsc_surface_transform(es, device->x, device->y, sx, sy);
686                 if (0 <= *sx && *sx < es->width &&
687                     0 <= *sy && *sy < es->height)
688                         return es;
689         }
690
691         return NULL;
692 }
693
694
695 static void
696 motion_grab_motion(struct wl_grab *grab,
697                    uint32_t time, int32_t x, int32_t y)
698 {
699         struct wlsc_input_device *device =
700                 (struct wlsc_input_device *) grab->input_device;
701         struct wlsc_surface *es =
702                 (struct wlsc_surface *) device->input_device.pointer_focus;
703         int32_t sx, sy;
704
705         wlsc_surface_transform(es, x, y, &sx, &sy);
706         wl_client_post_event(es->surface.client,
707                              &device->input_device.object,
708                              WL_INPUT_DEVICE_MOTION,
709                              time, x, y, sx, sy);
710 }
711
712 static void
713 motion_grab_button(struct wl_grab *grab,
714                    uint32_t time, int32_t button, int32_t state)
715 {
716         wl_client_post_event(grab->input_device->pointer_focus->client,
717                              &grab->input_device->object,
718                              WL_INPUT_DEVICE_BUTTON,
719                              time, button, state);
720 }
721
722 static void
723 motion_grab_end(struct wl_grab *grab, uint32_t time)
724 {
725 }
726
727 static const struct wl_grab_interface motion_grab_interface = {
728         motion_grab_motion,
729         motion_grab_button,
730         motion_grab_end
731 };
732
733 void
734 notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
735 {
736         struct wlsc_surface *es;
737         struct wlsc_compositor *ec =
738                 (struct wlsc_compositor *) device->compositor;
739         struct wlsc_output *output;
740         const struct wl_grab_interface *interface;
741         struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
742         int32_t sx, sy;
743
744         /* FIXME: We need some multi head love here. */
745         output = container_of(ec->output_list.next, struct wlsc_output, link);
746         if (x < output->x)
747                 x = 0;
748         if (y < output->y)
749                 y = 0;
750         if (x >= output->x + output->width)
751                 x = output->x + output->width - 1;
752         if (y >= output->y + output->height)
753                 y = output->y + output->height - 1;
754
755         device->x = x;
756         device->y = y;
757
758         if (device->grab) {
759                 interface = device->grab->interface;
760                 interface->motion(device->grab, time, x, y);
761         } else {
762                 es = pick_surface(device, &sx, &sy);
763                 wl_input_device_set_pointer_focus(device,
764                                                   &es->surface,
765                                                   time, x, y, sx, sy);
766                 if (es)
767                         wl_client_post_event(es->surface.client,
768                                              &device->object,
769                                              WL_INPUT_DEVICE_MOTION,
770                                              time, x, y, sx, sy);
771         }
772
773         wd->sprite->x = device->x - wd->hotspot_x;
774         wd->sprite->y = device->y - wd->hotspot_y;
775         wlsc_surface_update_matrix(wd->sprite);
776
777         wlsc_compositor_schedule_repaint(ec);
778 }
779
780 static void
781 wlsc_surface_activate(struct wlsc_surface *surface,
782                       struct wlsc_input_device *device, uint32_t time)
783 {
784         wlsc_surface_raise(surface);
785         if (device->selection)
786                 wlsc_selection_set_focus(device->selection,
787                                          &surface->surface, time);
788
789         wl_input_device_set_keyboard_focus(&device->input_device,
790                                            &surface->surface,
791                                            time);
792 }
793
794 void
795 notify_button(struct wl_input_device *device,
796               uint32_t time, int32_t button, int32_t state)
797 {
798         struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
799         struct wlsc_surface *surface;
800         struct wlsc_compositor *compositor =
801                 (struct wlsc_compositor *) device->compositor;
802
803         surface = (struct wlsc_surface *) device->pointer_focus;
804         uint32_t edges = 0;
805         int32_t x, y;
806
807         if (state && surface && device->grab == NULL) {
808                 wlsc_surface_activate(surface, wd, time);
809                 wl_input_device_start_grab(device,
810                                            &device->motion_grab,
811                                            button, time);
812         }
813
814         if (state && surface && button == BTN_LEFT &&
815             (wd->modifier_state & MODIFIER_SUPER))
816                 shell_move(NULL,
817                            (struct wl_shell *) &compositor->shell,
818                            &surface->surface, device, time);
819         else if (state && surface && button == BTN_MIDDLE &&
820                  (wd->modifier_state & MODIFIER_SUPER)) {
821
822                 x = device->grab_x - surface->x;
823                 y = device->grab_y - surface->y;
824
825                 if (x < surface->width / 3)
826                         edges |= WL_SHELL_RESIZE_LEFT;
827                 else if (x < 2 * surface->width / 3)
828                         edges |= 0;
829                 else
830                         edges |= WL_SHELL_RESIZE_RIGHT;
831
832                 if (y < surface->height / 3)
833                         edges |= WL_SHELL_RESIZE_TOP;
834                 else if (y < 2 * surface->height / 3)
835                         edges |= 0;
836                 else
837                         edges |= WL_SHELL_RESIZE_BOTTOM;
838
839                 shell_resize(NULL,
840                              (struct wl_shell *) &compositor->shell,
841                              &surface->surface, device, time, edges);
842         }
843
844         if (device->grab)
845                 device->grab->interface->button(device->grab, time,
846                                                 button, state);
847
848         if (!state && device->grab && device->grab_button == button)
849                 wl_input_device_end_grab(device, time);
850 }
851
852 static void
853 wlsc_switcher_next(struct wlsc_switcher *switcher)
854 {
855         struct wl_list *l;
856
857         l = switcher->current->link.next;
858         if (l == &switcher->compositor->surface_list)
859                 l = switcher->compositor->surface_list.next;
860         switcher->current = container_of(l, struct wlsc_surface, link);
861         wl_list_remove(&switcher->listener.link);
862         wl_list_insert(switcher->current->surface.destroy_listener_list.prev,
863                        &switcher->listener.link);
864         wlsc_compositor_schedule_repaint(switcher->compositor);
865 }
866
867 static void
868 switcher_handle_surface_destroy(struct wl_listener *listener,
869                                 struct wl_surface *surface, uint32_t time)
870 {
871         struct wlsc_switcher *switcher =
872                 container_of(listener, struct wlsc_switcher, listener);
873
874         wlsc_switcher_next(switcher);
875 }
876
877 static struct wlsc_switcher *
878 wlsc_switcher_create(struct wlsc_compositor *compositor)
879 {
880         struct wlsc_switcher *switcher;
881
882         switcher = malloc(sizeof *switcher);
883         switcher->compositor = compositor;
884         switcher->current = container_of(compositor->surface_list.next,
885                                          struct wlsc_surface, link);
886         switcher->listener.func = switcher_handle_surface_destroy;
887         wl_list_init(&switcher->listener.link);
888
889         return switcher;
890 }
891
892 static void
893 wlsc_switcher_destroy(struct wlsc_switcher *switcher)
894 {
895         wl_list_remove(&switcher->listener.link);
896         free(switcher);
897 }
898
899 void
900 notify_key(struct wl_input_device *device,
901            uint32_t time, uint32_t key, uint32_t state)
902 {
903         struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
904         struct wlsc_compositor *compositor =
905                 (struct wlsc_compositor *) device->compositor;
906         uint32_t *k, *end;
907         uint32_t modifier;
908
909         switch (key | wd->modifier_state) {
910         case KEY_BACKSPACE | MODIFIER_CTRL | MODIFIER_ALT:
911                 wl_display_terminate(compositor->wl_display);
912                 return;
913
914         case KEY_TAB | MODIFIER_SUPER:
915                 if (!state)
916                         return;
917                 if (wl_list_empty(&compositor->surface_list))
918                         return;
919                 if (compositor->switcher == NULL)
920                         compositor->switcher = wlsc_switcher_create(compositor);
921
922                 wlsc_switcher_next(compositor->switcher);
923                 return;
924
925         case KEY_LEFTMETA | MODIFIER_SUPER:
926         case KEY_RIGHTMETA | MODIFIER_SUPER:
927                 if (compositor->switcher && !state) {
928                         wlsc_surface_activate(compositor->switcher->current,
929                                               wd, time);
930                         wlsc_switcher_destroy(compositor->switcher);
931                         compositor->switcher = NULL;
932                 }
933                 break;
934         }
935
936         switch (key) {
937         case KEY_LEFTCTRL:
938         case KEY_RIGHTCTRL:
939                 modifier = MODIFIER_CTRL;
940                 break;
941
942         case KEY_LEFTALT:
943         case KEY_RIGHTALT:
944                 modifier = MODIFIER_ALT;
945                 break;
946
947         case KEY_LEFTMETA:
948         case KEY_RIGHTMETA:
949                 modifier = MODIFIER_SUPER;
950                 break;
951
952         default:
953                 modifier = 0;
954                 break;
955         }
956
957         if (state)
958                 wd->modifier_state |= modifier;
959         else
960                 wd->modifier_state &= ~modifier;
961
962         end = device->keys.data + device->keys.size;
963         for (k = device->keys.data; k < end; k++) {
964                 if (*k == key)
965                         *k = *--end;
966         }
967         device->keys.size = (void *) end - device->keys.data;
968         if (state) {
969                 k = wl_array_add(&device->keys, sizeof *k);
970                 *k = key;
971         }
972
973         if (device->keyboard_focus != NULL)
974                 wl_client_post_event(device->keyboard_focus->client,
975                                      &device->object,
976                                      WL_INPUT_DEVICE_KEY, time, key, state);
977 }
978
979 void
980 notify_pointer_focus(struct wl_input_device *device,
981                      uint32_t time, struct wlsc_output *output,
982                      int32_t x, int32_t y)
983 {
984         struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
985         struct wlsc_compositor *compositor =
986                 (struct wlsc_compositor *) device->compositor;
987         struct wlsc_surface *es;
988         int32_t sx, sy;
989
990         if (output) {
991                 device->x = x;
992                 device->y = y;
993                 es = pick_surface(device, &sx, &sy);
994                 wl_input_device_set_pointer_focus(device,
995                                                   &es->surface,
996                                                   time, x, y, sx, sy);
997
998                 compositor->focus = 1;
999
1000                 wd->sprite->x = device->x - wd->hotspot_x;
1001                 wd->sprite->y = device->y - wd->hotspot_y;
1002                 wlsc_surface_update_matrix(wd->sprite);
1003         } else {
1004                 wl_input_device_set_pointer_focus(device, NULL,
1005                                                   time, 0, 0, 0, 0);
1006                 compositor->focus = 0;
1007         }
1008
1009         wlsc_compositor_schedule_repaint(compositor);
1010 }
1011
1012 void
1013 notify_keyboard_focus(struct wl_input_device *device,
1014                       uint32_t time, struct wlsc_output *output,
1015                       struct wl_array *keys)
1016 {
1017         struct wlsc_input_device *wd =
1018                 (struct wlsc_input_device *) device;
1019         struct wlsc_compositor *compositor =
1020                 (struct wlsc_compositor *) device->compositor;
1021         struct wlsc_surface *es;
1022
1023         if (!wl_list_empty(&compositor->surface_list))
1024                 es = container_of(compositor->surface_list.next,
1025                                   struct wlsc_surface, link);
1026         else
1027                 es = NULL;
1028
1029         if (output) {
1030                 wl_array_copy(&wd->input_device.keys, keys);
1031                 wl_input_device_set_keyboard_focus(&wd->input_device,
1032                                                    &es->surface, time);
1033         } else {
1034                 wl_input_device_set_keyboard_focus(&wd->input_device,
1035                                                    NULL, time);
1036         }
1037 }
1038
1039
1040 static void
1041 input_device_attach(struct wl_client *client,
1042                     struct wl_input_device *device_base,
1043                     uint32_t time,
1044                     struct wl_buffer *buffer, int32_t x, int32_t y)
1045 {
1046         struct wlsc_input_device *device =
1047                 (struct wlsc_input_device *) device_base;
1048
1049         if (time < device->input_device.pointer_focus_time)
1050                 return;
1051         if (device->input_device.pointer_focus == NULL)
1052                 return;
1053         if (device->input_device.pointer_focus->client != client)
1054                 return;
1055
1056         if (buffer == NULL) {
1057                 wlsc_input_device_set_pointer_image(device,
1058                                                     WLSC_POINTER_LEFT_PTR);
1059                 return;
1060         }
1061
1062         wlsc_input_device_attach(device, buffer, x, y);
1063 }
1064
1065 const static struct wl_input_device_interface input_device_interface = {
1066         input_device_attach,
1067 };
1068
1069 void
1070 wlsc_input_device_init(struct wlsc_input_device *device,
1071                        struct wlsc_compositor *ec)
1072 {
1073         wl_input_device_init(&device->input_device, &ec->compositor);
1074
1075         device->input_device.object.interface = &wl_input_device_interface;
1076         device->input_device.object.implementation =
1077                 (void (**)(void)) &input_device_interface;
1078         wl_display_add_object(ec->wl_display, &device->input_device.object);
1079         wl_display_add_global(ec->wl_display, &device->input_device.object, NULL);
1080
1081         device->sprite = wlsc_surface_create(ec,
1082                                              device->input_device.x,
1083                                              device->input_device.y, 32, 32);
1084         device->hotspot_x = 16;
1085         device->hotspot_y = 16;
1086
1087         device->input_device.motion_grab.interface = &motion_grab_interface;
1088
1089         wl_list_insert(ec->input_device_list.prev, &device->link);
1090
1091         wlsc_input_device_set_pointer_image(device, WLSC_POINTER_LEFT_PTR);
1092 }
1093
1094 static void
1095 wlsc_output_post_geometry(struct wl_client *client, struct wl_object *global)
1096 {
1097         struct wlsc_output *output =
1098                 container_of(global, struct wlsc_output, object);
1099
1100         wl_client_post_event(client, global,
1101                              WL_OUTPUT_GEOMETRY,
1102                              output->x, output->y,
1103                              output->width, output->height);
1104 }
1105
1106 static const char vertex_shader[] =
1107         "uniform mat4 proj;\n"
1108         "attribute vec4 position;\n"
1109         "attribute vec2 texcoord;\n"
1110         "varying vec2 v_texcoord;\n"
1111         "void main()\n"
1112         "{\n"
1113         "   gl_Position = proj * position;\n"
1114         "   v_texcoord = texcoord;\n"
1115         "}\n";
1116
1117 static const char fragment_shader[] =
1118         "precision mediump float;\n"
1119         "varying vec2 v_texcoord;\n"
1120         "uniform sampler2D tex;\n"
1121         "void main()\n"
1122         "{\n"
1123         "   gl_FragColor = texture2D(tex, v_texcoord)\n;"
1124         "}\n";
1125
1126 static int
1127 init_shaders(struct wlsc_compositor *ec)
1128 {
1129         GLuint v, f, program;
1130         const char *p;
1131         char msg[512];
1132         GLfloat vertices[4 * 5];
1133         GLint status;
1134
1135         p = vertex_shader;
1136         v = glCreateShader(GL_VERTEX_SHADER);
1137         glShaderSource(v, 1, &p, NULL);
1138         glCompileShader(v);
1139         glGetShaderiv(v, GL_COMPILE_STATUS, &status);
1140         if (!status) {
1141                 glGetShaderInfoLog(v, sizeof msg, NULL, msg);
1142                 fprintf(stderr, "vertex shader info: %s\n", msg);
1143                 return -1;
1144         }
1145
1146         p = fragment_shader;
1147         f = glCreateShader(GL_FRAGMENT_SHADER);
1148         glShaderSource(f, 1, &p, NULL);
1149         glCompileShader(f);
1150         glGetShaderiv(f, GL_COMPILE_STATUS, &status);
1151         if (!status) {
1152                 glGetShaderInfoLog(f, sizeof msg, NULL, msg);
1153                 fprintf(stderr, "fragment shader info: %s\n", msg);
1154                 return -1;
1155         }
1156
1157         program = glCreateProgram();
1158         glAttachShader(program, v);
1159         glAttachShader(program, f);
1160         glBindAttribLocation(program, 0, "position");
1161         glBindAttribLocation(program, 1, "texcoord");
1162
1163         glLinkProgram(program);
1164         glGetProgramiv(program, GL_LINK_STATUS, &status);
1165         if (!status) {
1166                 glGetProgramInfoLog(program, sizeof msg, NULL, msg);
1167                 fprintf(stderr, "link info: %s\n", msg);
1168                 return -1;
1169         }
1170
1171         glUseProgram(program);
1172         ec->proj_uniform = glGetUniformLocation(program, "proj");
1173         ec->tex_uniform = glGetUniformLocation(program, "tex");
1174
1175         vertices[ 0] = 0.0;
1176         vertices[ 1] = 0.0;
1177         vertices[ 2] = 0.0;
1178         vertices[ 3] = 0.0;
1179         vertices[ 4] = 0.0;
1180
1181         vertices[ 5] = 0.0;
1182         vertices[ 6] = 1.0;
1183         vertices[ 7] = 0.0;
1184         vertices[ 8] = 0.0;
1185         vertices[ 9] = 1.0;
1186
1187         vertices[10] = 1.0;
1188         vertices[11] = 0.0;
1189         vertices[12] = 0.0;
1190         vertices[13] = 1.0;
1191         vertices[14] = 0.0;
1192
1193         vertices[15] = 1.0;
1194         vertices[16] = 1.0;
1195         vertices[17] = 0.0;
1196         vertices[18] = 1.0;
1197         vertices[19] = 1.0;
1198
1199         glGenBuffers(1, &ec->vbo);
1200         glBindBuffer(GL_ARRAY_BUFFER, ec->vbo);
1201         glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW);
1202
1203         return 0;
1204 }
1205
1206 void
1207 wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
1208                  int x, int y, int width, int height)
1209 {
1210         output->compositor = c;
1211         output->x = x;
1212         output->y = y;
1213         output->width = width;
1214         output->height = height;
1215
1216         output->background =
1217                 background_create(output, option_background);
1218
1219         wlsc_matrix_init(&output->matrix);
1220         wlsc_matrix_translate(&output->matrix,
1221                               -output->x - output->width / 2.0,
1222                               -output->y - output->height / 2.0, 0);
1223         wlsc_matrix_scale(&output->matrix,
1224                           2.0 / output->width, 2.0 / output->height, 1);
1225
1226         output->object.interface = &wl_output_interface;
1227         wl_display_add_object(c->wl_display, &output->object);
1228         wl_display_add_global(c->wl_display, &output->object,
1229                               wlsc_output_post_geometry);
1230 }
1231
1232 int
1233 wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display)
1234 {
1235         struct wl_event_loop *loop;
1236         const char *extensions;
1237
1238         ec->wl_display = display;
1239
1240         wl_compositor_init(&ec->compositor, &compositor_interface, display);
1241
1242         wlsc_shm_init(ec);
1243
1244         wlsc_shell_init(ec);
1245
1246         wl_list_init(&ec->surface_list);
1247         wl_list_init(&ec->input_device_list);
1248         wl_list_init(&ec->output_list);
1249
1250         create_pointer_images(ec);
1251
1252         screenshooter_create(ec);
1253
1254         extensions = (const char *) glGetString(GL_EXTENSIONS);
1255         if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
1256                 fprintf(stderr,
1257                         "GL_EXT_texture_format_BGRA8888 not available\n");
1258                 return -1;
1259         }
1260
1261         glGenFramebuffers(1, &ec->fbo);
1262         glBindFramebuffer(GL_FRAMEBUFFER, ec->fbo);
1263         glActiveTexture(GL_TEXTURE0);
1264         if (init_shaders(ec) < 0)
1265                 return -1;
1266
1267         loop = wl_display_get_event_loop(ec->wl_display);
1268         ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec);
1269         wlsc_compositor_schedule_repaint(ec);
1270
1271         return 0;
1272 }
1273
1274 static void on_term_signal(int signal_number, void *data)
1275 {
1276         struct wlsc_compositor *ec = data;
1277
1278         wl_display_terminate(ec->wl_display);
1279 }
1280
1281 int main(int argc, char *argv[])
1282 {
1283         struct wl_display *display;
1284         struct wlsc_compositor *ec;
1285         struct wl_event_loop *loop;
1286         GError *error = NULL;
1287         GOptionContext *context;
1288         int width, height;
1289
1290         g_type_init(); /* GdkPixbuf needs this, it seems. */
1291
1292         context = g_option_context_new(NULL);
1293         g_option_context_add_main_entries(context, option_entries, "Wayland");
1294         if (!g_option_context_parse(context, &argc, &argv, &error)) {
1295                 fprintf(stderr, "option parsing failed: %s\n", error->message);
1296                 exit(EXIT_FAILURE);
1297         }
1298         if (sscanf(option_geometry, "%dx%d", &width, &height) != 2) {
1299                 fprintf(stderr, "invalid geometry option: %s \n",
1300                         option_geometry);
1301                 exit(EXIT_FAILURE);
1302         }
1303
1304         display = wl_display_create();
1305
1306         ec = NULL;
1307
1308 #if BUILD_WAYLAND_COMPOSITOR
1309         if (getenv("WAYLAND_DISPLAY"))
1310                 ec = wayland_compositor_create(display, width, height);
1311 #endif
1312
1313 #if BUILD_X11_COMPOSITOR
1314         if (ec == NULL && getenv("DISPLAY"))
1315                 ec = x11_compositor_create(display, width, height);
1316 #endif
1317
1318 #if BUILD_DRM_COMPOSITOR
1319         if (ec == NULL)
1320                 ec = drm_compositor_create(display, option_connector);
1321 #endif
1322
1323         if (ec == NULL) {
1324                 fprintf(stderr, "failed to create compositor\n");
1325                 exit(EXIT_FAILURE);
1326         }
1327
1328         if (wl_display_add_socket(display, option_socket_name)) {
1329                 fprintf(stderr, "failed to add socket: %m\n");
1330                 exit(EXIT_FAILURE);
1331         }
1332
1333         loop = wl_display_get_event_loop(ec->wl_display);
1334         wl_event_loop_add_signal(loop, SIGTERM, on_term_signal, ec);
1335         wl_event_loop_add_signal(loop, SIGINT, on_term_signal, ec);
1336
1337         wl_display_run(display);
1338
1339         wl_display_destroy(display);
1340
1341         ec->destroy(ec);
1342
1343         return 0;
1344 }