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