2 * An OpenGL based 'interactive canvas' library.
3 * Authored By Matthew Allum <mallum@openedhand.com>
4 * Copyright (C) 2006-2007 OpenedHand
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.
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.
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/>.
26 #include <glib/gi18n-lib.h>
32 #include <sys/ioctl.h>
34 #include <sys/types.h>
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"
47 #include "xsettings/xsettings-common.h"
50 #include <X11/extensions/Xcomposite.h>
54 #include <X11/extensions/XInput.h>
58 #include <X11/extensions/XInput2.h>
61 #include <cogl/cogl.h>
62 #include <cogl/cogl-xlib.h>
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"
71 #define clutter_backend_x11_get_type _clutter_backend_x11_get_type
73 G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
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!
79 static const gchar *atom_names[] = {
83 "_NET_WM_STATE_FULLSCREEN",
93 #define N_ATOM_NAMES G_N_ELEMENTS (atom_names)
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;
102 static gchar *clutter_display_name = NULL;
103 static gint clutter_screen = -1;
104 static gboolean clutter_synchronise = FALSE;
107 static int TrappedErrorCode = 0;
108 static int (* old_error_handler) (Display *, XErrorEvent *);
110 static ClutterX11FilterReturn
111 xsettings_filter (XEvent *xevent,
115 ClutterBackendX11 *backend_x11 = data;
117 _clutter_xsettings_client_process_event (backend_x11->xsettings, xevent);
119 /* we always want the rest of the stack to get XSettings events, even
120 * if Clutter already handled them
123 return CLUTTER_X11_FILTER_CONTINUE;
126 static ClutterX11FilterReturn
127 cogl_xlib_filter (XEvent *xevent,
131 ClutterX11FilterReturn retval;
132 CoglFilterReturn ret;
134 ret = cogl_xlib_handle_event (xevent);
137 case COGL_FILTER_REMOVE:
138 retval = CLUTTER_X11_FILTER_REMOVE;
141 case COGL_FILTER_CONTINUE:
143 retval = CLUTTER_X11_FILTER_CONTINUE;
151 clutter_backend_x11_xsettings_notify (const char *name,
152 XSettingsAction action,
153 XSettingsSetting *setting,
156 ClutterSettings *settings = clutter_settings_get_default ();
159 if (name == NULL || *name == '\0')
165 g_object_freeze_notify (G_OBJECT (settings));
167 for (i = 0; i < _n_clutter_settings_map; i++)
169 if (g_strcmp0 (name, CLUTTER_SETTING_X11_NAME (i)) == 0)
171 GValue value = { 0, };
173 switch (setting->type)
175 case XSETTINGS_TYPE_INT:
176 g_value_init (&value, G_TYPE_INT);
177 g_value_set_int (&value, setting->data.v_int);
180 case XSETTINGS_TYPE_STRING:
181 g_value_init (&value, G_TYPE_STRING);
182 g_value_set_string (&value, setting->data.v_string);
185 case XSETTINGS_TYPE_COLOR:
189 color.red = (guint8) ((float) setting->data.v_color.red
191 color.green = (guint8) ((float) setting->data.v_color.green
193 color.blue = (guint8) ((float) setting->data.v_color.blue
195 color.alpha = (guint8) ((float) setting->data.v_color.alpha
198 g_value_init (&value, G_TYPE_BOXED);
199 clutter_value_set_color (&value, &color);
204 CLUTTER_NOTE (BACKEND,
205 "Mapping XSETTING '%s' to 'ClutterSettings:%s'",
206 CLUTTER_SETTING_X11_NAME (i),
207 CLUTTER_SETTING_PROPERTY (i));
209 g_object_set_property (G_OBJECT (settings),
210 CLUTTER_SETTING_PROPERTY (i),
213 g_value_unset (&value);
219 g_object_thaw_notify (G_OBJECT (settings));
223 clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
225 if (G_UNLIKELY (backend_x11->device_manager == NULL))
227 ClutterEventTranslator *translator;
228 ClutterBackend *backend;
230 #if defined(HAVE_XINPUT) || defined(HAVE_XINPUT_2)
231 if (clutter_enable_xinput)
233 int event_base, first_event, first_error;
235 if (XQueryExtension (backend_x11->xdpy, "XInputExtension",
243 #ifdef HAVE_XINPUT_2_2
247 #endif /* HAVE_XINPUT_2_2 */
249 if (XIQueryVersion (backend_x11->xdpy, &major, &minor) != BadRequest)
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,
259 backend_x11->xi_minor = minor;
262 #endif /* HAVE_XINPUT_2 */
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,
272 backend_x11->xi_minor = -1;
277 #endif /* HAVE_XINPUT || HAVE_XINPUT_2 */
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,
286 backend_x11->xi_minor = -1;
289 backend = CLUTTER_BACKEND (backend_x11);
290 backend->device_manager = backend_x11->device_manager;
292 translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->device_manager);
293 _clutter_backend_add_event_translator (backend, translator);
298 clutter_backend_x11_create_keymap (ClutterBackendX11 *backend_x11)
300 if (backend_x11->keymap == NULL)
302 ClutterEventTranslator *translator;
303 ClutterBackend *backend;
305 backend_x11->keymap =
306 g_object_new (CLUTTER_TYPE_KEYMAP_X11,
307 "backend", backend_x11,
310 backend = CLUTTER_BACKEND (backend_x11);
311 translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->keymap);
312 _clutter_backend_add_event_translator (backend, translator);
317 clutter_backend_x11_pre_parse (ClutterBackend *backend,
320 const gchar *env_string;
322 /* we don't fail here if DISPLAY is not set, as the user
323 * might pass the --display command line switch
325 env_string = g_getenv ("DISPLAY");
328 clutter_display_name = g_strdup (env_string);
332 env_string = g_getenv ("CLUTTER_DISABLE_ARGB_VISUAL");
335 clutter_enable_argb = FALSE;
339 env_string = g_getenv ("CLUTTER_ENABLE_XINPUT");
342 clutter_enable_xinput = TRUE;
350 clutter_backend_x11_post_parse (ClutterBackend *backend,
353 ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
354 ClutterSettings *settings;
355 Atom atoms[N_ATOM_NAMES];
359 backend_x11->xdpy = _foreign_dpy;
361 /* Only open connection if not already set by prior call to
362 * clutter_x11_set_display()
364 if (backend_x11->xdpy == NULL)
366 if (clutter_display_name != NULL &&
367 *clutter_display_name != '\0')
369 CLUTTER_NOTE (BACKEND, "XOpenDisplay on '%s'", clutter_display_name);
371 backend_x11->xdpy = XOpenDisplay (clutter_display_name);
372 if (backend_x11->xdpy == NULL)
374 g_set_error (error, CLUTTER_INIT_ERROR,
375 CLUTTER_INIT_ERROR_BACKEND,
376 "Unable to open display '%s'",
377 clutter_display_name);
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");
392 g_assert (backend_x11->xdpy != NULL);
394 CLUTTER_NOTE (BACKEND, "Getting the X screen");
396 settings = clutter_settings_get_default ();
398 /* Cogl needs to know the Xlib display connection for
399 CoglTexturePixmapX11 */
400 cogl_xlib_set_display (backend_x11->xdpy);
402 /* add event filter for Cogl events */
403 clutter_x11_add_filter (cogl_xlib_filter, NULL);
405 if (clutter_screen == -1)
406 backend_x11->xscreen = DefaultScreenOfDisplay (backend_x11->xdpy);
408 backend_x11->xscreen = ScreenOfDisplay (backend_x11->xdpy,
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);
415 backend_x11->xwin_root = RootWindow (backend_x11->xdpy,
416 backend_x11->xscreen_num);
418 backend_x11->display_name = g_strdup (clutter_display_name);
420 dpi = (((double) DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num) * 25.4)
421 / (double) DisplayHeightMM (backend_x11->xdpy, backend_x11->xscreen_num));
423 g_object_set (settings, "font-dpi", (int) dpi * 1024, NULL);
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,
433 /* add event filter for XSETTINGS events */
434 clutter_x11_add_filter (xsettings_filter, backend_x11);
436 if (clutter_synchronise)
437 XSynchronize (backend_x11->xdpy, True);
439 XInternAtoms (backend_x11->xdpy,
440 (char **) atom_names, N_ATOM_NAMES,
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];
455 g_free (clutter_display_name);
457 CLUTTER_NOTE (BACKEND,
458 "X Display '%s'[%p] opened (screen:%d, root:%u, dpi:%f)",
459 backend_x11->display_name,
461 backend_x11->xscreen_num,
462 (unsigned int) backend_x11->xwin_root,
463 clutter_backend_get_resolution (backend));
469 _clutter_backend_x11_events_init (ClutterBackend *backend)
471 ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
473 CLUTTER_NOTE (EVENT, "initialising the event loop");
475 /* the event source is optional */
476 if (!_no_xevent_retrieval)
480 source = _clutter_x11_event_source_new (backend_x11);
482 /* default priority for events
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
488 g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
490 /* attach the source to the default context, and transfer the
491 * ownership to the GMainContext itself
493 g_source_attach (source, NULL);
494 g_source_unref (source);
496 backend_x11->event_source = source;
499 /* create the device manager; we need this because we can effectively
500 * choose between core+XI1 and XI2 input events
502 clutter_backend_x11_create_device_manager (backend_x11);
504 /* register keymap; unless we create a generic Keymap object, I'm
505 * afraid this will have to stay
507 clutter_backend_x11_create_keymap (backend_x11);
510 static const GOptionEntry entries[] =
514 G_OPTION_FLAG_IN_MAIN,
515 G_OPTION_ARG_STRING, &clutter_display_name,
516 N_("X display to use"), "DISPLAY"
520 G_OPTION_FLAG_IN_MAIN,
521 G_OPTION_ARG_INT, &clutter_screen,
522 N_("X screen to use"), "SCREEN"
526 G_OPTION_ARG_NONE, &clutter_synchronise,
527 N_("Make X calls synchronous"), NULL
529 #if defined(HAVE_XINPUT) || defined(HAVE_XINPUT_2)
533 G_OPTION_ARG_NONE, &clutter_enable_xinput,
534 N_("Enable XInput support"), NULL
536 #endif /* HAVE_XINPUT */
541 clutter_backend_x11_add_options (ClutterBackend *backend,
544 g_option_group_add_entries (group, entries);
548 clutter_backend_x11_finalize (GObject *gobject)
550 ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
552 g_free (backend_x11->display_name);
554 clutter_x11_remove_filter (cogl_xlib_filter, NULL);
556 clutter_x11_remove_filter (xsettings_filter, backend_x11);
557 _clutter_xsettings_client_destroy (backend_x11->xsettings);
559 XCloseDisplay (backend_x11->xdpy);
561 G_OBJECT_CLASS (clutter_backend_x11_parent_class)->finalize (gobject);
565 clutter_backend_x11_dispose (GObject *gobject)
567 G_OBJECT_CLASS (clutter_backend_x11_parent_class)->dispose (gobject);
570 static ClutterFeatureFlags
571 clutter_backend_x11_get_features (ClutterBackend *backend)
573 ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_USER_RESIZE
574 | CLUTTER_FEATURE_STAGE_CURSOR;
576 flags |= CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class)->get_features (backend);
582 clutter_backend_x11_copy_event_data (ClutterBackend *backend,
583 const ClutterEvent *src,
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));
594 clutter_backend_x11_free_event_data (ClutterBackend *backend,
599 event_x11 = _clutter_event_get_platform_data (event);
600 if (event_x11 != NULL)
601 _clutter_event_x11_free (event_x11);
605 update_last_event_time (ClutterBackendX11 *backend_x11,
608 Time current_time = CurrentTime;
609 Time last_time = backend_x11->last_event_time;
611 switch (xevent->type)
615 current_time = xevent->xkey.time;
620 current_time = xevent->xbutton.time;
624 current_time = xevent->xmotion.time;
629 current_time = xevent->xcrossing.time;
633 current_time = xevent->xproperty.time;
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
644 if ((current_time != CurrentTime) &&
645 (current_time > last_time || (last_time - current_time > (30 * 1000))))
646 backend_x11->last_event_time = current_time;
650 clutter_backend_x11_translate_event (ClutterBackend *backend,
654 ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
655 ClutterBackendClass *parent_class;
656 XEvent *xevent = native;
658 /* X11 filter functions have a higher priority */
659 if (backend_x11->event_filters != NULL)
661 GSList *node = backend_x11->event_filters;
665 ClutterX11EventFilter *filter = node->data;
667 switch (filter->func (xevent, event, filter->data))
669 case CLUTTER_X11_FILTER_CONTINUE:
672 case CLUTTER_X11_FILTER_TRANSLATE:
675 case CLUTTER_X11_FILTER_REMOVE:
686 /* we update the event time only for events that can
687 * actually reach Clutter's event queue
689 update_last_event_time (backend_x11, xevent);
691 /* chain up to the parent implementation, which will handle
694 parent_class = CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class);
695 return parent_class->translate_event (backend, native, event);
698 static CoglRenderer *
699 clutter_backend_x11_get_renderer (ClutterBackend *backend,
702 ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
703 Display *xdisplay = backend_x11->xdpy;
704 CoglRenderer *renderer;
706 CLUTTER_NOTE (BACKEND, "Creating a new Xlib renderer");
708 renderer = cogl_renderer_new ();
710 cogl_renderer_add_constraint (renderer, COGL_RENDERER_CONSTRAINT_USES_X11);
712 /* set the display object we're using */
713 cogl_xlib_renderer_set_foreign_display (renderer, xdisplay);
719 clutter_backend_x11_get_display (ClutterBackend *backend,
720 CoglRenderer *renderer,
721 CoglSwapChain *swap_chain,
724 CoglOnscreenTemplate *onscreen_template;
725 GError *internal_error = NULL;
726 CoglDisplay *display;
729 CLUTTER_NOTE (BACKEND, "Alpha on Cogl swap chain: %s",
730 clutter_enable_argb ? "enabled" : "disabled");
732 cogl_swap_chain_set_has_alpha (swap_chain, clutter_enable_argb);
734 onscreen_template = cogl_onscreen_template_new (swap_chain);
736 res = cogl_renderer_check_onscreen_template (renderer,
739 if (!res && clutter_enable_argb)
741 CLUTTER_NOTE (BACKEND,
742 "Creation of a context with a ARGB visual failed: %s",
743 internal_error != NULL ? internal_error->message
746 g_clear_error (&internal_error);
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
752 * XXX: It might be nice to have a CoglRenderer feature we could
753 * explicitly check for ahead of time.
755 clutter_enable_argb = FALSE;
756 cogl_swap_chain_set_has_alpha (swap_chain, FALSE);
757 res = cogl_renderer_check_onscreen_template (renderer,
764 g_set_error_literal (error, CLUTTER_INIT_ERROR,
765 CLUTTER_INIT_ERROR_BACKEND,
766 internal_error->message);
768 g_error_free (internal_error);
769 cogl_object_unref (onscreen_template);
774 display = cogl_display_new (renderer, onscreen_template);
775 cogl_object_unref (onscreen_template);
780 static ClutterStageWindow *
781 clutter_backend_x11_create_stage (ClutterBackend *backend,
782 ClutterStage *wrapper,
785 ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
786 ClutterEventTranslator *translator;
787 ClutterStageWindow *stage;
789 stage = g_object_new (CLUTTER_TYPE_STAGE_X11,
794 /* the X11 stage does event translation */
795 translator = CLUTTER_EVENT_TRANSLATOR (stage);
796 _clutter_backend_add_event_translator (backend, translator);
798 CLUTTER_NOTE (MISC, "X11 stage created (display:%p, screen:%d, root:%u)",
800 backend_x11->xscreen_num,
801 (unsigned int) backend_x11->xwin_root);
807 clutter_backend_x11_class_init (ClutterBackendX11Class *klass)
809 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
810 ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
812 gobject_class->dispose = clutter_backend_x11_dispose;
813 gobject_class->finalize = clutter_backend_x11_finalize;
815 backend_class->stage_window_type = CLUTTER_TYPE_STAGE_X11;
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;
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;
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;
832 clutter_backend_x11_init (ClutterBackendX11 *backend_x11)
834 backend_x11->last_event_time = CurrentTime;
838 error_handler(Display *xdpy,
841 TrappedErrorCode = error->error_code;
846 * clutter_x11_trap_x_errors:
848 * Traps every X error until clutter_x11_untrap_x_errors() is called.
853 clutter_x11_trap_x_errors (void)
855 TrappedErrorCode = 0;
856 old_error_handler = XSetErrorHandler (error_handler);
860 * clutter_x11_untrap_x_errors:
862 * Removes the X error trap and returns the current status.
864 * Return value: the trapped error code, or 0 for success
869 clutter_x11_untrap_x_errors (void)
871 XSetErrorHandler (old_error_handler);
873 return TrappedErrorCode;
877 * clutter_x11_get_default_display:
879 * Retrieves the pointer to the default display.
881 * Return value: (transfer none): the default display
886 clutter_x11_get_default_display (void)
888 ClutterBackend *backend = clutter_get_default_backend ();
892 g_critical ("The Clutter backend has not been initialised");
896 if (!CLUTTER_IS_BACKEND_X11 (backend))
898 g_critical ("The Clutter backend is not a X11 backend");
902 return CLUTTER_BACKEND_X11 (backend)->xdpy;
906 * clutter_x11_set_display:
907 * @xdpy: pointer to a X display connection.
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.
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().
921 clutter_x11_set_display (Display *xdpy)
923 if (_clutter_context_is_initialized ())
925 g_warning ("%s() can only be used before calling clutter_init()",
934 * clutter_x11_enable_xinput:
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.
940 * This function must be called before clutter_init().
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.
948 clutter_x11_enable_xinput (void)
950 if (_clutter_context_is_initialized ())
952 g_warning ("%s() can only be used before calling clutter_init()",
957 clutter_enable_xinput = TRUE;
961 * clutter_x11_disable_event_retrieval:
963 * Disables the internal polling of X11 events in the main loop.
965 * Libraries or applications calling this function will be responsible of
966 * polling all X11 events.
968 * You also must call clutter_x11_handle_event() to let Clutter process
969 * events and maintain its internal state.
971 * <warning>This function can only be called before calling
972 * clutter_init().</warning>
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>
981 * This function should not be normally used by applications.
986 clutter_x11_disable_event_retrieval (void)
988 if (_clutter_context_is_initialized ())
990 g_warning ("%s() can only be used before calling clutter_init()",
995 _no_xevent_retrieval = TRUE;
999 * clutter_x11_has_event_retrieval:
1001 * Queries the X11 backend to check if event collection has been disabled.
1003 * Return value: TRUE if event retrival has been disabled. FALSE otherwise.
1008 clutter_x11_has_event_retrieval (void)
1010 return !_no_xevent_retrieval;
1014 * clutter_x11_get_default_screen:
1016 * Gets the number of the default X Screen object.
1018 * Return value: the number of the default screen
1023 clutter_x11_get_default_screen (void)
1025 ClutterBackend *backend = clutter_get_default_backend ();
1027 if (backend == NULL)
1029 g_critical ("The Clutter backend has not been initialised");
1033 if (!CLUTTER_IS_BACKEND_X11 (backend))
1035 g_critical ("The Clutter backend is not a X11 backend");
1039 return CLUTTER_BACKEND_X11 (backend)->xscreen_num;
1043 * clutter_x11_get_root_window: (skip)
1045 * Retrieves the root window.
1047 * Return value: the id of the root window
1052 clutter_x11_get_root_window (void)
1054 ClutterBackend *backend = clutter_get_default_backend ();
1056 if (backend == NULL)
1058 g_critical ("The Clutter backend has not been initialised");
1062 if (!CLUTTER_IS_BACKEND_X11 (backend))
1064 g_critical ("The Clutter backend is not a X11 backend");
1068 return CLUTTER_BACKEND_X11 (backend)->xwin_root;
1072 * clutter_x11_add_filter: (skip)
1073 * @func: a filter function
1074 * @data: user data to be passed to the filter function, or %NULL
1076 * Adds an event filter function.
1081 clutter_x11_add_filter (ClutterX11FilterFunc func,
1084 ClutterX11EventFilter *filter;
1085 ClutterBackend *backend = clutter_get_default_backend ();
1086 ClutterBackendX11 *backend_x11;
1088 g_return_if_fail (func != NULL);
1090 if (backend == NULL)
1092 g_critical ("The Clutter backend has not been initialised");
1096 if (!CLUTTER_IS_BACKEND_X11 (backend))
1098 g_critical ("The Clutter backend is not a X11 backend");
1102 backend_x11 = CLUTTER_BACKEND_X11 (backend);
1104 filter = g_new0 (ClutterX11EventFilter, 1);
1105 filter->func = func;
1106 filter->data = data;
1108 backend_x11->event_filters =
1109 g_slist_append (backend_x11->event_filters, filter);
1115 * clutter_x11_remove_filter: (skip)
1116 * @func: a filter function
1117 * @data: user data to be passed to the filter function, or %NULL
1119 * Removes the given filter function.
1124 clutter_x11_remove_filter (ClutterX11FilterFunc func,
1127 GSList *tmp_list, *this;
1128 ClutterX11EventFilter *filter;
1129 ClutterBackend *backend = clutter_get_default_backend ();
1130 ClutterBackendX11 *backend_x11;
1132 g_return_if_fail (func != NULL);
1134 if (backend == NULL)
1136 g_critical ("The Clutter backend has not been initialised");
1140 if (!CLUTTER_IS_BACKEND_X11 (backend))
1142 g_critical ("The Clutter backend is not a X11 backend");
1146 backend_x11 = CLUTTER_BACKEND_X11 (backend);
1148 tmp_list = backend_x11->event_filters;
1152 filter = tmp_list->data;
1154 tmp_list = tmp_list->next;
1156 if (filter->func == func && filter->data == data)
1158 backend_x11->event_filters =
1159 g_slist_remove_link (backend_x11->event_filters, this);
1161 g_slist_free_1 (this);
1170 * clutter_x11_get_input_devices:
1172 * Retrieves a pointer to the list of input devices
1174 * Deprecated: 1.2: Use clutter_device_manager_peek_devices() instead
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
1183 clutter_x11_get_input_devices (void)
1185 ClutterDeviceManager *manager;
1187 manager = clutter_device_manager_get_default ();
1189 return clutter_device_manager_peek_devices (manager);
1193 * clutter_x11_has_xinput:
1195 * Gets whether Clutter has XInput support.
1197 * Return value: %TRUE if Clutter was compiled with XInput support
1198 * and XInput support is available at run time.
1203 clutter_x11_has_xinput (void)
1205 #if defined(HAVE_XINPUT) || defined(HAVE_XINPUT_2)
1206 ClutterBackend *backend = clutter_get_default_backend ();
1208 if (backend == NULL)
1210 g_critical ("The Clutter backend has not been initialised");
1214 if (!CLUTTER_IS_BACKEND_X11 (backend))
1216 g_critical ("The Clutter backend is not a X11 backend.");
1220 return CLUTTER_BACKEND_X11 (backend)->has_xinput;
1227 * clutter_x11_has_composite_extension:
1229 * Retrieves whether Clutter is running on an X11 server with the
1230 * XComposite extension
1232 * Return value: %TRUE if the XComposite extension is available
1235 clutter_x11_has_composite_extension (void)
1238 static gboolean have_composite = FALSE, done_check = FALSE;
1239 int error = 0, event = 0;
1243 return have_composite;
1245 if (!_clutter_context_is_initialized ())
1247 g_critical ("X11 backend has not been initialised");
1251 dpy = clutter_x11_get_default_display();
1255 if (XCompositeQueryExtension (dpy, &event, &error))
1257 int major = 0, minor = 0;
1258 if (XCompositeQueryVersion (dpy, &major, &minor))
1260 if (major >= 0 && minor >= 3)
1261 have_composite = TRUE;
1267 return have_composite;
1270 #endif /* HAVE_XCOMPOSITE */
1274 * clutter_x11_set_use_argb_visual:
1275 * @use_argb: %TRUE if ARGB visuals should be requested by default
1277 * Sets whether the Clutter X11 backend should request ARGB visuals by default
1280 * By default, Clutter requests RGB visuals.
1282 * <note>If no ARGB visuals are found, the X11 backend will fall back to
1283 * requesting a RGB visual instead.</note>
1285 * ARGB visuals are required for the #ClutterStage:use-alpha property to work.
1287 * <note>This function can only be called once, and before clutter_init() is
1293 clutter_x11_set_use_argb_visual (gboolean use_argb)
1295 if (_clutter_context_is_initialized ())
1297 g_warning ("%s() can only be used before calling clutter_init()",
1302 CLUTTER_NOTE (BACKEND, "ARGB visuals are %s",
1303 use_argb ? "enabled" : "disabled");
1305 clutter_enable_argb = use_argb;
1309 * clutter_x11_get_use_argb_visual:
1311 * Retrieves whether the Clutter X11 backend is using ARGB visuals by default
1313 * Return value: %TRUE if ARGB visuals are queried by default
1318 clutter_x11_get_use_argb_visual (void)
1320 return clutter_enable_argb;
1324 _clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11)
1326 return cogl_clutter_winsys_xlib_get_visual_info ();
1330 * clutter_x11_get_visual_info: (skip)
1332 * Retrieves the <structname>XVisualInfo</structname> used by the Clutter X11
1335 * Return value: (transfer full): a <structname>XVisualInfo</structname>, or
1336 * <varname>None</varname>. The returned value should be freed using XFree()
1342 clutter_x11_get_visual_info (void)
1344 ClutterBackendX11 *backend_x11;
1345 ClutterBackend *backend;
1347 backend = clutter_get_default_backend ();
1348 if (!CLUTTER_IS_BACKEND_X11 (backend))
1350 g_critical ("The Clutter backend is not a X11 backend.");
1354 backend_x11 = CLUTTER_BACKEND_X11 (backend);
1356 return _clutter_backend_x11_get_visual_info (backend_x11);
1360 _clutter_x11_input_device_translate_screen_coord (ClutterInputDevice *device,
1365 gdouble *axis_value)
1367 ClutterAxisInfo *info;
1368 ClutterBackendX11 *backend_x11;
1369 gdouble width, scale, offset;
1371 backend_x11 = CLUTTER_BACKEND_X11 (device->backend);
1373 if (device->axes == NULL || index_ >= device->axes->len)
1376 info = &g_array_index (device->axes, ClutterAxisInfo, index_);
1377 if (info->axis != CLUTTER_INPUT_AXIS_X ||
1378 info->axis != CLUTTER_INPUT_AXIS_Y)
1383 width = info->max_value - info->min_value;
1385 if (info->axis == CLUTTER_INPUT_AXIS_X)
1388 scale = backend_x11->xscreen_width / width;
1392 offset = - stage_root_x;
1397 scale = backend_x11->xscreen_height / width;
1401 offset = - stage_root_y;
1405 *axis_value = offset + scale * (value - info->min_value);