]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdisplay-x11.c
Merge branch 'button-box-orientable-584598'
[~andy/gtk] / gdk / x11 / gdkdisplay-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * gdkdisplay-x11.c
3  * 
4  * Copyright 2001 Sun Microsystems Inc.
5  * Copyright (C) 2004 Nokia Corporation
6  *
7  * Erwann Chenede <erwann.chenede@sun.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 #include "config.h"
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <unistd.h>
31
32 #include <glib.h>
33 #include "gdkx.h"
34 #include "gdkdisplay.h"
35 #include "gdkdisplay-x11.h"
36 #include "gdkscreen.h"
37 #include "gdkscreen-x11.h"
38 #include "gdkinternals.h"
39 #include "gdkinputprivate.h"
40 #include "xsettings-client.h"
41 #include "gdkalias.h"
42
43 #include <X11/Xatom.h>
44
45 #ifdef HAVE_XKB
46 #include <X11/XKBlib.h>
47 #endif
48
49 #ifdef HAVE_XFIXES
50 #include <X11/extensions/Xfixes.h>
51 #endif
52
53 #include <X11/extensions/shape.h>
54
55 #ifdef HAVE_XCOMPOSITE
56 #include <X11/extensions/Xcomposite.h>
57 #endif
58
59 #ifdef HAVE_XDAMAGE
60 #include <X11/extensions/Xdamage.h>
61 #endif
62
63 #ifdef HAVE_RANDR
64 #include <X11/extensions/Xrandr.h>
65 #endif
66
67
68 static void   gdk_display_x11_dispose            (GObject            *object);
69 static void   gdk_display_x11_finalize           (GObject            *object);
70
71 #ifdef HAVE_X11R6
72 static void gdk_internal_connection_watch (Display  *display,
73                                            XPointer  arg,
74                                            gint      fd,
75                                            gboolean  opening,
76                                            XPointer *watch_data);
77 #endif /* HAVE_X11R6 */
78
79 /* Note that we never *directly* use WM_LOCALE_NAME, WM_PROTOCOLS,
80  * but including them here has the side-effect of getting them
81  * into the internal Xlib cache
82  */
83 static const char *const precache_atoms[] = {
84   "UTF8_STRING",
85   "WM_CLIENT_LEADER",
86   "WM_DELETE_WINDOW",
87   "WM_ICON_NAME",
88   "WM_LOCALE_NAME",
89   "WM_NAME",
90   "WM_PROTOCOLS",
91   "WM_TAKE_FOCUS",
92   "WM_WINDOW_ROLE",
93   "_NET_ACTIVE_WINDOW",
94   "_NET_CURRENT_DESKTOP",
95   "_NET_FRAME_EXTENTS",
96   "_NET_STARTUP_ID",
97   "_NET_WM_CM_S0",
98   "_NET_WM_DESKTOP",
99   "_NET_WM_ICON",
100   "_NET_WM_ICON_NAME",
101   "_NET_WM_NAME",
102   "_NET_WM_PID",
103   "_NET_WM_PING",
104   "_NET_WM_STATE",
105   "_NET_WM_STATE_ABOVE",
106   "_NET_WM_STATE_BELOW",
107   "_NET_WM_STATE_FULLSCREEN",
108   "_NET_WM_STATE_MODAL",
109   "_NET_WM_STATE_MAXIMIZED_VERT",
110   "_NET_WM_STATE_MAXIMIZED_HORZ",
111   "_NET_WM_STATE_SKIP_TASKBAR",
112   "_NET_WM_STATE_SKIP_PAGER",
113   "_NET_WM_STATE_STICKY",
114   "_NET_WM_SYNC_REQUEST",
115   "_NET_WM_SYNC_REQUEST_COUNTER",
116   "_NET_WM_WINDOW_TYPE",
117   "_NET_WM_WINDOW_TYPE_NORMAL",
118   "_NET_WM_USER_TIME",
119   "_NET_VIRTUAL_ROOTS"
120 };
121
122 G_DEFINE_TYPE (GdkDisplayX11, _gdk_display_x11, GDK_TYPE_DISPLAY)
123
124 static void
125 _gdk_display_x11_class_init (GdkDisplayX11Class * class)
126 {
127   GObjectClass *object_class = G_OBJECT_CLASS (class);
128   
129   object_class->dispose = gdk_display_x11_dispose;
130   object_class->finalize = gdk_display_x11_finalize;
131 }
132
133 static void
134 _gdk_display_x11_init (GdkDisplayX11 *display)
135 {
136 }
137
138 /**
139  * gdk_display_open:
140  * @display_name: the name of the display to open
141  * @returns: a #GdkDisplay, or %NULL if the display
142  *  could not be opened.
143  *
144  * Opens a display.
145  *
146  * Since: 2.2
147  */
148 GdkDisplay *
149 gdk_display_open (const gchar *display_name)
150 {
151   Display *xdisplay;
152   GdkDisplay *display;
153   GdkDisplayX11 *display_x11;
154   GdkWindowAttr attr;
155   gint argc;
156   gchar *argv[1];
157   const char *sm_client_id;
158   
159   XClassHint *class_hint;
160   gulong pid;
161   gint i;
162   gint ignore;
163   gint maj, min;
164
165   xdisplay = XOpenDisplay (display_name);
166   if (!xdisplay)
167     return NULL;
168   
169   display = g_object_new (GDK_TYPE_DISPLAY_X11, NULL);
170   display_x11 = GDK_DISPLAY_X11 (display);
171
172   display_x11->use_xshm = TRUE;
173   display_x11->xdisplay = xdisplay;
174
175 #ifdef HAVE_X11R6  
176   /* Set up handlers for Xlib internal connections */
177   XAddConnectionWatch (xdisplay, gdk_internal_connection_watch, NULL);
178 #endif /* HAVE_X11R6 */
179   
180   _gdk_x11_precache_atoms (display, precache_atoms, G_N_ELEMENTS (precache_atoms));
181
182   /* RandR must be initialized before we initialize the screens */
183   display_x11->have_randr13 = FALSE;
184 #ifdef HAVE_RANDR
185   if (XRRQueryExtension (display_x11->xdisplay,
186                          &display_x11->xrandr_event_base, &ignore))
187   {
188       int major, minor;
189       
190       XRRQueryVersion (display_x11->xdisplay, &major, &minor);
191
192       if ((major == 1 && minor >= 3) || major > 1)
193           display_x11->have_randr13 = TRUE;
194
195        gdk_x11_register_standard_event_type (display, display_x11->xrandr_event_base, RRNumberEvents);
196   }
197 #endif
198   
199   /* initialize the display's screens */ 
200   display_x11->screens = g_new (GdkScreen *, ScreenCount (display_x11->xdisplay));
201   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
202     display_x11->screens[i] = _gdk_x11_screen_new (display, i);
203
204   /* We need to initialize events after we have the screen
205    * structures in places
206    */
207   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
208     _gdk_x11_events_init_screen (display_x11->screens[i]);
209   
210   /*set the default screen */
211   display_x11->default_screen = display_x11->screens[DefaultScreen (display_x11->xdisplay)];
212
213   attr.window_type = GDK_WINDOW_TOPLEVEL;
214   attr.wclass = GDK_INPUT_OUTPUT;
215   attr.x = 10;
216   attr.y = 10;
217   attr.width = 10;
218   attr.height = 10;
219   attr.event_mask = 0;
220
221   display_x11->leader_gdk_window = gdk_window_new (GDK_SCREEN_X11 (display_x11->default_screen)->root_window, 
222                                                    &attr, GDK_WA_X | GDK_WA_Y);
223   (_gdk_x11_window_get_toplevel (display_x11->leader_gdk_window))->is_leader = TRUE;
224
225   display_x11->leader_window = GDK_WINDOW_XID (display_x11->leader_gdk_window);
226
227   display_x11->leader_window_title_set = FALSE;
228
229   display_x11->have_render = GDK_UNKNOWN;
230
231 #ifdef HAVE_XFIXES
232   if (XFixesQueryExtension (display_x11->xdisplay, 
233                             &display_x11->xfixes_event_base, 
234                             &ignore))
235     {
236       display_x11->have_xfixes = TRUE;
237
238       gdk_x11_register_standard_event_type (display,
239                                             display_x11->xfixes_event_base, 
240                                             XFixesNumberEvents);
241     }
242   else
243 #endif
244     display_x11->have_xfixes = FALSE;
245
246 #ifdef HAVE_XCOMPOSITE
247   if (XCompositeQueryExtension (display_x11->xdisplay,
248                                 &ignore, &ignore))
249     {
250       int major, minor;
251
252       XCompositeQueryVersion (display_x11->xdisplay, &major, &minor);
253
254       /* Prior to Composite version 0.4, composited windows clipped their
255        * parents, so you had to use IncludeInferiors to draw to the parent
256        * This isn't useful for our purposes, so require 0.4
257        */
258       display_x11->have_xcomposite = major > 0 || (major == 0 && minor >= 4);
259     }
260   else
261 #endif
262     display_x11->have_xcomposite = FALSE;
263
264 #ifdef HAVE_XDAMAGE
265   if (XDamageQueryExtension (display_x11->xdisplay,
266                              &display_x11->xdamage_event_base,
267                              &ignore))
268     {
269       display_x11->have_xdamage = TRUE;
270
271       gdk_x11_register_standard_event_type (display,
272                                             display_x11->xdamage_event_base,
273                                             XDamageNumberEvents);
274     }
275   else
276 #endif
277     display_x11->have_xdamage = FALSE;
278
279   display_x11->have_shapes = FALSE;
280   display_x11->have_input_shapes = FALSE;
281
282   if (XShapeQueryExtension (GDK_DISPLAY_XDISPLAY (display), &ignore, &ignore))
283     {
284       display_x11->have_shapes = TRUE;
285 #ifdef ShapeInput             
286       if (XShapeQueryVersion (GDK_DISPLAY_XDISPLAY (display), &maj, &min))
287         display_x11->have_input_shapes = (maj == 1 && min >= 1);
288 #endif
289     }
290
291   display_x11->trusted_client = TRUE;
292   {
293     Window root, child;
294     int rootx, rooty, winx, winy;
295     unsigned int xmask;
296
297     gdk_error_trap_push ();
298     XQueryPointer (display_x11->xdisplay, 
299                    GDK_SCREEN_X11 (display_x11->default_screen)->xroot_window,
300                    &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
301     gdk_flush ();
302     if (G_UNLIKELY (gdk_error_trap_pop () == BadWindow)) 
303       {
304         g_warning ("Connection to display %s appears to be untrusted. Pointer and keyboard grabs and inter-client communication may not work as expected.", gdk_display_get_name (display));
305         display_x11->trusted_client = FALSE;
306       }
307   }
308
309   if (_gdk_synchronize)
310     XSynchronize (display_x11->xdisplay, True);
311   
312   class_hint = XAllocClassHint();
313   class_hint->res_name = g_get_prgname ();
314   
315   class_hint->res_class = (char *)gdk_get_program_class ();
316
317   /* XmbSetWMProperties sets the RESOURCE_NAME environment variable
318    * from argv[0], so we just synthesize an argument array here.
319    */
320   argc = 1;
321   argv[0] = g_get_prgname ();
322   
323   XmbSetWMProperties (display_x11->xdisplay,
324                       display_x11->leader_window,
325                       NULL, NULL, argv, argc, NULL, NULL,
326                       class_hint);
327   XFree (class_hint);
328
329   sm_client_id = _gdk_get_sm_client_id ();
330   if (sm_client_id)
331     _gdk_windowing_display_set_sm_client_id (display, sm_client_id);
332
333   pid = getpid ();
334   XChangeProperty (display_x11->xdisplay,
335                    display_x11->leader_window,
336                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"),
337                    XA_CARDINAL, 32, PropModeReplace, (guchar *) & pid, 1);
338
339   /* We don't yet know a valid time. */
340   display_x11->user_time = 0;
341   
342 #ifdef HAVE_XKB
343   {
344     gint xkb_major = XkbMajorVersion;
345     gint xkb_minor = XkbMinorVersion;
346     if (XkbLibraryVersion (&xkb_major, &xkb_minor))
347       {
348         xkb_major = XkbMajorVersion;
349         xkb_minor = XkbMinorVersion;
350             
351         if (XkbQueryExtension (display_x11->xdisplay, 
352                                NULL, &display_x11->xkb_event_type, NULL,
353                                &xkb_major, &xkb_minor))
354           {
355             Bool detectable_autorepeat_supported;
356             
357             display_x11->use_xkb = TRUE;
358
359             XkbSelectEvents (display_x11->xdisplay,
360                              XkbUseCoreKbd,
361                              XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask,
362                              XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask);
363
364             /* keep this in sync with _gdk_keymap_state_changed() */ 
365             XkbSelectEventDetails (display_x11->xdisplay,
366                                    XkbUseCoreKbd, XkbStateNotify,
367                                    XkbAllStateComponentsMask,
368                                    XkbGroupLockMask|XkbModifierLockMask);
369
370             XkbSetDetectableAutoRepeat (display_x11->xdisplay,
371                                         True,
372                                         &detectable_autorepeat_supported);
373
374             GDK_NOTE (MISC, g_message ("Detectable autorepeat %s.",
375                                        detectable_autorepeat_supported ? 
376                                        "supported" : "not supported"));
377             
378             display_x11->have_xkb_autorepeat = detectable_autorepeat_supported;
379           }
380       }
381   }
382 #endif
383
384   display_x11->use_sync = FALSE;
385 #ifdef HAVE_XSYNC
386   {
387     int major, minor;
388     int error_base, event_base;
389     
390     if (XSyncQueryExtension (display_x11->xdisplay,
391                              &event_base, &error_base) &&
392         XSyncInitialize (display_x11->xdisplay,
393                          &major, &minor))
394       display_x11->use_sync = TRUE;
395   }
396 #endif
397   
398   _gdk_windowing_image_init (display);
399   _gdk_events_init (display);
400   _gdk_input_init (display);
401   _gdk_dnd_init (display);
402
403   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
404     gdk_display_request_selection_notification (display, 
405                                                 GDK_SCREEN_X11 (display_x11->screens[i])->cm_selection_atom);
406
407   g_signal_emit_by_name (gdk_display_manager_get(),
408                          "display_opened", display);
409
410   return display;
411 }
412
413 #ifdef HAVE_X11R6
414 /*
415  * XLib internal connection handling
416  */
417 typedef struct _GdkInternalConnection GdkInternalConnection;
418
419 struct _GdkInternalConnection
420 {
421   gint           fd;
422   GSource       *source;
423   Display       *display;
424 };
425
426 static gboolean
427 process_internal_connection (GIOChannel  *gioc,
428                              GIOCondition cond,
429                              gpointer     data)
430 {
431   GdkInternalConnection *connection = (GdkInternalConnection *)data;
432
433   GDK_THREADS_ENTER ();
434
435   XProcessInternalConnection ((Display*)connection->display, connection->fd);
436
437   GDK_THREADS_LEAVE ();
438
439   return TRUE;
440 }
441
442 static GdkInternalConnection *
443 gdk_add_connection_handler (Display *display,
444                             guint    fd)
445 {
446   GIOChannel *io_channel;
447   GdkInternalConnection *connection;
448
449   connection = g_new (GdkInternalConnection, 1);
450
451   connection->fd = fd;
452   connection->display = display;
453   
454   io_channel = g_io_channel_unix_new (fd);
455   
456   connection->source = g_io_create_watch (io_channel, G_IO_IN);
457   g_source_set_callback (connection->source,
458                          (GSourceFunc)process_internal_connection, connection, NULL);
459   g_source_attach (connection->source, NULL);
460   
461   g_io_channel_unref (io_channel);
462   
463   return connection;
464 }
465
466 static void
467 gdk_remove_connection_handler (GdkInternalConnection *connection)
468 {
469   g_source_destroy (connection->source);
470   g_free (connection);
471 }
472
473 static void
474 gdk_internal_connection_watch (Display  *display,
475                                XPointer  arg,
476                                gint      fd,
477                                gboolean  opening,
478                                XPointer *watch_data)
479 {
480   if (opening)
481     *watch_data = (XPointer)gdk_add_connection_handler (display, fd);
482   else
483     gdk_remove_connection_handler ((GdkInternalConnection *)*watch_data);
484 }
485 #endif /* HAVE_X11R6 */
486
487 /**
488  * gdk_display_get_name:
489  * @display: a #GdkDisplay
490  *
491  * Gets the name of the display.
492  * 
493  * Returns: a string representing the display name. This string is owned
494  * by GDK and should not be modified or freed.
495  * 
496  * Since: 2.2
497  */
498 G_CONST_RETURN gchar *
499 gdk_display_get_name (GdkDisplay *display)
500 {
501   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
502   
503   return (gchar *) DisplayString (GDK_DISPLAY_X11 (display)->xdisplay);
504 }
505
506 /**
507  * gdk_display_get_n_screens:
508  * @display: a #GdkDisplay
509  *
510  * Gets the number of screen managed by the @display.
511  * 
512  * Returns: number of screens.
513  * 
514  * Since: 2.2
515  */
516 gint
517 gdk_display_get_n_screens (GdkDisplay *display)
518 {
519   g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
520   
521   return ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay);
522 }
523
524 /**
525  * gdk_display_get_screen:
526  * @display: a #GdkDisplay
527  * @screen_num: the screen number
528  *
529  * Returns a screen object for one of the screens of the display.
530  *
531  * Returns: the #GdkScreen object
532  *
533  * Since: 2.2
534  */
535 GdkScreen *
536 gdk_display_get_screen (GdkDisplay *display, 
537                         gint        screen_num)
538 {
539   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
540   g_return_val_if_fail (ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay) > screen_num, NULL);
541   
542   return GDK_DISPLAY_X11 (display)->screens[screen_num];
543 }
544
545 /**
546  * gdk_display_get_default_screen:
547  * @display: a #GdkDisplay
548  *
549  * Get the default #GdkScreen for @display.
550  * 
551  * Returns: the default #GdkScreen object for @display
552  *
553  * Since: 2.2
554  */
555 GdkScreen *
556 gdk_display_get_default_screen (GdkDisplay *display)
557 {
558   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
559   
560   return GDK_DISPLAY_X11 (display)->default_screen;
561 }
562
563 gboolean
564 _gdk_x11_display_is_root_window (GdkDisplay *display,
565                                  Window      xroot_window)
566 {
567   GdkDisplayX11 *display_x11;
568   gint i;
569   
570   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
571   
572   display_x11 = GDK_DISPLAY_X11 (display);
573   
574   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
575     {
576       if (GDK_SCREEN_XROOTWIN (display_x11->screens[i]) == xroot_window)
577         return TRUE;
578     }
579   return FALSE;
580 }
581
582 #define XSERVER_TIME_IS_LATER(time1, time2)                        \
583   ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
584     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
585   )
586
587 /**
588  * gdk_display_pointer_ungrab:
589  * @display: a #GdkDisplay.
590  * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
591  *
592  * Release any pointer grab.
593  *
594  * Since: 2.2
595  */
596 void
597 gdk_display_pointer_ungrab (GdkDisplay *display,
598                             guint32     time)
599 {
600   Display *xdisplay;
601   GdkDisplayX11 *display_x11;
602
603   g_return_if_fail (GDK_IS_DISPLAY (display));
604
605   display_x11 = GDK_DISPLAY_X11 (display);
606   xdisplay = GDK_DISPLAY_XDISPLAY (display);
607   
608   _gdk_input_ungrab_pointer (display, time);
609   XUngrabPointer (xdisplay, time);
610   XFlush (xdisplay);
611
612   if (time == GDK_CURRENT_TIME || 
613       display_x11->pointer_xgrab_time == GDK_CURRENT_TIME ||
614       !XSERVER_TIME_IS_LATER (display_x11->pointer_xgrab_time, time))
615     display_x11->pointer_xgrab_window = NULL;
616 }
617
618 /**
619  * gdk_display_pointer_is_grabbed:
620  * @display: a #GdkDisplay
621  *
622  * Test if the pointer is grabbed.
623  *
624  * Returns: %TRUE if an active X pointer grab is in effect
625  *
626  * Since: 2.2
627  */
628 gboolean
629 gdk_display_pointer_is_grabbed (GdkDisplay *display)
630 {
631   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
632   
633   return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL &&
634           !GDK_DISPLAY_X11 (display)->pointer_xgrab_implicit);
635 }
636
637 /**
638  * gdk_display_keyboard_ungrab:
639  * @display: a #GdkDisplay.
640  * @time_: a timestap (e.g #GDK_CURRENT_TIME).
641  *
642  * Release any keyboard grab
643  *
644  * Since: 2.2
645  */
646 void
647 gdk_display_keyboard_ungrab (GdkDisplay *display,
648                              guint32     time)
649 {
650   Display *xdisplay;
651   GdkDisplayX11 *display_x11;
652   
653   g_return_if_fail (GDK_IS_DISPLAY (display));
654
655   display_x11 = GDK_DISPLAY_X11 (display);
656   xdisplay = GDK_DISPLAY_XDISPLAY (display);
657   
658   XUngrabKeyboard (xdisplay, time);
659   XFlush (xdisplay);
660   
661   if (time == GDK_CURRENT_TIME || 
662       display_x11->keyboard_xgrab_time == GDK_CURRENT_TIME ||
663       !XSERVER_TIME_IS_LATER (display_x11->keyboard_xgrab_time, time))
664     display_x11->keyboard_xgrab_window = NULL;
665 }
666
667 /**
668  * gdk_display_beep:
669  * @display: a #GdkDisplay
670  *
671  * Emits a short beep on @display
672  *
673  * Since: 2.2
674  */
675 void
676 gdk_display_beep (GdkDisplay *display)
677 {
678   g_return_if_fail (GDK_IS_DISPLAY (display));
679   
680   XBell (GDK_DISPLAY_XDISPLAY (display), 0);
681 }
682
683 /**
684  * gdk_display_sync:
685  * @display: a #GdkDisplay
686  *
687  * Flushes any requests queued for the windowing system and waits until all
688  * requests have been handled. This is often used for making sure that the
689  * display is synchronized with the current state of the program. Calling
690  * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors
691  * generated from earlier requests are handled before the error trap is 
692  * removed.
693  *
694  * This is most useful for X11. On windowing systems where requests are
695  * handled synchronously, this function will do nothing.
696  *
697  * Since: 2.2
698  */
699 void
700 gdk_display_sync (GdkDisplay *display)
701 {
702   g_return_if_fail (GDK_IS_DISPLAY (display));
703   
704   XSync (GDK_DISPLAY_XDISPLAY (display), False);
705 }
706
707 /**
708  * gdk_display_flush:
709  * @display: a #GdkDisplay
710  *
711  * Flushes any requests queued for the windowing system; this happens automatically
712  * when the main loop blocks waiting for new events, but if your application
713  * is drawing without returning control to the main loop, you may need
714  * to call this function explicitely. A common case where this function
715  * needs to be called is when an application is executing drawing commands
716  * from a thread other than the thread where the main loop is running.
717  *
718  * This is most useful for X11. On windowing systems where requests are
719  * handled synchronously, this function will do nothing.
720  *
721  * Since: 2.4
722  */
723 void 
724 gdk_display_flush (GdkDisplay *display)
725 {
726   g_return_if_fail (GDK_IS_DISPLAY (display));
727
728   if (!display->closed)
729     XFlush (GDK_DISPLAY_XDISPLAY (display));
730 }
731
732 /**
733  * gdk_display_get_default_group:
734  * @display: a #GdkDisplay
735  * 
736  * Returns the default group leader window for all toplevel windows
737  * on @display. This window is implicitly created by GDK. 
738  * See gdk_window_set_group().
739  * 
740  * Return value: The default group leader window for @display
741  *
742  * Since: 2.4
743  **/
744 GdkWindow *
745 gdk_display_get_default_group (GdkDisplay *display)
746 {
747   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
748
749   return GDK_DISPLAY_X11 (display)->leader_gdk_window;
750 }
751
752 /**
753  * gdk_x11_display_grab:
754  * @display: a #GdkDisplay 
755  * 
756  * Call XGrabServer() on @display. 
757  * To ungrab the display again, use gdk_x11_display_ungrab(). 
758  *
759  * gdk_x11_display_grab()/gdk_x11_display_ungrab() calls can be nested.
760  *
761  * Since: 2.2
762  **/
763 void
764 gdk_x11_display_grab (GdkDisplay *display)
765 {
766   GdkDisplayX11 *display_x11;
767   
768   g_return_if_fail (GDK_IS_DISPLAY (display));
769   
770   display_x11 = GDK_DISPLAY_X11 (display);
771   
772   if (display_x11->grab_count == 0)
773     XGrabServer (display_x11->xdisplay);
774   display_x11->grab_count++;
775 }
776
777 /**
778  * gdk_x11_display_ungrab:
779  * @display: a #GdkDisplay
780  * 
781  * Ungrab @display after it has been grabbed with 
782  * gdk_x11_display_grab(). 
783  *
784  * Since: 2.2
785  **/
786 void
787 gdk_x11_display_ungrab (GdkDisplay *display)
788 {
789   GdkDisplayX11 *display_x11;
790   
791   g_return_if_fail (GDK_IS_DISPLAY (display));
792   
793   display_x11 = GDK_DISPLAY_X11 (display);;
794   g_return_if_fail (display_x11->grab_count > 0);
795   
796   display_x11->grab_count--;
797   if (display_x11->grab_count == 0)
798     {
799       XUngrabServer (display_x11->xdisplay);
800       XFlush (display_x11->xdisplay);
801     }
802 }
803
804 static void
805 gdk_display_x11_dispose (GObject *object)
806 {
807   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
808   gint           i;
809
810   g_list_foreach (display_x11->input_devices, (GFunc) g_object_run_dispose, NULL);
811
812   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
813     _gdk_screen_close (display_x11->screens[i]);
814
815   _gdk_events_uninit (GDK_DISPLAY_OBJECT (object));
816
817   G_OBJECT_CLASS (_gdk_display_x11_parent_class)->dispose (object);
818 }
819
820 static void
821 gdk_display_x11_finalize (GObject *object)
822 {
823   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
824   gint           i;
825
826   /* Keymap */
827   if (display_x11->keymap)
828     g_object_unref (display_x11->keymap);
829
830   /* Free motif Dnd */
831   if (display_x11->motif_target_lists)
832     {
833       for (i = 0; i < display_x11->motif_n_target_lists; i++)
834         g_list_free (display_x11->motif_target_lists[i]);
835       g_free (display_x11->motif_target_lists);
836     }
837
838   _gdk_x11_cursor_display_finalize (GDK_DISPLAY_OBJECT(display_x11));
839
840   /* Atom Hashtable */
841   g_hash_table_destroy (display_x11->atom_from_virtual);
842   g_hash_table_destroy (display_x11->atom_to_virtual);
843
844   /* Leader Window */
845   XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);
846
847   /* list of filters for client messages */
848   g_list_foreach (display_x11->client_filters, (GFunc) g_free, NULL);
849   g_list_free (display_x11->client_filters);
850
851   /* List of event window extraction functions */
852   g_slist_foreach (display_x11->event_types, (GFunc)g_free, NULL);
853   g_slist_free (display_x11->event_types);
854
855   /* input GdkDevice list */
856   g_list_foreach (display_x11->input_devices, (GFunc) g_object_unref, NULL);
857   g_list_free (display_x11->input_devices);
858
859   /* input GdkWindow list */
860   g_list_foreach (display_x11->input_windows, (GFunc) g_free, NULL);
861   g_list_free (display_x11->input_windows);
862
863   /* Free all GdkScreens */
864   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
865     g_object_unref (display_x11->screens[i]);
866   g_free (display_x11->screens);
867
868   g_free (display_x11->startup_notification_id);
869
870   /* X ID hashtable */
871   g_hash_table_destroy (display_x11->xid_ht);
872
873   XCloseDisplay (display_x11->xdisplay);
874
875   G_OBJECT_CLASS (_gdk_display_x11_parent_class)->finalize (object);
876 }
877
878 /**
879  * gdk_x11_lookup_xdisplay:
880  * @xdisplay: a pointer to an X Display
881  * 
882  * Find the #GdkDisplay corresponding to @display, if any exists.
883  * 
884  * Return value: the #GdkDisplay, if found, otherwise %NULL.
885  *
886  * Since: 2.2
887  **/
888 GdkDisplay *
889 gdk_x11_lookup_xdisplay (Display *xdisplay)
890 {
891   GSList *tmp_list;
892
893   for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
894     {
895       if (GDK_DISPLAY_XDISPLAY (tmp_list->data) == xdisplay)
896         return tmp_list->data;
897     }
898   
899   return NULL;
900 }
901
902 /**
903  * _gdk_x11_display_screen_for_xrootwin:
904  * @display: a #GdkDisplay
905  * @xrootwin: window ID for one of of the screen's of the display.
906  * 
907  * Given the root window ID of one of the screen's of a #GdkDisplay,
908  * finds the screen.
909  * 
910  * Return value: the #GdkScreen corresponding to @xrootwin, or %NULL.
911  **/
912 GdkScreen *
913 _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
914                                       Window      xrootwin)
915 {
916   gint i;
917
918   for (i = 0; i < ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay); i++)
919     {
920       GdkScreen *screen = gdk_display_get_screen (display, i);
921       if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
922         return screen;
923     }
924
925   return NULL;
926 }
927
928 /**
929  * gdk_x11_display_get_xdisplay:
930  * @display: a #GdkDisplay
931  * @returns: an X display.
932  *
933  * Returns the X display of a #GdkDisplay.
934  *
935  * Since: 2.2
936  */
937 Display *
938 gdk_x11_display_get_xdisplay (GdkDisplay *display)
939 {
940   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
941   return GDK_DISPLAY_X11 (display)->xdisplay;
942 }
943
944 void
945 _gdk_windowing_set_default_display (GdkDisplay *display)
946 {
947   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
948   const gchar *startup_id;
949   
950   if (!display)
951     {
952       gdk_display = NULL;
953       return;
954     }
955
956   gdk_display = GDK_DISPLAY_XDISPLAY (display);
957
958   g_free (display_x11->startup_notification_id);
959   display_x11->startup_notification_id = NULL;
960   
961   startup_id = g_getenv ("DESKTOP_STARTUP_ID");
962   if (startup_id && *startup_id != '\0')
963     {
964       gchar *time_str;
965
966       if (!g_utf8_validate (startup_id, -1, NULL))
967         g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
968       else
969         display_x11->startup_notification_id = g_strdup (startup_id);
970
971       /* Find the launch time from the startup_id, if it's there.  Newer spec
972        * states that the startup_id is of the form <unique>_TIME<timestamp>
973        */
974       time_str = g_strrstr (startup_id, "_TIME");
975       if (time_str != NULL)
976         {
977           gulong retval;
978           gchar *end;
979           errno = 0;
980
981           /* Skip past the "_TIME" part */
982           time_str += 5;
983
984           retval = strtoul (time_str, &end, 0);
985           if (end != time_str && errno == 0)
986             display_x11->user_time = retval;
987         }
988       
989       /* Clear the environment variable so it won't be inherited by
990        * child processes and confuse things.  
991        */
992       g_unsetenv ("DESKTOP_STARTUP_ID");
993
994       /* Set the startup id on the leader window so it
995        * applies to all windows we create on this display
996        */
997       XChangeProperty (display_x11->xdisplay,
998                        display_x11->leader_window,
999                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
1000                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
1001                        PropModeReplace,
1002                        (guchar *)startup_id, strlen (startup_id));
1003     }
1004 }
1005
1006 static void
1007 broadcast_xmessage (GdkDisplay *display,
1008                     const char *message_type,
1009                     const char *message_type_begin,
1010                     const char *message)
1011 {
1012   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1013   GdkScreen *screen = gdk_display_get_default_screen (display);
1014   GdkWindow *root_window = gdk_screen_get_root_window (screen);
1015   Window xroot_window = GDK_WINDOW_XID (root_window);
1016   
1017   Atom type_atom;
1018   Atom type_atom_begin;
1019   Window xwindow;
1020
1021   if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
1022     return;
1023
1024   {
1025     XSetWindowAttributes attrs;
1026
1027     attrs.override_redirect = True;
1028     attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
1029
1030     xwindow =
1031       XCreateWindow (xdisplay,
1032                      xroot_window,
1033                      -100, -100, 1, 1,
1034                      0,
1035                      CopyFromParent,
1036                      CopyFromParent,
1037                      (Visual *)CopyFromParent,
1038                      CWOverrideRedirect | CWEventMask,
1039                      &attrs);
1040   }
1041
1042   type_atom = gdk_x11_get_xatom_by_name_for_display (display,
1043                                                      message_type);
1044   type_atom_begin = gdk_x11_get_xatom_by_name_for_display (display,
1045                                                            message_type_begin);
1046   
1047   {
1048     XClientMessageEvent xclient;
1049     const char *src;
1050     const char *src_end;
1051     char *dest;
1052     char *dest_end;
1053     
1054                 memset(&xclient, 0, sizeof (xclient));
1055     xclient.type = ClientMessage;
1056     xclient.message_type = type_atom_begin;
1057     xclient.display =xdisplay;
1058     xclient.window = xwindow;
1059     xclient.format = 8;
1060
1061     src = message;
1062     src_end = message + strlen (message) + 1; /* +1 to include nul byte */
1063     
1064     while (src != src_end)
1065       {
1066         dest = &xclient.data.b[0];
1067         dest_end = dest + 20;        
1068         
1069         while (dest != dest_end &&
1070                src != src_end)
1071           {
1072             *dest = *src;
1073             ++dest;
1074             ++src;
1075           }
1076
1077         while (dest != dest_end)
1078           {
1079             *dest = 0;
1080             ++dest;
1081           }
1082         
1083         XSendEvent (xdisplay,
1084                     xroot_window,
1085                     False,
1086                     PropertyChangeMask,
1087                     (XEvent *)&xclient);
1088
1089         xclient.message_type = type_atom;
1090       }
1091   }
1092
1093   XDestroyWindow (xdisplay, xwindow);
1094   XFlush (xdisplay);
1095 }
1096
1097 /**
1098  * gdk_x11_display_broadcast_startup_message:
1099  * @display: a #GdkDisplay
1100  * @message_type: startup notification message type ("new", "change",
1101  * or "remove")
1102  * @...: a list of key/value pairs (as strings), terminated by a
1103  * %NULL key. (A %NULL value for a key will cause that key to be
1104  * skipped in the output.)
1105  *
1106  * Sends a startup notification message of type @message_type to
1107  * @display. 
1108  *
1109  * This is a convenience function for use by code that implements the
1110  * freedesktop startup notification specification. Applications should
1111  * not normally need to call it directly. See the <ulink
1112  * url="http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt">Startup
1113  * Notification Protocol specification</ulink> for
1114  * definitions of the message types and keys that can be used.
1115  *
1116  * Since: 2.12
1117  **/
1118 void
1119 gdk_x11_display_broadcast_startup_message (GdkDisplay *display,
1120                                            const char *message_type,
1121                                            ...)
1122 {
1123   GString *message;
1124   va_list ap;
1125   const char *key, *value, *p;
1126
1127   message = g_string_new (message_type);
1128   g_string_append_c (message, ':');
1129
1130   va_start (ap, message_type);
1131   while ((key = va_arg (ap, const char *)))
1132     {
1133       value = va_arg (ap, const char *);
1134       if (!value)
1135         continue;
1136
1137       g_string_append_printf (message, " %s=\"", key);
1138       for (p = value; *p; p++)
1139         {
1140           switch (*p)
1141             {
1142             case ' ':
1143             case '"':
1144             case '\\':
1145               g_string_append_c (message, '\\');
1146               break;
1147             }
1148
1149           g_string_append_c (message, *p);
1150         }
1151       g_string_append_c (message, '\"');
1152     }
1153   va_end (ap);
1154
1155   broadcast_xmessage (display,
1156                       "_NET_STARTUP_INFO",
1157                       "_NET_STARTUP_INFO_BEGIN",
1158                       message->str);
1159
1160   g_string_free (message, TRUE);
1161 }
1162
1163 /**
1164  * gdk_notify_startup_complete:
1165  * 
1166  * Indicates to the GUI environment that the application has finished
1167  * loading. If the applications opens windows, this function is
1168  * normally called after opening the application's initial set of
1169  * windows.
1170  * 
1171  * GTK+ will call this function automatically after opening the first
1172  * #GtkWindow unless gtk_window_set_auto_startup_notification() is called 
1173  * to disable that feature.
1174  *
1175  * Since: 2.2
1176  **/
1177 void
1178 gdk_notify_startup_complete (void)
1179 {
1180   GdkDisplay *display;
1181   GdkDisplayX11 *display_x11;
1182
1183   display = gdk_display_get_default ();
1184   if (!display)
1185     return;
1186   
1187   display_x11 = GDK_DISPLAY_X11 (display);
1188
1189   if (display_x11->startup_notification_id == NULL)
1190     return;
1191
1192   gdk_notify_startup_complete_with_id (display_x11->startup_notification_id);
1193 }
1194
1195 /**
1196  * gdk_notify_startup_complete_with_id:
1197  * @startup_id: a startup-notification identifier, for which notification
1198  *              process should be completed
1199  * 
1200  * Indicates to the GUI environment that the application has finished
1201  * loading, using a given identifier.
1202  * 
1203  * GTK+ will call this function automatically for #GtkWindow with custom
1204  * startup-notification identifier unless
1205  * gtk_window_set_auto_startup_notification() is called to disable
1206  * that feature.
1207  *
1208  * Since: 2.12
1209  **/
1210 void
1211 gdk_notify_startup_complete_with_id (const gchar* startup_id)
1212 {
1213   GdkDisplay *display;
1214
1215   display = gdk_display_get_default ();
1216   if (!display)
1217     return;
1218
1219   gdk_x11_display_broadcast_startup_message (display, "remove",
1220                                              "ID", startup_id,
1221                                              NULL);
1222 }
1223
1224 /**
1225  * gdk_display_supports_selection_notification:
1226  * @display: a #GdkDisplay
1227  * 
1228  * Returns whether #GdkEventOwnerChange events will be 
1229  * sent when the owner of a selection changes.
1230  * 
1231  * Return value: whether #GdkEventOwnerChange events will 
1232  *               be sent.
1233  *
1234  * Since: 2.6
1235  **/
1236 gboolean 
1237 gdk_display_supports_selection_notification (GdkDisplay *display)
1238 {
1239   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1240
1241   return display_x11->have_xfixes;
1242 }
1243
1244 /**
1245  * gdk_display_request_selection_notification:
1246  * @display: a #GdkDisplay
1247  * @selection: the #GdkAtom naming the selection for which
1248  *             ownership change notification is requested
1249  * 
1250  * Request #GdkEventOwnerChange events for ownership changes
1251  * of the selection named by the given atom.
1252  * 
1253  * Return value: whether #GdkEventOwnerChange events will 
1254  *               be sent.
1255  *
1256  * Since: 2.6
1257  **/
1258 gboolean
1259 gdk_display_request_selection_notification (GdkDisplay *display,
1260                                             GdkAtom     selection)
1261
1262 {
1263 #ifdef HAVE_XFIXES
1264   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1265   Atom atom;
1266
1267   if (display_x11->have_xfixes)
1268     {
1269       atom = gdk_x11_atom_to_xatom_for_display (display, 
1270                                                 selection);
1271       XFixesSelectSelectionInput (display_x11->xdisplay, 
1272                                   display_x11->leader_window,
1273                                   atom,
1274                                   XFixesSetSelectionOwnerNotifyMask |
1275                                   XFixesSelectionWindowDestroyNotifyMask |
1276                                   XFixesSelectionClientCloseNotifyMask);
1277       return TRUE;
1278     }
1279   else
1280 #endif
1281     return FALSE;
1282 }
1283
1284 /**
1285  * gdk_display_supports_clipboard_persistence
1286  * @display: a #GdkDisplay
1287  *
1288  * Returns whether the speicifed display supports clipboard
1289  * persistance; i.e. if it's possible to store the clipboard data after an
1290  * application has quit. On X11 this checks if a clipboard daemon is
1291  * running.
1292  *
1293  * Returns: %TRUE if the display supports clipboard persistance.
1294  *
1295  * Since: 2.6
1296  */
1297 gboolean
1298 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
1299 {
1300   Atom clipboard_manager;
1301
1302   /* It might make sense to cache this */
1303   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
1304   return XGetSelectionOwner (GDK_DISPLAY_X11 (display)->xdisplay, clipboard_manager) != None;
1305 }
1306
1307 /**
1308  * gdk_display_store_clipboard
1309  * @display:          a #GdkDisplay
1310  * @clipboard_window: a #GdkWindow belonging to the clipboard owner
1311  * @time_:            a timestamp
1312  * @targets:          an array of targets that should be saved, or %NULL 
1313  *                    if all available targets should be saved.
1314  * @n_targets:        length of the @targets array
1315  *
1316  * Issues a request to the clipboard manager to store the
1317  * clipboard data. On X11, this is a special program that works
1318  * according to the freedesktop clipboard specification, available at
1319  * <ulink url="http://www.freedesktop.org/Standards/clipboard-manager-spec">
1320  * http://www.freedesktop.org/Standards/clipboard-manager-spec</ulink>.
1321  *
1322  * Since: 2.6
1323  */
1324 void
1325 gdk_display_store_clipboard (GdkDisplay    *display,
1326                              GdkWindow     *clipboard_window,
1327                              guint32        time_,
1328                              const GdkAtom *targets,
1329                              gint           n_targets)
1330 {
1331   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1332   Atom clipboard_manager, save_targets;
1333   
1334   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
1335   save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
1336
1337   gdk_error_trap_push ();
1338
1339   if (XGetSelectionOwner (display_x11->xdisplay, clipboard_manager) != None)
1340     {
1341       Atom property_name = None;
1342       Atom *xatoms;
1343       int i;
1344       
1345       if (n_targets > 0)
1346         {
1347           property_name = gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property);
1348
1349           xatoms = g_new (Atom, n_targets);
1350           for (i = 0; i < n_targets; i++)
1351             xatoms[i] = gdk_x11_atom_to_xatom_for_display (display, targets[i]);
1352
1353           XChangeProperty (display_x11->xdisplay, GDK_WINDOW_XID (clipboard_window),
1354                            property_name, XA_ATOM,
1355                            32, PropModeReplace, (guchar *)xatoms, n_targets);
1356           g_free (xatoms);
1357
1358         }
1359       
1360       XConvertSelection (display_x11->xdisplay,
1361                          clipboard_manager, save_targets, property_name,
1362                          GDK_WINDOW_XID (clipboard_window), time_);
1363       
1364     }
1365   gdk_error_trap_pop ();
1366
1367 }
1368
1369 /**
1370  * gdk_x11_display_get_user_time:
1371  * @display: a #GdkDisplay
1372  *
1373  * Returns the timestamp of the last user interaction on 
1374  * @display. The timestamp is taken from events caused
1375  * by user interaction such as key presses or pointer 
1376  * movements. See gdk_x11_window_set_user_time().
1377  *
1378  * Returns: the timestamp of the last user interaction 
1379  *
1380  * Since: 2.8
1381  */
1382 guint32
1383 gdk_x11_display_get_user_time (GdkDisplay *display)
1384 {
1385   return GDK_DISPLAY_X11 (display)->user_time;
1386 }
1387
1388 /**
1389  * gdk_display_supports_shapes:
1390  * @display: a #GdkDisplay
1391  *
1392  * Returns %TRUE if gdk_window_shape_combine_mask() can
1393  * be used to create shaped windows on @display.
1394  *
1395  * Returns: %TRUE if shaped windows are supported 
1396  *
1397  * Since: 2.10
1398  */
1399 gboolean 
1400 gdk_display_supports_shapes (GdkDisplay *display)
1401 {
1402   return GDK_DISPLAY_X11 (display)->have_shapes;
1403 }
1404
1405 /**
1406  * gdk_display_supports_input_shapes:
1407  * @display: a #GdkDisplay
1408  *
1409  * Returns %TRUE if gdk_window_input_shape_combine_mask() can
1410  * be used to modify the input shape of windows on @display.
1411  *
1412  * Returns: %TRUE if windows with modified input shape are supported 
1413  *
1414  * Since: 2.10
1415  */
1416 gboolean 
1417 gdk_display_supports_input_shapes (GdkDisplay *display)
1418 {
1419   return GDK_DISPLAY_X11 (display)->have_input_shapes;
1420 }
1421
1422
1423 /**
1424  * gdk_x11_display_get_startup_notification_id:
1425  * @display: a #GdkDisplay
1426  *
1427  * Gets the startup notification ID for a display.
1428  * 
1429  * Returns: the startup notification ID for @display
1430  *
1431  * Since: 2.12
1432  */
1433 G_CONST_RETURN gchar *
1434 gdk_x11_display_get_startup_notification_id (GdkDisplay *display)
1435 {
1436   return GDK_DISPLAY_X11 (display)->startup_notification_id;
1437 }
1438
1439 /**
1440  * gdk_display_supports_composite:
1441  * @display: a #GdkDisplay
1442  *
1443  * Returns %TRUE if gdk_window_set_composited() can be used
1444  * to redirect drawing on the window using compositing.
1445  *
1446  * Currently this only works on X11 with XComposite and
1447  * XDamage extensions available.
1448  *
1449  * Returns: %TRUE if windows may be composited.
1450  *
1451  * Since: 2.12
1452  */
1453 gboolean
1454 gdk_display_supports_composite (GdkDisplay *display)
1455 {
1456   GdkDisplayX11 *x11_display = GDK_DISPLAY_X11 (display);
1457
1458   return x11_display->have_xcomposite &&
1459          x11_display->have_xdamage &&
1460          x11_display->have_xfixes;
1461 }
1462
1463
1464 #define __GDK_DISPLAY_X11_C__
1465 #include "gdkaliasdef.c"