update to 1.10.4
[profile/ivi/clutter.git] / clutter / x11 / clutter-backend-x11.c
1 /* Clutter.
2  * An OpenGL based 'interactive canvas' library.
3  * Authored By Matthew Allum  <mallum@openedhand.com>
4  * Copyright (C) 2006-2007 OpenedHand
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <glib/gi18n-lib.h>
27
28 #include <string.h>
29
30 #include <unistd.h>
31
32 #include <sys/ioctl.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35
36 #include <fcntl.h>
37
38 #include <errno.h>
39
40 #include "clutter-backend-x11.h"
41 #include "clutter-device-manager-core-x11.h"
42 #include "clutter-device-manager-xi2.h"
43 #include "clutter-settings-x11.h"
44 #include "clutter-stage-x11.h"
45 #include "clutter-x11.h"
46
47 #include "xsettings/xsettings-common.h"
48
49 #if HAVE_XCOMPOSITE
50 #include <X11/extensions/Xcomposite.h>
51 #endif
52
53 #if HAVE_XINPUT
54 #include <X11/extensions/XInput.h>
55 #endif
56
57 #if HAVE_XINPUT_2
58 #include <X11/extensions/XInput2.h>
59 #endif
60
61 #include <cogl/cogl.h>
62 #include <cogl/cogl-xlib.h>
63
64 #include "clutter-backend.h"
65 #include "clutter-debug.h"
66 #include "clutter-device-manager-private.h"
67 #include "clutter-event-private.h"
68 #include "clutter-main.h"
69 #include "clutter-private.h"
70
71 #define clutter_backend_x11_get_type    _clutter_backend_x11_get_type
72
73 G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
74
75 /* atoms; remember to add the code that assigns the atom value to
76  * the member of the ClutterBackendX11 structure if you add an
77  * atom name here. do not change the order!
78  */
79 static const gchar *atom_names[] = {
80   "_NET_WM_PID",
81   "_NET_WM_PING",
82   "_NET_WM_STATE",
83   "_NET_WM_STATE_FULLSCREEN",
84   "_NET_WM_USER_TIME",
85   "WM_PROTOCOLS",
86   "WM_DELETE_WINDOW",
87   "_XEMBED",
88   "_XEMBED_INFO",
89   "_NET_WM_NAME",
90   "UTF8_STRING",
91 };
92
93 #define N_ATOM_NAMES G_N_ELEMENTS (atom_names)
94
95 /* various flags corresponding to pre init setup calls */
96 static gboolean _no_xevent_retrieval = FALSE;
97 static gboolean clutter_enable_xinput = FALSE;
98 static gboolean clutter_enable_argb = FALSE;
99 static Display  *_foreign_dpy = NULL;
100
101 /* options */
102 static gchar *clutter_display_name = NULL;
103 static gint clutter_screen = -1;
104 static gboolean clutter_synchronise = FALSE;
105
106 /* X error trap */
107 static int TrappedErrorCode = 0;
108 static int (* old_error_handler) (Display *, XErrorEvent *);
109
110 static ClutterX11FilterReturn
111 xsettings_filter (XEvent       *xevent,
112                   ClutterEvent *event,
113                   gpointer      data)
114 {
115   ClutterBackendX11 *backend_x11 = data;
116
117   _clutter_xsettings_client_process_event (backend_x11->xsettings, xevent);
118
119   /* we always want the rest of the stack to get XSettings events, even
120    * if Clutter already handled them
121    */
122
123   return CLUTTER_X11_FILTER_CONTINUE;
124 }
125
126 static ClutterX11FilterReturn
127 cogl_xlib_filter (XEvent       *xevent,
128                   ClutterEvent *event,
129                   gpointer      data)
130 {
131   ClutterX11FilterReturn retval;
132   CoglFilterReturn ret;
133
134   ret = cogl_xlib_handle_event (xevent);
135   switch (ret)
136     {
137     case COGL_FILTER_REMOVE:
138       retval = CLUTTER_X11_FILTER_REMOVE;
139       break;
140
141     case COGL_FILTER_CONTINUE:
142     default:
143       retval = CLUTTER_X11_FILTER_CONTINUE;
144       break;
145     }
146
147   return retval;
148 }
149
150 static void
151 clutter_backend_x11_xsettings_notify (const char       *name,
152                                       XSettingsAction   action,
153                                       XSettingsSetting *setting,
154                                       void             *cb_data)
155 {
156   ClutterSettings *settings = clutter_settings_get_default ();
157   gint i;
158
159   if (name == NULL || *name == '\0')
160     return;
161
162   if (setting == NULL)
163     return;
164
165   g_object_freeze_notify (G_OBJECT (settings));
166
167   for (i = 0; i < _n_clutter_settings_map; i++)
168     {
169       if (g_strcmp0 (name, CLUTTER_SETTING_X11_NAME (i)) == 0)
170         {
171           GValue value = { 0, };
172
173           switch (setting->type)
174             {
175             case XSETTINGS_TYPE_INT:
176               g_value_init (&value, G_TYPE_INT);
177               g_value_set_int (&value, setting->data.v_int);
178               break;
179
180             case XSETTINGS_TYPE_STRING:
181               g_value_init (&value, G_TYPE_STRING);
182               g_value_set_string (&value, setting->data.v_string);
183               break;
184
185             case XSETTINGS_TYPE_COLOR:
186               {
187                 ClutterColor color;
188
189                 color.red   = (guint8) ((float) setting->data.v_color.red
190                             / 65535.0 * 255);
191                 color.green = (guint8) ((float) setting->data.v_color.green
192                             / 65535.0 * 255);
193                 color.blue  = (guint8) ((float) setting->data.v_color.blue
194                             / 65535.0 * 255);
195                 color.alpha = (guint8) ((float) setting->data.v_color.alpha
196                             / 65535.0 * 255);
197
198                 g_value_init (&value, G_TYPE_BOXED);
199                 clutter_value_set_color (&value, &color);
200               }
201               break;
202             }
203
204           CLUTTER_NOTE (BACKEND,
205                         "Mapping XSETTING '%s' to 'ClutterSettings:%s'",
206                         CLUTTER_SETTING_X11_NAME (i),
207                         CLUTTER_SETTING_PROPERTY (i));
208
209           g_object_set_property (G_OBJECT (settings),
210                                  CLUTTER_SETTING_PROPERTY (i),
211                                  &value);
212
213           g_value_unset (&value);
214
215           break;
216         }
217     }
218
219   g_object_thaw_notify (G_OBJECT (settings));
220 }
221
222 static void
223 clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
224 {
225   if (G_UNLIKELY (backend_x11->device_manager == NULL))
226     {
227       ClutterEventTranslator *translator;
228       ClutterBackend *backend;
229
230 #if defined(HAVE_XINPUT) || defined(HAVE_XINPUT_2)
231       if (clutter_enable_xinput)
232         {
233           int event_base, first_event, first_error;
234
235           if (XQueryExtension (backend_x11->xdpy, "XInputExtension",
236                                &event_base,
237                                &first_event,
238                                &first_error))
239             {
240 #ifdef HAVE_XINPUT_2
241               int major = 2;
242
243 #ifdef HAVE_XINPUT_2_2
244               int minor = 2;
245 #else
246               int minor = 0;
247 #endif /* HAVE_XINPUT_2_2 */
248
249               if (XIQueryVersion (backend_x11->xdpy, &major, &minor) != BadRequest)
250                 {
251                   CLUTTER_NOTE (BACKEND, "Creating XI2 device manager");
252                   backend_x11->has_xinput = TRUE;
253                   backend_x11->device_manager =
254                     g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_XI2,
255                                   "backend", backend_x11,
256                                   "opcode", event_base,
257                                   NULL);
258
259                   backend_x11->xi_minor = minor;
260                 }
261               else
262 #endif /* HAVE_XINPUT_2 */
263                 {
264                   CLUTTER_NOTE (BACKEND, "Creating Core+XI device manager");
265                   backend_x11->has_xinput = TRUE;
266                   backend_x11->device_manager =
267                     g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11,
268                                   "backend", backend_x11,
269                                   "event-base", first_event,
270                                   NULL);
271
272                   backend_x11->xi_minor = -1;
273                 }
274             }
275         }
276       else
277 #endif /* HAVE_XINPUT || HAVE_XINPUT_2 */
278         {
279           CLUTTER_NOTE (BACKEND, "Creating Core device manager");
280           backend_x11->has_xinput = FALSE;
281           backend_x11->device_manager =
282             g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11,
283                           "backend", backend_x11,
284                           NULL);
285
286           backend_x11->xi_minor = -1;
287         }
288
289       backend = CLUTTER_BACKEND (backend_x11);
290       backend->device_manager = backend_x11->device_manager;
291
292       translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->device_manager);
293       _clutter_backend_add_event_translator (backend, translator);
294     }
295 }
296
297 static void
298 clutter_backend_x11_create_keymap (ClutterBackendX11 *backend_x11)
299 {
300   if (backend_x11->keymap == NULL)
301     {
302       ClutterEventTranslator *translator;
303       ClutterBackend *backend;
304
305       backend_x11->keymap =
306         g_object_new (CLUTTER_TYPE_KEYMAP_X11,
307                       "backend", backend_x11,
308                       NULL);
309
310       backend = CLUTTER_BACKEND (backend_x11);
311       translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->keymap);
312       _clutter_backend_add_event_translator (backend, translator);
313     }
314 }
315
316 static gboolean
317 clutter_backend_x11_pre_parse (ClutterBackend  *backend,
318                                GError         **error)
319 {
320   const gchar *env_string;
321
322   /* we don't fail here if DISPLAY is not set, as the user
323    * might pass the --display command line switch
324    */
325   env_string = g_getenv ("DISPLAY");
326   if (env_string)
327     {
328       clutter_display_name = g_strdup (env_string);
329       env_string = NULL;
330     }
331
332   env_string = g_getenv ("CLUTTER_DISABLE_ARGB_VISUAL");
333   if (env_string)
334     {
335       clutter_enable_argb = FALSE;
336       env_string = NULL;
337     }
338
339   env_string = g_getenv ("CLUTTER_ENABLE_XINPUT");
340   if (env_string)
341     {
342       clutter_enable_xinput = TRUE;
343       env_string = NULL;
344     }
345
346   return TRUE;
347 }
348
349 static gboolean
350 clutter_backend_x11_post_parse (ClutterBackend  *backend,
351                                 GError         **error)
352 {
353   ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
354   ClutterSettings *settings;
355   Atom atoms[N_ATOM_NAMES];
356   double dpi;
357
358   if (_foreign_dpy)
359     backend_x11->xdpy = _foreign_dpy;
360
361   /* Only open connection if not already set by prior call to
362    * clutter_x11_set_display()
363    */
364   if (backend_x11->xdpy == NULL)
365     {
366       if (clutter_display_name != NULL &&
367           *clutter_display_name != '\0')
368         {
369           CLUTTER_NOTE (BACKEND, "XOpenDisplay on '%s'", clutter_display_name);
370
371           backend_x11->xdpy = XOpenDisplay (clutter_display_name);
372           if (backend_x11->xdpy == NULL)
373             {
374               g_set_error (error, CLUTTER_INIT_ERROR,
375                            CLUTTER_INIT_ERROR_BACKEND,
376                            "Unable to open display '%s'",
377                            clutter_display_name);
378               return FALSE;
379             }
380         }
381       else
382         {
383           g_set_error_literal (error, CLUTTER_INIT_ERROR,
384                                CLUTTER_INIT_ERROR_BACKEND,
385                                "Unable to open display. You have to set the "
386                                "DISPLAY environment variable, or use the "
387                                "--display command line argument");
388           return FALSE;
389         }
390     }
391
392   g_assert (backend_x11->xdpy != NULL);
393
394   CLUTTER_NOTE (BACKEND, "Getting the X screen");
395
396   settings = clutter_settings_get_default ();
397
398   /* Cogl needs to know the Xlib display connection for
399      CoglTexturePixmapX11 */
400   cogl_xlib_set_display (backend_x11->xdpy);
401
402   /* add event filter for Cogl events */
403   clutter_x11_add_filter (cogl_xlib_filter, NULL);
404
405   if (clutter_screen == -1)
406     backend_x11->xscreen = DefaultScreenOfDisplay (backend_x11->xdpy);
407   else
408     backend_x11->xscreen = ScreenOfDisplay (backend_x11->xdpy,
409                                             clutter_screen);
410
411   backend_x11->xscreen_num = XScreenNumberOfScreen (backend_x11->xscreen);
412   backend_x11->xscreen_width = WidthOfScreen (backend_x11->xscreen);
413   backend_x11->xscreen_height = HeightOfScreen (backend_x11->xscreen);
414
415   backend_x11->xwin_root = RootWindow (backend_x11->xdpy,
416                                        backend_x11->xscreen_num);
417
418   backend_x11->display_name = g_strdup (clutter_display_name);
419
420   dpi = (((double) DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num) * 25.4)
421       / (double) DisplayHeightMM (backend_x11->xdpy, backend_x11->xscreen_num));
422
423   g_object_set (settings, "font-dpi", (int) dpi * 1024, NULL);
424
425   /* create XSETTINGS client */
426   backend_x11->xsettings =
427     _clutter_xsettings_client_new (backend_x11->xdpy,
428                                    backend_x11->xscreen_num,
429                                    clutter_backend_x11_xsettings_notify,
430                                    NULL,
431                                    backend_x11);
432
433   /* add event filter for XSETTINGS events */
434   clutter_x11_add_filter (xsettings_filter, backend_x11);
435
436   if (clutter_synchronise)
437     XSynchronize (backend_x11->xdpy, True);
438
439   XInternAtoms (backend_x11->xdpy,
440                 (char **) atom_names, N_ATOM_NAMES,
441                 False, atoms);
442
443   backend_x11->atom_NET_WM_PID = atoms[0];
444   backend_x11->atom_NET_WM_PING = atoms[1];
445   backend_x11->atom_NET_WM_STATE = atoms[2];
446   backend_x11->atom_NET_WM_STATE_FULLSCREEN = atoms[3];
447   backend_x11->atom_NET_WM_USER_TIME = atoms[4];
448   backend_x11->atom_WM_PROTOCOLS = atoms[5];
449   backend_x11->atom_WM_DELETE_WINDOW = atoms[6];
450   backend_x11->atom_XEMBED = atoms[7];
451   backend_x11->atom_XEMBED_INFO = atoms[8];
452   backend_x11->atom_NET_WM_NAME = atoms[9];
453   backend_x11->atom_UTF8_STRING = atoms[10];
454
455   g_free (clutter_display_name);
456
457   CLUTTER_NOTE (BACKEND,
458                 "X Display '%s'[%p] opened (screen:%d, root:%u, dpi:%f)",
459                 backend_x11->display_name,
460                 backend_x11->xdpy,
461                 backend_x11->xscreen_num,
462                 (unsigned int) backend_x11->xwin_root,
463                 clutter_backend_get_resolution (backend));
464
465   return TRUE;
466 }
467
468 void
469 _clutter_backend_x11_events_init (ClutterBackend *backend)
470 {
471   ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
472
473   CLUTTER_NOTE (EVENT, "initialising the event loop");
474
475   /* the event source is optional */
476   if (!_no_xevent_retrieval)
477     {
478       GSource *source;
479
480       source = _clutter_x11_event_source_new (backend_x11);
481
482       /* default priority for events
483        *
484        * XXX - at some point we'll have a common EventSource API that
485        * is created by the backend, and this code will most likely go
486        * into the default implementation of ClutterBackend
487        */
488       g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
489
490       /* attach the source to the default context, and transfer the
491        * ownership to the GMainContext itself
492        */
493       g_source_attach (source, NULL);
494       g_source_unref (source);
495
496       backend_x11->event_source = source;
497     }
498
499   /* create the device manager; we need this because we can effectively
500    * choose between core+XI1 and XI2 input events
501    */
502   clutter_backend_x11_create_device_manager (backend_x11);
503
504   /* register keymap; unless we create a generic Keymap object, I'm
505    * afraid this will have to stay
506    */
507   clutter_backend_x11_create_keymap (backend_x11);
508 }
509
510 static const GOptionEntry entries[] =
511 {
512   {
513     "display", 0,
514     G_OPTION_FLAG_IN_MAIN,
515     G_OPTION_ARG_STRING, &clutter_display_name,
516     N_("X display to use"), "DISPLAY"
517   },
518   {
519     "screen", 0,
520     G_OPTION_FLAG_IN_MAIN,
521     G_OPTION_ARG_INT, &clutter_screen,
522     N_("X screen to use"), "SCREEN"
523   },
524   { "synch", 0,
525     0,
526     G_OPTION_ARG_NONE, &clutter_synchronise,
527     N_("Make X calls synchronous"), NULL
528   },
529 #if defined(HAVE_XINPUT) || defined(HAVE_XINPUT_2)
530   {
531     "enable-xinput", 0,
532     0,
533     G_OPTION_ARG_NONE, &clutter_enable_xinput,
534     N_("Enable XInput support"), NULL
535   },
536 #endif /* HAVE_XINPUT */
537   { NULL }
538 };
539
540 static void
541 clutter_backend_x11_add_options (ClutterBackend *backend,
542                                  GOptionGroup   *group)
543 {
544   g_option_group_add_entries (group, entries);
545 }
546
547 static void
548 clutter_backend_x11_finalize (GObject *gobject)
549 {
550   ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
551
552   g_free (backend_x11->display_name);
553
554   clutter_x11_remove_filter (cogl_xlib_filter, NULL);
555
556   clutter_x11_remove_filter (xsettings_filter, backend_x11);
557   _clutter_xsettings_client_destroy (backend_x11->xsettings);
558
559   XCloseDisplay (backend_x11->xdpy);
560
561   G_OBJECT_CLASS (clutter_backend_x11_parent_class)->finalize (gobject);
562 }
563
564 static void
565 clutter_backend_x11_dispose (GObject *gobject)
566 {
567   G_OBJECT_CLASS (clutter_backend_x11_parent_class)->dispose (gobject);
568 }
569
570 static ClutterFeatureFlags
571 clutter_backend_x11_get_features (ClutterBackend *backend)
572 {
573   ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_USER_RESIZE
574                             | CLUTTER_FEATURE_STAGE_CURSOR;
575
576   flags |= CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class)->get_features (backend);
577
578   return flags;
579 }
580
581 static void
582 clutter_backend_x11_copy_event_data (ClutterBackend     *backend,
583                                      const ClutterEvent *src,
584                                      ClutterEvent       *dest)
585 {
586   gpointer event_x11;
587
588   event_x11 = _clutter_event_get_platform_data (src);
589   if (event_x11 != NULL)
590     _clutter_event_set_platform_data (dest, _clutter_event_x11_copy (event_x11));
591 }
592
593 static void
594 clutter_backend_x11_free_event_data (ClutterBackend *backend,
595                                      ClutterEvent   *event)
596 {
597   gpointer event_x11;
598
599   event_x11 = _clutter_event_get_platform_data (event);
600   if (event_x11 != NULL)
601     _clutter_event_x11_free (event_x11);
602 }
603
604 static void
605 update_last_event_time (ClutterBackendX11 *backend_x11,
606                         XEvent            *xevent)
607 {
608   Time current_time = CurrentTime;
609   Time last_time = backend_x11->last_event_time;
610
611   switch (xevent->type)
612     {
613     case KeyPress:
614     case KeyRelease:
615       current_time = xevent->xkey.time;
616       break;
617
618     case ButtonPress:
619     case ButtonRelease:
620       current_time = xevent->xbutton.time;
621       break;
622
623     case MotionNotify:
624       current_time = xevent->xmotion.time;
625       break;
626
627     case EnterNotify:
628     case LeaveNotify:
629       current_time = xevent->xcrossing.time;
630       break;
631
632     case PropertyNotify:
633       current_time = xevent->xproperty.time;
634       break;
635
636     default:
637       break;
638     }
639
640   /* only change the current event time if it's after the previous event
641    * time, or if it is at least 30 seconds earlier - in case the system
642    * clock was changed
643    */
644   if ((current_time != CurrentTime) &&
645       (current_time > last_time || (last_time - current_time > (30 * 1000))))
646     backend_x11->last_event_time = current_time;
647 }
648
649 static gboolean
650 clutter_backend_x11_translate_event (ClutterBackend *backend,
651                                      gpointer        native,
652                                      ClutterEvent   *event)
653 {
654   ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
655   ClutterBackendClass *parent_class;
656   XEvent *xevent = native;
657
658   /* X11 filter functions have a higher priority */
659   if (backend_x11->event_filters != NULL)
660     {
661       GSList *node = backend_x11->event_filters;
662
663       while (node != NULL)
664         {
665           ClutterX11EventFilter *filter = node->data;
666
667           switch (filter->func (xevent, event, filter->data))
668             {
669             case CLUTTER_X11_FILTER_CONTINUE:
670               break;
671
672             case CLUTTER_X11_FILTER_TRANSLATE:
673               return TRUE;
674
675             case CLUTTER_X11_FILTER_REMOVE:
676               return FALSE;
677
678             default:
679               break;
680             }
681
682           node = node->next;
683         }
684     }
685
686   /* we update the event time only for events that can
687    * actually reach Clutter's event queue
688    */
689   update_last_event_time (backend_x11, xevent);
690
691   /* chain up to the parent implementation, which will handle
692    * event translators
693    */
694   parent_class = CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class);
695   return parent_class->translate_event (backend, native, event);
696 }
697
698 static CoglRenderer *
699 clutter_backend_x11_get_renderer (ClutterBackend  *backend,
700                                   GError         **error)
701 {
702   ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
703   Display *xdisplay = backend_x11->xdpy;
704   CoglRenderer *renderer;
705
706   CLUTTER_NOTE (BACKEND, "Creating a new Xlib renderer");
707
708   renderer = cogl_renderer_new ();
709
710   cogl_renderer_add_constraint (renderer, COGL_RENDERER_CONSTRAINT_USES_X11);
711
712   /* set the display object we're using */
713   cogl_xlib_renderer_set_foreign_display (renderer, xdisplay);
714
715   return renderer;
716 }
717
718 static CoglDisplay *
719 clutter_backend_x11_get_display (ClutterBackend  *backend,
720                                  CoglRenderer    *renderer,
721                                  CoglSwapChain   *swap_chain,
722                                  GError         **error)
723 {
724   CoglOnscreenTemplate *onscreen_template;
725   GError *internal_error = NULL;
726   CoglDisplay *display;
727   gboolean res;
728
729   CLUTTER_NOTE (BACKEND, "Alpha on Cogl swap chain: %s",
730                 clutter_enable_argb ? "enabled" : "disabled");
731
732   cogl_swap_chain_set_has_alpha (swap_chain, clutter_enable_argb);
733
734   onscreen_template = cogl_onscreen_template_new (swap_chain);
735
736   res = cogl_renderer_check_onscreen_template (renderer,
737                                                onscreen_template,
738                                                &internal_error);
739   if (!res && clutter_enable_argb)
740     {
741       CLUTTER_NOTE (BACKEND,
742                     "Creation of a context with a ARGB visual failed: %s",
743                     internal_error != NULL ? internal_error->message
744                                            : "Unknown reason");
745
746       g_clear_error (&internal_error);
747
748       /* It's possible that the current renderer doesn't support transparency
749        * in a swap_chain so lets see if we can fallback to not having any
750        * transparency...
751        *
752        * XXX: It might be nice to have a CoglRenderer feature we could
753        * explicitly check for ahead of time.
754        */
755       clutter_enable_argb = FALSE;
756       cogl_swap_chain_set_has_alpha (swap_chain, FALSE);
757       res = cogl_renderer_check_onscreen_template (renderer,
758                                                    onscreen_template,
759                                                    &internal_error);
760     }
761
762   if (!res)
763     {
764       g_set_error_literal (error, CLUTTER_INIT_ERROR,
765                            CLUTTER_INIT_ERROR_BACKEND,
766                            internal_error->message);
767
768       g_error_free (internal_error);
769       cogl_object_unref (onscreen_template);
770
771       return NULL;
772     }
773
774   display = cogl_display_new (renderer, onscreen_template);
775   cogl_object_unref (onscreen_template);
776
777   return display;
778 }
779
780 static ClutterStageWindow *
781 clutter_backend_x11_create_stage (ClutterBackend  *backend,
782                                   ClutterStage    *wrapper,
783                                   GError         **error)
784 {
785   ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
786   ClutterEventTranslator *translator;
787   ClutterStageWindow *stage;
788
789   stage = g_object_new (CLUTTER_TYPE_STAGE_X11,
790                         "backend", backend,
791                         "wrapper", wrapper,
792                         NULL);
793
794   /* the X11 stage does event translation */
795   translator = CLUTTER_EVENT_TRANSLATOR (stage);
796   _clutter_backend_add_event_translator (backend, translator);
797
798   CLUTTER_NOTE (MISC, "X11 stage created (display:%p, screen:%d, root:%u)",
799                 backend_x11->xdpy,
800                 backend_x11->xscreen_num,
801                 (unsigned int) backend_x11->xwin_root);
802
803   return stage;
804 }
805
806 static void
807 clutter_backend_x11_class_init (ClutterBackendX11Class *klass)
808 {
809   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
810   ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
811
812   gobject_class->dispose = clutter_backend_x11_dispose;
813   gobject_class->finalize = clutter_backend_x11_finalize;
814
815   backend_class->stage_window_type = CLUTTER_TYPE_STAGE_X11;
816
817   backend_class->pre_parse = clutter_backend_x11_pre_parse;
818   backend_class->post_parse = clutter_backend_x11_post_parse;
819   backend_class->add_options = clutter_backend_x11_add_options;
820   backend_class->get_features = clutter_backend_x11_get_features;
821
822   backend_class->copy_event_data = clutter_backend_x11_copy_event_data;
823   backend_class->free_event_data = clutter_backend_x11_free_event_data;
824   backend_class->translate_event = clutter_backend_x11_translate_event;
825
826   backend_class->get_renderer = clutter_backend_x11_get_renderer;
827   backend_class->get_display = clutter_backend_x11_get_display;
828   backend_class->create_stage = clutter_backend_x11_create_stage;
829 }
830
831 static void
832 clutter_backend_x11_init (ClutterBackendX11 *backend_x11)
833 {
834   backend_x11->last_event_time = CurrentTime;
835 }
836
837 static int
838 error_handler(Display     *xdpy,
839               XErrorEvent *error)
840 {
841   TrappedErrorCode = error->error_code;
842   return 0;
843 }
844
845 /**
846  * clutter_x11_trap_x_errors:
847  *
848  * Traps every X error until clutter_x11_untrap_x_errors() is called.
849  *
850  * Since: 0.6
851  */
852 void
853 clutter_x11_trap_x_errors (void)
854 {
855   TrappedErrorCode  = 0;
856   old_error_handler = XSetErrorHandler (error_handler);
857 }
858
859 /**
860  * clutter_x11_untrap_x_errors:
861  *
862  * Removes the X error trap and returns the current status.
863  *
864  * Return value: the trapped error code, or 0 for success
865  *
866  * Since: 0.4
867  */
868 gint
869 clutter_x11_untrap_x_errors (void)
870 {
871   XSetErrorHandler (old_error_handler);
872
873   return TrappedErrorCode;
874 }
875
876 /**
877  * clutter_x11_get_default_display:
878  *
879  * Retrieves the pointer to the default display.
880  *
881  * Return value: (transfer none): the default display
882  *
883  * Since: 0.6
884  */
885 Display *
886 clutter_x11_get_default_display (void)
887 {
888   ClutterBackend *backend = clutter_get_default_backend ();
889
890   if (backend == NULL)
891     {
892       g_critical ("The Clutter backend has not been initialised");
893       return NULL;
894     }
895
896   if (!CLUTTER_IS_BACKEND_X11 (backend))
897     {
898       g_critical ("The Clutter backend is not a X11 backend");
899       return NULL;
900     }
901
902   return CLUTTER_BACKEND_X11 (backend)->xdpy;
903 }
904
905 /**
906  * clutter_x11_set_display:
907  * @xdpy: pointer to a X display connection.
908  *
909  * Sets the display connection Clutter should use; must be called
910  * before clutter_init(), clutter_init_with_args() or other functions
911  * pertaining Clutter's initialization process.
912  *
913  * If you are parsing the command line arguments by retrieving Clutter's
914  * #GOptionGroup with clutter_get_option_group() and calling
915  * g_option_context_parse() yourself, you should also call
916  * clutter_x11_set_display() before g_option_context_parse().
917  *
918  * Since: 0.8
919  */
920 void
921 clutter_x11_set_display (Display *xdpy)
922 {
923   if (_clutter_context_is_initialized ())
924     {
925       g_warning ("%s() can only be used before calling clutter_init()",
926                  G_STRFUNC);
927       return;
928     }
929
930   _foreign_dpy= xdpy;
931 }
932
933 /**
934  * clutter_x11_enable_xinput:
935  *
936  * Enables the use of the XInput extension if present on connected
937  * XServer and support built into Clutter. XInput allows for multiple
938  * pointing devices to be used.
939  *
940  * This function must be called before clutter_init().
941  *
942  * Since XInput might not be supported by the X server, you might
943  * want to use clutter_x11_has_xinput() to see if support was enabled.
944  *
945  * Since: 0.8
946  */
947 void
948 clutter_x11_enable_xinput (void)
949 {
950   if (_clutter_context_is_initialized ())
951     {
952       g_warning ("%s() can only be used before calling clutter_init()",
953                  G_STRFUNC);
954       return;
955     }
956
957   clutter_enable_xinput = TRUE;
958 }
959
960 /**
961  * clutter_x11_disable_event_retrieval:
962  *
963  * Disables the internal polling of X11 events in the main loop.
964  *
965  * Libraries or applications calling this function will be responsible of
966  * polling all X11 events.
967  *
968  * You also must call clutter_x11_handle_event() to let Clutter process
969  * events and maintain its internal state.
970  *
971  * <warning>This function can only be called before calling
972  * clutter_init().</warning>
973  *
974  * <note>Even with event handling disabled, Clutter will still select
975  * all the events required to maintain its internal state on the stage
976  * Window; compositors using Clutter and input regions to pass events
977  * through to application windows should not rely on an empty input
978  * region, and should instead clear it themselves explicitly using the
979  * XFixes extension.</note>
980  *
981  * This function should not be normally used by applications.
982  *
983  * Since: 0.8
984  */
985 void
986 clutter_x11_disable_event_retrieval (void)
987 {
988   if (_clutter_context_is_initialized ())
989     {
990       g_warning ("%s() can only be used before calling clutter_init()",
991                  G_STRFUNC);
992       return;
993     }
994
995   _no_xevent_retrieval = TRUE;
996 }
997
998 /**
999  * clutter_x11_has_event_retrieval:
1000  *
1001  * Queries the X11 backend to check if event collection has been disabled.
1002  *
1003  * Return value: TRUE if event retrival has been disabled. FALSE otherwise.
1004  *
1005  * Since: 0.8
1006  */
1007 gboolean
1008 clutter_x11_has_event_retrieval (void)
1009 {
1010   return !_no_xevent_retrieval;
1011 }
1012
1013 /**
1014  * clutter_x11_get_default_screen:
1015  *
1016  * Gets the number of the default X Screen object.
1017  *
1018  * Return value: the number of the default screen
1019  *
1020  * Since: 0.6
1021  */
1022 int
1023 clutter_x11_get_default_screen (void)
1024 {
1025  ClutterBackend *backend = clutter_get_default_backend ();
1026
1027   if (backend == NULL)
1028     {
1029       g_critical ("The Clutter backend has not been initialised");
1030       return 0;
1031     }
1032
1033   if (!CLUTTER_IS_BACKEND_X11 (backend))
1034     {
1035       g_critical ("The Clutter backend is not a X11 backend");
1036       return 0;
1037     }
1038
1039   return CLUTTER_BACKEND_X11 (backend)->xscreen_num;
1040 }
1041
1042 /**
1043  * clutter_x11_get_root_window: (skip)
1044  *
1045  * Retrieves the root window.
1046  *
1047  * Return value: the id of the root window
1048  *
1049  * Since: 0.6
1050  */
1051 Window
1052 clutter_x11_get_root_window (void)
1053 {
1054  ClutterBackend *backend = clutter_get_default_backend ();
1055
1056   if (backend == NULL)
1057     {
1058       g_critical ("The Clutter backend has not been initialised");
1059       return None;
1060     }
1061
1062   if (!CLUTTER_IS_BACKEND_X11 (backend))
1063     {
1064       g_critical ("The Clutter backend is not a X11 backend");
1065       return None;
1066     }
1067
1068   return CLUTTER_BACKEND_X11 (backend)->xwin_root;
1069 }
1070
1071 /**
1072  * clutter_x11_add_filter: (skip)
1073  * @func: a filter function
1074  * @data: user data to be passed to the filter function, or %NULL
1075  *
1076  * Adds an event filter function.
1077  *
1078  * Since: 0.6
1079  */
1080 void
1081 clutter_x11_add_filter (ClutterX11FilterFunc func,
1082                         gpointer             data)
1083 {
1084   ClutterX11EventFilter *filter;
1085   ClutterBackend *backend = clutter_get_default_backend ();
1086   ClutterBackendX11 *backend_x11;
1087
1088   g_return_if_fail (func != NULL);
1089
1090   if (backend == NULL)
1091     {
1092       g_critical ("The Clutter backend has not been initialised");
1093       return;
1094     }
1095
1096   if (!CLUTTER_IS_BACKEND_X11 (backend))
1097     {
1098       g_critical ("The Clutter backend is not a X11 backend");
1099       return;
1100     }
1101
1102   backend_x11 = CLUTTER_BACKEND_X11 (backend);
1103
1104   filter = g_new0 (ClutterX11EventFilter, 1);
1105   filter->func = func;
1106   filter->data = data;
1107
1108   backend_x11->event_filters =
1109     g_slist_append (backend_x11->event_filters, filter);
1110
1111   return;
1112 }
1113
1114 /**
1115  * clutter_x11_remove_filter: (skip)
1116  * @func: a filter function
1117  * @data: user data to be passed to the filter function, or %NULL
1118  *
1119  * Removes the given filter function.
1120  *
1121  * Since: 0.6
1122  */
1123 void
1124 clutter_x11_remove_filter (ClutterX11FilterFunc func,
1125                            gpointer             data)
1126 {
1127   GSList                *tmp_list, *this;
1128   ClutterX11EventFilter *filter;
1129   ClutterBackend *backend = clutter_get_default_backend ();
1130   ClutterBackendX11 *backend_x11;
1131
1132   g_return_if_fail (func != NULL);
1133
1134   if (backend == NULL)
1135     {
1136       g_critical ("The Clutter backend has not been initialised");
1137       return;
1138     }
1139
1140   if (!CLUTTER_IS_BACKEND_X11 (backend))
1141     {
1142       g_critical ("The Clutter backend is not a X11 backend");
1143       return;
1144     }
1145
1146   backend_x11 = CLUTTER_BACKEND_X11 (backend);
1147
1148   tmp_list = backend_x11->event_filters;
1149
1150   while (tmp_list)
1151     {
1152       filter   = tmp_list->data;
1153       this     =  tmp_list;
1154       tmp_list = tmp_list->next;
1155
1156       if (filter->func == func && filter->data == data)
1157         {
1158           backend_x11->event_filters =
1159             g_slist_remove_link (backend_x11->event_filters, this);
1160
1161           g_slist_free_1 (this);
1162           g_free (filter);
1163
1164           return;
1165         }
1166     }
1167 }
1168
1169 /**
1170  * clutter_x11_get_input_devices:
1171  *
1172  * Retrieves a pointer to the list of input devices
1173  *
1174  * Deprecated: 1.2: Use clutter_device_manager_peek_devices() instead
1175  *
1176  * Since: 0.8
1177  *
1178  * Return value: (transfer none) (element-type Clutter.InputDevice): a
1179  *   pointer to the internal list of input devices; the returned list is
1180  *   owned by Clutter and should not be modified or freed
1181  */
1182 const GSList *
1183 clutter_x11_get_input_devices (void)
1184 {
1185   ClutterDeviceManager *manager;
1186
1187   manager = clutter_device_manager_get_default ();
1188
1189   return clutter_device_manager_peek_devices (manager);
1190 }
1191
1192 /**
1193  * clutter_x11_has_xinput:
1194  *
1195  * Gets whether Clutter has XInput support.
1196  *
1197  * Return value: %TRUE if Clutter was compiled with XInput support
1198  *   and XInput support is available at run time.
1199  *
1200  * Since: 0.8
1201  */
1202 gboolean
1203 clutter_x11_has_xinput (void)
1204 {
1205 #if defined(HAVE_XINPUT) || defined(HAVE_XINPUT_2)
1206  ClutterBackend *backend = clutter_get_default_backend ();
1207
1208   if (backend == NULL)
1209     {
1210       g_critical ("The Clutter backend has not been initialised");
1211       return FALSE;
1212     }
1213
1214   if (!CLUTTER_IS_BACKEND_X11 (backend))
1215     {
1216       g_critical ("The Clutter backend is not a X11 backend.");
1217       return FALSE;
1218     }
1219
1220   return CLUTTER_BACKEND_X11 (backend)->has_xinput;
1221 #else
1222   return FALSE;
1223 #endif
1224 }
1225
1226 /**
1227  * clutter_x11_has_composite_extension:
1228  *
1229  * Retrieves whether Clutter is running on an X11 server with the
1230  * XComposite extension
1231  *
1232  * Return value: %TRUE if the XComposite extension is available
1233  */
1234 gboolean
1235 clutter_x11_has_composite_extension (void)
1236 {
1237 #if HAVE_XCOMPOSITE
1238   static gboolean have_composite = FALSE, done_check = FALSE;
1239   int error = 0, event = 0;
1240   Display *dpy;
1241
1242   if (done_check)
1243     return have_composite;
1244
1245   if (!_clutter_context_is_initialized ())
1246     {
1247       g_critical ("X11 backend has not been initialised");
1248       return FALSE;
1249     }
1250
1251   dpy = clutter_x11_get_default_display();
1252   if (dpy == NULL)
1253     return FALSE;
1254
1255   if (XCompositeQueryExtension (dpy, &event, &error))
1256     {
1257       int major = 0, minor = 0;
1258       if (XCompositeQueryVersion (dpy, &major, &minor))
1259         {
1260           if (major >= 0 && minor >= 3)
1261             have_composite = TRUE;
1262         }
1263     }
1264
1265   done_check = TRUE;
1266
1267   return have_composite;
1268 #else
1269   return FALSE;
1270 #endif /* HAVE_XCOMPOSITE */
1271 }
1272
1273 /**
1274  * clutter_x11_set_use_argb_visual:
1275  * @use_argb: %TRUE if ARGB visuals should be requested by default
1276  *
1277  * Sets whether the Clutter X11 backend should request ARGB visuals by default
1278  * or not.
1279  *
1280  * By default, Clutter requests RGB visuals.
1281  *
1282  * <note>If no ARGB visuals are found, the X11 backend will fall back to
1283  * requesting a RGB visual instead.</note>
1284  *
1285  * ARGB visuals are required for the #ClutterStage:use-alpha property to work.
1286  *
1287  * <note>This function can only be called once, and before clutter_init() is
1288  * called.</note>
1289  *
1290  * Since: 1.2
1291  */
1292 void
1293 clutter_x11_set_use_argb_visual (gboolean use_argb)
1294 {
1295   if (_clutter_context_is_initialized ())
1296     {
1297       g_warning ("%s() can only be used before calling clutter_init()",
1298                  G_STRFUNC);
1299       return;
1300     }
1301
1302   CLUTTER_NOTE (BACKEND, "ARGB visuals are %s",
1303                 use_argb ? "enabled" : "disabled");
1304
1305   clutter_enable_argb = use_argb;
1306 }
1307
1308 /**
1309  * clutter_x11_get_use_argb_visual:
1310  *
1311  * Retrieves whether the Clutter X11 backend is using ARGB visuals by default
1312  *
1313  * Return value: %TRUE if ARGB visuals are queried by default
1314  *
1315  * Since: 1.2
1316  */
1317 gboolean
1318 clutter_x11_get_use_argb_visual (void)
1319 {
1320   return clutter_enable_argb;
1321 }
1322
1323 XVisualInfo *
1324 _clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11)
1325 {
1326   return cogl_clutter_winsys_xlib_get_visual_info ();
1327 }
1328
1329 /**
1330  * clutter_x11_get_visual_info: (skip)
1331  *
1332  * Retrieves the <structname>XVisualInfo</structname> used by the Clutter X11
1333  * backend.
1334  *
1335  * Return value: (transfer full): a <structname>XVisualInfo</structname>, or
1336  *   <varname>None</varname>. The returned value should be freed using XFree()
1337  *   when done
1338  *
1339  * Since: 1.2
1340  */
1341 XVisualInfo *
1342 clutter_x11_get_visual_info (void)
1343 {
1344   ClutterBackendX11 *backend_x11;
1345   ClutterBackend *backend;
1346
1347   backend = clutter_get_default_backend ();
1348   if (!CLUTTER_IS_BACKEND_X11 (backend))
1349     {
1350       g_critical ("The Clutter backend is not a X11 backend.");
1351       return NULL;
1352     }
1353
1354   backend_x11 = CLUTTER_BACKEND_X11 (backend);
1355
1356   return _clutter_backend_x11_get_visual_info (backend_x11);
1357 }
1358
1359 gboolean
1360 _clutter_x11_input_device_translate_screen_coord (ClutterInputDevice *device,
1361                                                   gint                stage_root_x,
1362                                                   gint                stage_root_y,
1363                                                   guint               index_,
1364                                                   gdouble             value,
1365                                                   gdouble            *axis_value)
1366 {
1367   ClutterAxisInfo *info;
1368   ClutterBackendX11 *backend_x11;
1369   gdouble width, scale, offset;
1370   
1371   backend_x11 = CLUTTER_BACKEND_X11 (device->backend);
1372
1373   if (device->axes == NULL || index_ >= device->axes->len)
1374     return FALSE;
1375
1376   info = &g_array_index (device->axes, ClutterAxisInfo, index_);
1377   if (info->axis != CLUTTER_INPUT_AXIS_X ||
1378       info->axis != CLUTTER_INPUT_AXIS_Y)
1379     {
1380       return FALSE;
1381     }
1382
1383   width = info->max_value - info->min_value;
1384
1385   if (info->axis == CLUTTER_INPUT_AXIS_X)
1386     {
1387       if (width > 0)
1388         scale = backend_x11->xscreen_width / width;
1389       else
1390         scale = 1;
1391
1392       offset = - stage_root_x;
1393     }
1394   else
1395     {
1396       if (width > 0)
1397         scale = backend_x11->xscreen_height / width;
1398       else
1399         scale = 1;
1400
1401       offset = - stage_root_y;
1402     }
1403
1404   if (axis_value)
1405     *axis_value = offset + scale * (value - info->min_value);
1406
1407   return TRUE;
1408 }