compositor-x11: Add error handling in x11_compositor_create()
[platform/upstream/weston.git] / src / compositor-x11.c
1 /*
2  * Copyright © 2008-2011 Kristian Høgsberg
3  * Copyright © 2010-2011 Intel Corporation
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 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stddef.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <sys/time.h>
35 #include <linux/input.h>
36
37 #include <xcb/xcb.h>
38 #ifdef HAVE_XCB_XKB
39 #include <xcb/xkb.h>
40 #endif
41
42 #include <X11/Xlib.h>
43 #include <X11/Xlib-xcb.h>
44
45 #include <xkbcommon/xkbcommon.h>
46
47 #include <GLES2/gl2.h>
48 #include <EGL/egl.h>
49
50 #include "compositor.h"
51 #include "../shared/config-parser.h"
52 #include "log.h"
53
54 struct x11_compositor {
55         struct weston_compositor         base;
56
57         EGLSurface               dummy_pbuffer;
58
59         Display                 *dpy;
60         xcb_connection_t        *conn;
61         xcb_screen_t            *screen;
62         xcb_cursor_t             null_cursor;
63         struct wl_array          keys;
64         struct wl_event_source  *xcb_source;
65         struct xkb_keymap       *xkb_keymap;
66         unsigned int             has_xkb;
67         uint8_t                  xkb_event_base;
68         struct {
69                 xcb_atom_t               wm_protocols;
70                 xcb_atom_t               wm_normal_hints;
71                 xcb_atom_t               wm_size_hints;
72                 xcb_atom_t               wm_delete_window;
73                 xcb_atom_t               wm_class;
74                 xcb_atom_t               net_wm_name;
75                 xcb_atom_t               net_wm_icon;
76                 xcb_atom_t               net_wm_state;
77                 xcb_atom_t               net_wm_state_fullscreen;
78                 xcb_atom_t               string;
79                 xcb_atom_t               utf8_string;
80                 xcb_atom_t               cardinal;
81                 xcb_atom_t               xkb_names;
82         } atom;
83 };
84
85 struct x11_output {
86         struct weston_output    base;
87
88         xcb_window_t            window;
89         EGLSurface              egl_surface;
90         struct weston_mode      mode;
91         struct wl_event_source *finish_frame_timer;
92 };
93
94 struct x11_input {
95         struct weston_seat base;
96 };
97
98 static struct xkb_keymap *
99 x11_compositor_get_keymap(struct x11_compositor *c)
100 {
101         xcb_get_property_cookie_t cookie;
102         xcb_get_property_reply_t *reply;
103         xcb_generic_error_t *error;
104         struct xkb_rule_names names;
105         struct xkb_keymap *ret;
106         const char *value_all, *value_part;
107         int length_all, length_part;
108
109         memset(&names, 0, sizeof(names));
110
111         cookie = xcb_get_property(c->conn, 0, c->screen->root,
112                                   c->atom.xkb_names, c->atom.string, 0, 1024);
113         reply = xcb_get_property_reply(c->conn, cookie, &error);
114         if (reply == NULL)
115                 return NULL;
116
117         value_all = xcb_get_property_value(reply);
118         length_all = xcb_get_property_value_length(reply);
119         value_part = value_all;
120
121 #define copy_prop_value(to) \
122         length_part = strlen(value_part); \
123         if (value_part + length_part < (value_all + length_all) && \
124             length_part > 0) \
125                 names.to = value_part; \
126         value_part += length_part + 1;
127
128         copy_prop_value(rules);
129         copy_prop_value(model);
130         copy_prop_value(layout);
131         copy_prop_value(variant);
132         copy_prop_value(options);
133 #undef copy_prop_value
134
135         ret = xkb_map_new_from_names(c->base.xkb_context, &names, 0);
136
137         free(reply);
138         return ret;
139 }
140
141 static void
142 x11_compositor_setup_xkb(struct x11_compositor *c)
143 {
144 #ifndef HAVE_XCB_XKB
145         weston_log("XCB-XKB not available during build\n");
146         c->has_xkb = 0;
147         c->xkb_event_base = 0;
148         return;
149 #else
150         const xcb_query_extension_reply_t *ext;
151         xcb_generic_error_t *error;
152         xcb_void_cookie_t select;
153         xcb_xkb_per_client_flags_cookie_t pcf;
154         xcb_xkb_per_client_flags_reply_t *pcf_reply;
155
156         c->has_xkb = 0;
157         c->xkb_event_base = 0;
158
159         ext = xcb_get_extension_data(c->conn, &xcb_xkb_id);
160         if (!ext) {
161                 weston_log("XKB extension not available on host X11 server\n");
162                 return;
163         }
164         c->xkb_event_base = ext->first_event;
165
166         select = xcb_xkb_select_events(c->conn,
167                                        XCB_XKB_ID_USE_CORE_KBD,
168                                        XCB_XKB_EVENT_TYPE_STATE_NOTIFY,
169                                        0,
170                                        XCB_XKB_EVENT_TYPE_STATE_NOTIFY,
171                                        0,
172                                        0,
173                                        NULL);
174         error = xcb_request_check(c->conn, select);
175         if (error) {
176                 weston_log("error: failed to select for XKB state events\n");
177                 return;
178         }
179
180         pcf = xcb_xkb_per_client_flags(c->conn,
181                                        XCB_XKB_ID_USE_CORE_KBD,
182                                        XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT,
183                                        XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT,
184                                        0,
185                                        0,
186                                        0);
187         pcf_reply = xcb_xkb_per_client_flags_reply(c->conn, pcf, &error);
188         free(pcf_reply);
189         if (error) {
190                 weston_log("failed to set XKB per-client flags, not using "
191                            "detectable repeat\n");
192                 return;
193         }
194
195         c->has_xkb = 1;
196 #endif
197 }
198
199 static int
200 x11_input_create(struct x11_compositor *c, int no_input)
201 {
202         struct x11_input *input;
203         struct xkb_keymap *keymap;
204
205         input = malloc(sizeof *input);
206         if (input == NULL)
207                 return -1;
208
209         memset(input, 0, sizeof *input);
210         weston_seat_init(&input->base, &c->base);
211         c->base.seat = &input->base;
212
213         if (no_input)
214                 return 0;
215
216         weston_seat_init_pointer(&input->base);
217
218         x11_compositor_setup_xkb(c);
219
220         keymap = x11_compositor_get_keymap(c);
221         weston_seat_init_keyboard(&input->base, keymap);
222         if (keymap)
223                 xkb_map_unref(keymap);
224
225         return 0;
226 }
227
228 static void
229 x11_input_destroy(struct x11_compositor *compositor)
230 {
231         struct x11_input *input = container_of(compositor->base.seat,
232                                                struct x11_input,
233                                                base);
234
235         weston_seat_release(&input->base);
236         free(input);
237 }
238
239 static int
240 x11_compositor_init_egl(struct x11_compositor *c)
241 {
242         EGLint major, minor;
243         EGLint n;
244         EGLint config_attribs[] = {
245                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
246                 EGL_RED_SIZE, 1,
247                 EGL_GREEN_SIZE, 1,
248                 EGL_BLUE_SIZE, 1,
249                 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
250                 EGL_NONE
251         };
252         static const EGLint context_attribs[] = {
253                 EGL_CONTEXT_CLIENT_VERSION, 2,
254                 EGL_NONE
255         };
256
257         static const EGLint pbuffer_attribs[] = {
258                 EGL_WIDTH, 10,
259                 EGL_HEIGHT, 10,
260                 EGL_NONE
261         };
262
263         c->base.egl_display = eglGetDisplay(c->dpy);
264         if (c->base.egl_display == NULL) {
265                 weston_log("failed to create display\n");
266                 return -1;
267         }
268
269         if (!eglInitialize(c->base.egl_display, &major, &minor)) {
270                 weston_log("failed to initialize display\n");
271                 return -1;
272         }
273
274         if (!eglBindAPI(EGL_OPENGL_ES_API)) {
275                 weston_log("failed to bind EGL_OPENGL_ES_API\n");
276                 return -1;
277         }
278         if (!eglChooseConfig(c->base.egl_display, config_attribs,
279                              &c->base.egl_config, 1, &n) || n == 0) {
280                 weston_log("failed to choose config: %d\n", n);
281                 return -1;
282         }
283
284         c->base.egl_context =
285                 eglCreateContext(c->base.egl_display, c->base.egl_config,
286                                  EGL_NO_CONTEXT, context_attribs);
287         if (c->base.egl_context == NULL) {
288                 weston_log("failed to create context\n");
289                 return -1;
290         }
291
292         c->dummy_pbuffer = eglCreatePbufferSurface(c->base.egl_display,
293                                                    c->base.egl_config,
294                                                    pbuffer_attribs);
295         if (c->dummy_pbuffer == NULL) {
296                 weston_log("failed to create dummy pbuffer\n");
297                 return -1;
298         }
299
300         if (!eglMakeCurrent(c->base.egl_display, c->dummy_pbuffer,
301                             c->dummy_pbuffer, c->base.egl_context)) {
302                 weston_log("failed to make context current\n");
303                 return -1;
304         }
305
306         return 0;
307 }
308
309 static void
310 x11_compositor_fini_egl(struct x11_compositor *compositor)
311 {
312         eglMakeCurrent(compositor->base.egl_display,
313                        EGL_NO_SURFACE, EGL_NO_SURFACE,
314                        EGL_NO_CONTEXT);
315
316         eglTerminate(compositor->base.egl_display);
317         eglReleaseThread();
318 }
319
320 static void
321 x11_output_repaint(struct weston_output *output_base,
322                    pixman_region32_t *damage)
323 {
324         struct x11_output *output = (struct x11_output *)output_base;
325         struct x11_compositor *compositor =
326                 (struct x11_compositor *)output->base.compositor;
327         struct weston_surface *surface;
328
329         if (!eglMakeCurrent(compositor->base.egl_display, output->egl_surface,
330                             output->egl_surface,
331                             compositor->base.egl_context)) {
332                 weston_log("failed to make current\n");
333                 return;
334         }
335
336         wl_list_for_each_reverse(surface, &compositor->base.surface_list, link)
337                 weston_surface_draw(surface, &output->base, damage);
338
339         wl_signal_emit(&output->base.frame_signal, output);
340
341         eglSwapBuffers(compositor->base.egl_display, output->egl_surface);
342
343         wl_event_source_timer_update(output->finish_frame_timer, 10);
344 }
345
346 static int
347 finish_frame_handler(void *data)
348 {
349         struct x11_output *output = data;
350         uint32_t msec;
351         struct timeval tv;
352         
353         gettimeofday(&tv, NULL);
354         msec = tv.tv_sec * 1000 + tv.tv_usec / 1000;
355         weston_output_finish_frame(&output->base, msec);
356
357         return 1;
358 }
359
360 static void
361 x11_output_destroy(struct weston_output *output_base)
362 {
363         struct x11_output *output = (struct x11_output *)output_base;
364         struct x11_compositor *compositor =
365                 (struct x11_compositor *)output->base.compositor;
366
367         wl_list_remove(&output->base.link);
368         wl_event_source_remove(output->finish_frame_timer);
369
370         eglDestroySurface(compositor->base.egl_display, output->egl_surface);
371
372         xcb_destroy_window(compositor->conn, output->window);
373
374         weston_output_destroy(&output->base);
375
376         free(output);
377 }
378
379 static void
380 x11_output_set_wm_protocols(struct x11_output *output)
381 {
382         xcb_atom_t list[1];
383         struct x11_compositor *c =
384                 (struct x11_compositor *) output->base.compositor;
385
386         list[0] = c->atom.wm_delete_window;
387         xcb_change_property (c->conn, 
388                              XCB_PROP_MODE_REPLACE,
389                              output->window,
390                              c->atom.wm_protocols,
391                              XCB_ATOM_ATOM,
392                              32,
393                              ARRAY_LENGTH(list),
394                              list);
395 }
396
397 static void
398 x11_output_change_state(struct x11_output *output, int add, xcb_atom_t state)
399 {
400         xcb_client_message_event_t event;
401         struct x11_compositor *c =
402                 (struct x11_compositor *) output->base.compositor;
403         xcb_screen_iterator_t iter;
404
405 #define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
406 #define _NET_WM_STATE_ADD           1    /* add/set property */
407 #define _NET_WM_STATE_TOGGLE        2    /* toggle property  */  
408
409         memset(&event, 0, sizeof event);
410         event.response_type = XCB_CLIENT_MESSAGE;
411         event.format = 32;
412         event.window = output->window;
413         event.type = c->atom.net_wm_state;
414
415         event.data.data32[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
416         event.data.data32[1] = state;
417         event.data.data32[2] = 0;
418         event.data.data32[3] = 0;
419         event.data.data32[4] = 0;
420
421         iter = xcb_setup_roots_iterator(xcb_get_setup(c->conn));
422         xcb_send_event(c->conn, 0, iter.data->root,
423                        XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
424                        XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
425                        (void *) &event);
426 }
427
428
429 struct wm_normal_hints {
430         uint32_t flags;
431         uint32_t pad[4];
432         int32_t min_width, min_height;
433         int32_t max_width, max_height;
434         int32_t width_inc, height_inc;
435         int32_t min_aspect_x, min_aspect_y;
436         int32_t max_aspect_x, max_aspect_y;
437         int32_t base_width, base_height;
438         int32_t win_gravity;
439 };
440
441 #define WM_NORMAL_HINTS_MIN_SIZE        16
442 #define WM_NORMAL_HINTS_MAX_SIZE        32
443
444 static void
445 x11_output_set_icon(struct x11_compositor *c,
446                     struct x11_output *output, const char *filename)
447 {
448         uint32_t *icon;
449         int32_t width, height;
450         pixman_image_t *image;
451
452         image = load_image(filename);
453         if (!image)
454                 return;
455         width = pixman_image_get_width(image);
456         height = pixman_image_get_height(image);
457         icon = malloc(width * height * 4 + 8);
458         if (!icon) {
459                 pixman_image_unref(image);
460                 return;
461         }
462
463         icon[0] = width;
464         icon[1] = height;
465         memcpy(icon + 2, pixman_image_get_data(image), width * height * 4);
466         xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window,
467                             c->atom.net_wm_icon, c->atom.cardinal, 32,
468                             width * height + 2, icon);
469         free(icon);
470         pixman_image_unref(image);
471 }
472
473 static int
474 x11_compositor_create_output(struct x11_compositor *c, int x, int y,
475                              int width, int height, int fullscreen,
476                              int no_input)
477 {
478         static const char name[] = "Weston Compositor";
479         static const char class[] = "weston-1\0Weston Compositor";
480         struct x11_output *output;
481         xcb_screen_iterator_t iter;
482         struct wm_normal_hints normal_hints;
483         struct wl_event_loop *loop;
484         uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
485         uint32_t values[2] = {
486                 XCB_EVENT_MASK_EXPOSURE |
487                 XCB_EVENT_MASK_STRUCTURE_NOTIFY,
488                 0
489         };
490
491         if (!no_input)
492                 values[0] |=
493                         XCB_EVENT_MASK_KEY_PRESS |
494                         XCB_EVENT_MASK_KEY_RELEASE |
495                         XCB_EVENT_MASK_BUTTON_PRESS |
496                         XCB_EVENT_MASK_BUTTON_RELEASE |
497                         XCB_EVENT_MASK_POINTER_MOTION |
498                         XCB_EVENT_MASK_ENTER_WINDOW |
499                         XCB_EVENT_MASK_LEAVE_WINDOW |
500                         XCB_EVENT_MASK_KEYMAP_STATE |
501                         XCB_EVENT_MASK_FOCUS_CHANGE;
502
503         output = malloc(sizeof *output);
504         if (output == NULL)
505                 return -1;
506
507         memset(output, 0, sizeof *output);
508
509         output->mode.flags =
510                 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
511         output->mode.width = width;
512         output->mode.height = height;
513         output->mode.refresh = 60000;
514         wl_list_init(&output->base.mode_list);
515         wl_list_insert(&output->base.mode_list, &output->mode.link);
516
517         output->base.current = &output->mode;
518         output->base.make = "xwayland";
519         output->base.model = "none";
520         weston_output_init(&output->base, &c->base, x, y, width, height,
521                          WL_OUTPUT_FLIPPED);
522
523         values[1] = c->null_cursor;
524         output->window = xcb_generate_id(c->conn);
525         iter = xcb_setup_roots_iterator(xcb_get_setup(c->conn));
526         xcb_create_window(c->conn,
527                           XCB_COPY_FROM_PARENT,
528                           output->window,
529                           iter.data->root,
530                           0, 0,
531                           width, height,
532                           0,
533                           XCB_WINDOW_CLASS_INPUT_OUTPUT,
534                           iter.data->root_visual,
535                           mask, values);
536
537         /* Don't resize me. */
538         memset(&normal_hints, 0, sizeof normal_hints);
539         normal_hints.flags =
540                 WM_NORMAL_HINTS_MAX_SIZE | WM_NORMAL_HINTS_MIN_SIZE;
541         normal_hints.min_width = width;
542         normal_hints.min_height = height;
543         normal_hints.max_width = width;
544         normal_hints.max_height = height;
545         xcb_change_property (c->conn, XCB_PROP_MODE_REPLACE, output->window,
546                              c->atom.wm_normal_hints,
547                              c->atom.wm_size_hints, 32,
548                              sizeof normal_hints / 4,
549                              (uint8_t *) &normal_hints);
550
551         /* Set window name.  Don't bother with non-EWMH WMs. */
552         xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window,
553                             c->atom.net_wm_name, c->atom.utf8_string, 8,
554                             strlen(name), name);
555         xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window,
556                             c->atom.wm_class, c->atom.string, 8,
557                             sizeof class, class);
558
559         x11_output_set_icon(c, output, DATADIR "/weston/wayland.png");
560
561         xcb_map_window(c->conn, output->window);
562
563         x11_output_set_wm_protocols(output);
564
565         if (fullscreen)
566                 x11_output_change_state(output, 1,
567                                         c->atom.net_wm_state_fullscreen);
568
569         output->egl_surface = 
570                 eglCreateWindowSurface(c->base.egl_display, c->base.egl_config,
571                                        output->window, NULL);
572         if (!output->egl_surface) {
573                 weston_log("failed to create window surface\n");
574                 return -1;
575         }
576         if (!eglMakeCurrent(c->base.egl_display, output->egl_surface,
577                             output->egl_surface, c->base.egl_context)) {
578                 weston_log("failed to make surface current\n");
579                 return -1;
580         }
581
582         loop = wl_display_get_event_loop(c->base.wl_display);
583         output->finish_frame_timer =
584                 wl_event_loop_add_timer(loop, finish_frame_handler, output);
585
586         output->base.origin = output->base.current;
587         output->base.repaint = x11_output_repaint;
588         output->base.destroy = x11_output_destroy;
589         output->base.assign_planes = NULL;
590         output->base.set_backlight = NULL;
591         output->base.set_dpms = NULL;
592         output->base.switch_mode = NULL;
593
594         wl_list_insert(c->base.output_list.prev, &output->base.link);
595
596         weston_log("x11 output %dx%d, window id %d\n",
597                    width, height, output->window);
598
599         return 0;
600 }
601
602 static struct x11_output *
603 x11_compositor_find_output(struct x11_compositor *c, xcb_window_t window)
604 {
605         struct x11_output *output;
606
607         wl_list_for_each(output, &c->base.output_list, base.link) {
608                 if (output->window == window)
609                         return output;
610         }
611
612         return NULL;
613 }
614
615 static uint32_t
616 get_xkb_mod_mask(struct x11_compositor *c, uint32_t in)
617 {
618         struct weston_xkb_info *info = &c->base.seat->xkb_info;
619         uint32_t ret = 0;
620
621         if ((in & ShiftMask) && info->shift_mod != XKB_MOD_INVALID)
622                 ret |= (1 << info->shift_mod);
623         if ((in & LockMask) && info->caps_mod != XKB_MOD_INVALID)
624                 ret |= (1 << info->caps_mod);
625         if ((in & ControlMask) && info->ctrl_mod != XKB_MOD_INVALID)
626                 ret |= (1 << info->ctrl_mod);
627         if ((in & Mod1Mask) && info->alt_mod != XKB_MOD_INVALID)
628                 ret |= (1 << info->alt_mod);
629         if ((in & Mod2Mask) && info->mod2_mod != XKB_MOD_INVALID)
630                 ret |= (1 << info->mod2_mod);
631         if ((in & Mod3Mask) && info->mod3_mod != XKB_MOD_INVALID)
632                 ret |= (1 << info->mod3_mod);
633         if ((in & Mod4Mask) && info->super_mod != XKB_MOD_INVALID)
634                 ret |= (1 << info->super_mod);
635         if ((in & Mod5Mask) && info->mod5_mod != XKB_MOD_INVALID)
636                 ret |= (1 << info->mod5_mod);
637
638         return ret;
639 }
640
641 #ifdef HAVE_XCB_XKB
642 static void
643 update_xkb_state(struct x11_compositor *c, xcb_xkb_state_notify_event_t *state)
644 {
645         struct weston_compositor *ec = &c->base;
646         struct wl_seat *seat = &ec->seat->seat;
647
648         xkb_state_update_mask(c->base.seat->xkb_state.state,
649                               get_xkb_mod_mask(c, state->baseMods),
650                               get_xkb_mod_mask(c, state->latchedMods),
651                               get_xkb_mod_mask(c, state->lockedMods),
652                               0,
653                               0,
654                               state->group);
655
656         notify_modifiers(seat, wl_display_next_serial(c->base.wl_display));
657 }
658 #endif
659
660 /**
661  * This is monumentally unpleasant.  If we don't have XCB-XKB bindings,
662  * the best we can do (given that XCB also lacks XI2 support), is to take
663  * the state from the core key events.  Unfortunately that only gives us
664  * the effective (i.e. union of depressed/latched/locked) state, and we
665  * need the granularity.
666  *
667  * So we still update the state with every key event we see, but also use
668  * the state field from X11 events as a mask so we don't get any stuck
669  * modifiers.
670  */
671 static void
672 update_xkb_state_from_core(struct x11_compositor *c, uint16_t x11_mask)
673 {
674         uint32_t mask = get_xkb_mod_mask(c, x11_mask);
675         struct wl_keyboard *keyboard = &c->base.seat->keyboard;
676
677         xkb_state_update_mask(c->base.seat->xkb_state.state,
678                               keyboard->modifiers.mods_depressed & mask,
679                               keyboard->modifiers.mods_latched & mask,
680                               keyboard->modifiers.mods_locked & mask,
681                               0,
682                               0,
683                               (x11_mask >> 13) & 3);
684         notify_modifiers(&c->base.seat->seat,
685                          wl_display_next_serial(c->base.wl_display));
686 }
687
688 static void
689 x11_compositor_deliver_button_event(struct x11_compositor *c,
690                                     xcb_generic_event_t *event, int state)
691 {
692         xcb_button_press_event_t *button_event =
693                 (xcb_button_press_event_t *) event;
694         uint32_t button;
695
696         if (!c->has_xkb)
697                 update_xkb_state_from_core(c, button_event->state);
698
699         switch (button_event->detail) {
700         default:
701                 button = button_event->detail + BTN_LEFT - 1;
702                 break;
703         case 2:
704                 button = BTN_MIDDLE;
705                 break;
706         case 3:
707                 button = BTN_RIGHT;
708                 break;
709         case 4:
710                 if (state)
711                         notify_axis(&c->base.seat->seat,
712                                       weston_compositor_get_time(),
713                                       WL_POINTER_AXIS_VERTICAL_SCROLL,
714                                       wl_fixed_from_int(1));
715                 return;
716         case 5:
717                 if (state)
718                         notify_axis(&c->base.seat->seat,
719                                       weston_compositor_get_time(),
720                                       WL_POINTER_AXIS_VERTICAL_SCROLL,
721                                       wl_fixed_from_int(-1));
722                 return;
723         case 6:
724                 if (state)
725                         notify_axis(&c->base.seat->seat,
726                                       weston_compositor_get_time(),
727                                       WL_POINTER_AXIS_HORIZONTAL_SCROLL,
728                                       wl_fixed_from_int(1));
729                 return;
730         case 7:
731                 if (state)
732                         notify_axis(&c->base.seat->seat,
733                                       weston_compositor_get_time(),
734                                       WL_POINTER_AXIS_HORIZONTAL_SCROLL,
735                                       wl_fixed_from_int(-1));
736                 return;
737         }
738
739         notify_button(&c->base.seat->seat,
740                       weston_compositor_get_time(), button,
741                       state ? WL_POINTER_BUTTON_STATE_PRESSED :
742                               WL_POINTER_BUTTON_STATE_RELEASED);
743 }
744
745 static int
746 x11_compositor_next_event(struct x11_compositor *c,
747                           xcb_generic_event_t **event, uint32_t mask)
748 {
749         if (mask & WL_EVENT_READABLE) {
750                 *event = xcb_poll_for_event(c->conn);
751         } else {
752 #ifdef HAVE_XCB_POLL_FOR_QUEUED_EVENT
753                 *event = xcb_poll_for_queued_event(c->conn);
754 #else
755                 *event = xcb_poll_for_event(c->conn);
756 #endif
757         }
758
759         return *event != NULL;
760 }
761
762 static int
763 x11_compositor_handle_event(int fd, uint32_t mask, void *data)
764 {
765         struct x11_compositor *c = data;
766         struct x11_output *output;
767         xcb_generic_event_t *event, *prev;
768         xcb_client_message_event_t *client_message;
769         xcb_motion_notify_event_t *motion_notify;
770         xcb_enter_notify_event_t *enter_notify;
771         xcb_key_press_event_t *key_press, *key_release;
772         xcb_keymap_notify_event_t *keymap_notify;
773         xcb_focus_in_event_t *focus_in;
774         xcb_expose_event_t *expose;
775         xcb_atom_t atom;
776         uint32_t *k;
777         uint32_t i, set;
778         wl_fixed_t x, y;
779         int count;
780
781         prev = NULL;
782         count = 0;
783         while (x11_compositor_next_event(c, &event, mask)) {
784                 switch (prev ? prev->response_type & ~0x80 : 0x80) {
785                 case XCB_KEY_RELEASE:
786                         /* Suppress key repeat events; this is only used if we
787                          * don't have XCB XKB support. */
788                         key_release = (xcb_key_press_event_t *) prev;
789                         key_press = (xcb_key_press_event_t *) event;
790                         if ((event->response_type & ~0x80) == XCB_KEY_PRESS &&
791                             key_release->time == key_press->time &&
792                             key_release->detail == key_press->detail) {
793                                 /* Don't deliver the held key release
794                                  * event or the new key press event. */
795                                 free(event);
796                                 free(prev);
797                                 prev = NULL;
798                                 continue;
799                         } else {
800                                 /* Deliver the held key release now
801                                  * and fall through and handle the new
802                                  * event below. */
803                                 update_xkb_state_from_core(c, key_release->state);
804                                 notify_key(&c->base.seat->seat,
805                                            weston_compositor_get_time(),
806                                            key_release->detail - 8,
807                                            WL_KEYBOARD_KEY_STATE_RELEASED,
808                                            STATE_UPDATE_AUTOMATIC);
809                                 free(prev);
810                                 prev = NULL;
811                                 break;
812                         }
813
814                 case XCB_FOCUS_IN:
815                         /* assert event is keymap_notify */
816                         focus_in = (xcb_focus_in_event_t *) prev;
817                         keymap_notify = (xcb_keymap_notify_event_t *) event;
818                         c->keys.size = 0;
819                         for (i = 0; i < ARRAY_LENGTH(keymap_notify->keys) * 8; i++) {
820                                 set = keymap_notify->keys[i >> 3] &
821                                         (1 << (i & 7));
822                                 if (set) {
823                                         k = wl_array_add(&c->keys, sizeof *k);
824                                         *k = i;
825                                 }
826                         }
827
828                         output = x11_compositor_find_output(c, focus_in->event);
829                         /* Unfortunately the state only comes with the enter
830                          * event, rather than with the focus event.  I'm not
831                          * sure of the exact semantics around it and whether
832                          * we can ensure that we get both? */
833                         notify_keyboard_focus_in(&c->base.seat->seat, &c->keys,
834                                                  STATE_UPDATE_AUTOMATIC);
835
836                         free(prev);
837                         prev = NULL;
838                         break;
839
840                 default:
841                         /* No previous event held */
842                         break;
843                 }
844
845                 switch (event->response_type & ~0x80) {
846                 case XCB_KEY_PRESS:
847                         key_press = (xcb_key_press_event_t *) event;
848                         if (!c->has_xkb)
849                                 update_xkb_state_from_core(c, key_press->state);
850                         notify_key(&c->base.seat->seat,
851                                    weston_compositor_get_time(),
852                                    key_press->detail - 8,
853                                    WL_KEYBOARD_KEY_STATE_PRESSED,
854                                    c->has_xkb ? STATE_UPDATE_NONE :
855                                                 STATE_UPDATE_AUTOMATIC);
856                         break;
857                 case XCB_KEY_RELEASE:
858                         /* If we don't have XKB, we need to use the lame
859                          * autorepeat detection above. */
860                         if (!c->has_xkb) {
861                                 prev = event;
862                                 break;
863                         }
864                         key_release = (xcb_key_press_event_t *) event;
865                         notify_key(&c->base.seat->seat,
866                                    weston_compositor_get_time(),
867                                    key_release->detail - 8,
868                                    WL_KEYBOARD_KEY_STATE_RELEASED,
869                                    STATE_UPDATE_NONE);
870                         break;
871                 case XCB_BUTTON_PRESS:
872                         x11_compositor_deliver_button_event(c, event, 1);
873                         break;
874                 case XCB_BUTTON_RELEASE:
875                         x11_compositor_deliver_button_event(c, event, 0);
876                         break;
877                 case XCB_MOTION_NOTIFY:
878                         motion_notify = (xcb_motion_notify_event_t *) event;
879                         if (!c->has_xkb)
880                                 update_xkb_state_from_core(c, motion_notify->state);
881                         output = x11_compositor_find_output(c, motion_notify->event);
882                         x = wl_fixed_from_int(output->base.x + motion_notify->event_x);
883                         y = wl_fixed_from_int(output->base.y + motion_notify->event_y);
884                         notify_motion(&c->base.seat->seat,
885                                       weston_compositor_get_time(), x, y);
886                         break;
887
888                 case XCB_EXPOSE:
889                         expose = (xcb_expose_event_t *) event;
890                         output = x11_compositor_find_output(c, expose->window);
891                         weston_output_schedule_repaint(&output->base);
892                         break;
893
894                 case XCB_ENTER_NOTIFY:
895                         enter_notify = (xcb_enter_notify_event_t *) event;
896                         if (enter_notify->state >= Button1Mask)
897                                 break;
898                         if (!c->has_xkb)
899                                 update_xkb_state_from_core(c, enter_notify->state);
900                         output = x11_compositor_find_output(c, enter_notify->event);
901                         x = wl_fixed_from_int(output->base.x + enter_notify->event_x);
902                         y = wl_fixed_from_int(output->base.y + enter_notify->event_y);
903
904                         notify_pointer_focus(&c->base.seat->seat,
905                                              &output->base, x, y);
906                         break;
907
908                 case XCB_LEAVE_NOTIFY:
909                         enter_notify = (xcb_enter_notify_event_t *) event;
910                         if (enter_notify->state >= Button1Mask)
911                                 break;
912                         if (!c->has_xkb)
913                                 update_xkb_state_from_core(c, enter_notify->state);
914                         output = x11_compositor_find_output(c, enter_notify->event);
915                         notify_pointer_focus(&c->base.seat->seat, NULL, 0, 0);
916                         break;
917
918                 case XCB_CLIENT_MESSAGE:
919                         client_message = (xcb_client_message_event_t *) event;
920                         atom = client_message->data.data32[0];
921                         if (atom == c->atom.wm_delete_window)
922                                 wl_display_terminate(c->base.wl_display);
923                         break;
924
925                 case XCB_FOCUS_IN:
926                         focus_in = (xcb_focus_in_event_t *) event;
927                         if (focus_in->mode == XCB_NOTIFY_MODE_WHILE_GRABBED)
928                                 break;
929
930                         prev = event;
931                         break;
932
933                 case XCB_FOCUS_OUT:
934                         focus_in = (xcb_focus_in_event_t *) event;
935                         if (focus_in->mode == XCB_NOTIFY_MODE_WHILE_GRABBED ||
936                             focus_in->mode == XCB_NOTIFY_MODE_UNGRAB)
937                                 break;
938                         notify_keyboard_focus_out(&c->base.seat->seat);
939                         break;
940
941                 default:
942                         break;
943                 }
944
945 #ifdef HAVE_XCB_XKB
946                 if (c->has_xkb &&
947                     (event->response_type & ~0x80) == c->xkb_event_base) {
948                         xcb_xkb_state_notify_event_t *state =
949                                 (xcb_xkb_state_notify_event_t *) event;
950                         if (state->xkbType == XCB_XKB_STATE_NOTIFY)
951                                 update_xkb_state(c, state);
952                 }
953 #endif
954
955                 count++;
956                 if (prev != event)
957                         free (event);
958         }
959
960         switch (prev ? prev->response_type & ~0x80 : 0x80) {
961         case XCB_KEY_RELEASE:
962                 key_release = (xcb_key_press_event_t *) prev;
963                 update_xkb_state_from_core(c, key_release->state);
964                 notify_key(&c->base.seat->seat,
965                            weston_compositor_get_time(),
966                            key_release->detail - 8,
967                            WL_KEYBOARD_KEY_STATE_RELEASED,
968                            STATE_UPDATE_AUTOMATIC);
969                 free(prev);
970                 prev = NULL;
971                 break;
972         default:
973                 break;
974         }
975
976         return count;
977 }
978
979 #define F(field) offsetof(struct x11_compositor, field)
980
981 static void
982 x11_compositor_get_resources(struct x11_compositor *c)
983 {
984         static const struct { const char *name; int offset; } atoms[] = {
985                 { "WM_PROTOCOLS",       F(atom.wm_protocols) },
986                 { "WM_NORMAL_HINTS",    F(atom.wm_normal_hints) },
987                 { "WM_SIZE_HINTS",      F(atom.wm_size_hints) },
988                 { "WM_DELETE_WINDOW",   F(atom.wm_delete_window) },
989                 { "WM_CLASS",           F(atom.wm_class) },
990                 { "_NET_WM_NAME",       F(atom.net_wm_name) },
991                 { "_NET_WM_ICON",       F(atom.net_wm_icon) },
992                 { "_NET_WM_STATE",      F(atom.net_wm_state) },
993                 { "_NET_WM_STATE_FULLSCREEN", F(atom.net_wm_state_fullscreen) },
994                 { "STRING",             F(atom.string) },
995                 { "UTF8_STRING",        F(atom.utf8_string) },
996                 { "CARDINAL",           F(atom.cardinal) },
997                 { "_XKB_RULES_NAMES",   F(atom.xkb_names) },
998         };
999
1000         xcb_intern_atom_cookie_t cookies[ARRAY_LENGTH(atoms)];
1001         xcb_intern_atom_reply_t *reply;
1002         xcb_pixmap_t pixmap;
1003         xcb_gc_t gc;
1004         unsigned int i;
1005         uint8_t data[] = { 0, 0, 0, 0 };
1006
1007         for (i = 0; i < ARRAY_LENGTH(atoms); i++)
1008                 cookies[i] = xcb_intern_atom (c->conn, 0,
1009                                               strlen(atoms[i].name),
1010                                               atoms[i].name);
1011
1012         for (i = 0; i < ARRAY_LENGTH(atoms); i++) {
1013                 reply = xcb_intern_atom_reply (c->conn, cookies[i], NULL);
1014                 *(xcb_atom_t *) ((char *) c + atoms[i].offset) = reply->atom;
1015                 free(reply);
1016         }
1017
1018         pixmap = xcb_generate_id(c->conn);
1019         gc = xcb_generate_id(c->conn);
1020         xcb_create_pixmap(c->conn, 1, pixmap, c->screen->root, 1, 1);
1021         xcb_create_gc(c->conn, gc, pixmap, 0, NULL);
1022         xcb_put_image(c->conn, XCB_IMAGE_FORMAT_XY_PIXMAP,
1023                       pixmap, gc, 1, 1, 0, 0, 0, 32, sizeof data, data);
1024         c->null_cursor = xcb_generate_id(c->conn);
1025         xcb_create_cursor (c->conn, c->null_cursor,
1026                            pixmap, pixmap, 0, 0, 0,  0, 0, 0,  1, 1);
1027         xcb_free_gc(c->conn, gc);
1028         xcb_free_pixmap(c->conn, pixmap);
1029 }
1030
1031 static void
1032 x11_destroy(struct weston_compositor *ec)
1033 {
1034         struct x11_compositor *compositor = (struct x11_compositor *)ec;
1035
1036         wl_event_source_remove(compositor->xcb_source);
1037         x11_input_destroy(compositor);
1038
1039         weston_compositor_shutdown(ec); /* destroys outputs, too */
1040
1041         x11_compositor_fini_egl(compositor);
1042
1043         XCloseDisplay(compositor->dpy);
1044         free(ec);
1045 }
1046
1047 static struct weston_compositor *
1048 x11_compositor_create(struct wl_display *display,
1049                       int width, int height, int count, int fullscreen,
1050                       int no_input,
1051                       int argc, char *argv[], const char *config_file)
1052 {
1053         struct x11_compositor *c;
1054         xcb_screen_iterator_t s;
1055         int i, x;
1056
1057         weston_log("initializing x11 backend\n");
1058
1059         c = malloc(sizeof *c);
1060         if (c == NULL)
1061                 return NULL;
1062
1063         memset(c, 0, sizeof *c);
1064
1065         if (weston_compositor_init(&c->base, display, argc, argv,
1066                                    config_file) < 0)
1067                 goto err_free;
1068
1069         c->dpy = XOpenDisplay(NULL);
1070         if (c->dpy == NULL)
1071                 goto err_free;
1072
1073         c->conn = XGetXCBConnection(c->dpy);
1074         XSetEventQueueOwner(c->dpy, XCBOwnsEventQueue);
1075
1076         if (xcb_connection_has_error(c->conn))
1077                 goto err_xdisplay;
1078
1079         s = xcb_setup_roots_iterator(xcb_get_setup(c->conn));
1080         c->screen = s.data;
1081         wl_array_init(&c->keys);
1082
1083         x11_compositor_get_resources(c);
1084
1085         c->base.wl_display = display;
1086         if (x11_compositor_init_egl(c) < 0)
1087                 goto err_xdisplay;
1088
1089         c->base.destroy = x11_destroy;
1090
1091         if (weston_compositor_init_gl(&c->base) < 0)
1092                 goto err_egl;
1093
1094         if (x11_input_create(c, no_input) < 0)
1095                 goto err_egl;
1096
1097         for (i = 0, x = 0; i < count; i++) {
1098                 if (x11_compositor_create_output(c, x, 0, width, height,
1099                                                  fullscreen, no_input) < 0)
1100                         goto err_x11_input;
1101                 x += width;
1102         }
1103
1104         c->xcb_source =
1105                 wl_event_loop_add_fd(c->base.input_loop,
1106                                      xcb_get_file_descriptor(c->conn),
1107                                      WL_EVENT_READABLE,
1108                                      x11_compositor_handle_event, c);
1109         wl_event_source_check(c->xcb_source);
1110
1111         return &c->base;
1112
1113 err_x11_input:
1114         x11_input_destroy(c);
1115 err_egl:
1116         x11_compositor_fini_egl(c);
1117 err_xdisplay:
1118         XCloseDisplay(c->dpy);
1119 err_free:
1120         free(c);
1121         return NULL;
1122 }
1123
1124 WL_EXPORT struct weston_compositor *
1125 backend_init(struct wl_display *display, int argc, char *argv[],
1126              const char *config_file)
1127 {
1128         int width = 1024, height = 640, fullscreen = 0, count = 1;
1129         int no_input = 0;
1130
1131         const struct weston_option x11_options[] = {
1132                 { WESTON_OPTION_INTEGER, "width", 0, &width },
1133                 { WESTON_OPTION_INTEGER, "height", 0, &height },
1134                 { WESTON_OPTION_BOOLEAN, "fullscreen", 0, &fullscreen },
1135                 { WESTON_OPTION_INTEGER, "output-count", 0, &count },
1136                 { WESTON_OPTION_BOOLEAN, "no-input", 0, &no_input },
1137         };
1138
1139         parse_options(x11_options, ARRAY_LENGTH(x11_options), argc, argv);
1140
1141         return x11_compositor_create(display,
1142                                      width, height, count, fullscreen,
1143                                      no_input,
1144                                      argc, argv, config_file);
1145 }