]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdisplay-x11.c
Make the !xkb build survive a little longer
[~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), &display_x11->shape_event_base, &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 #ifdef HAVE_XKB
694   XkbBell (GDK_DISPLAY_XDISPLAY (display), None, 0, None);
695 #else
696   XBell (GDK_DISPLAY_XDISPLAY (display), 0);
697 #endif
698 }
699
700 /**
701  * gdk_display_sync:
702  * @display: a #GdkDisplay
703  *
704  * Flushes any requests queued for the windowing system and waits until all
705  * requests have been handled. This is often used for making sure that the
706  * display is synchronized with the current state of the program. Calling
707  * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors
708  * generated from earlier requests are handled before the error trap is 
709  * removed.
710  *
711  * This is most useful for X11. On windowing systems where requests are
712  * handled synchronously, this function will do nothing.
713  *
714  * Since: 2.2
715  */
716 void
717 gdk_display_sync (GdkDisplay *display)
718 {
719   g_return_if_fail (GDK_IS_DISPLAY (display));
720   
721   XSync (GDK_DISPLAY_XDISPLAY (display), False);
722 }
723
724 /**
725  * gdk_display_flush:
726  * @display: a #GdkDisplay
727  *
728  * Flushes any requests queued for the windowing system; this happens automatically
729  * when the main loop blocks waiting for new events, but if your application
730  * is drawing without returning control to the main loop, you may need
731  * to call this function explicitely. A common case where this function
732  * needs to be called is when an application is executing drawing commands
733  * from a thread other than the thread where the main loop is running.
734  *
735  * This is most useful for X11. On windowing systems where requests are
736  * handled synchronously, this function will do nothing.
737  *
738  * Since: 2.4
739  */
740 void 
741 gdk_display_flush (GdkDisplay *display)
742 {
743   g_return_if_fail (GDK_IS_DISPLAY (display));
744
745   if (!display->closed)
746     XFlush (GDK_DISPLAY_XDISPLAY (display));
747 }
748
749 /**
750  * gdk_display_get_default_group:
751  * @display: a #GdkDisplay
752  * 
753  * Returns the default group leader window for all toplevel windows
754  * on @display. This window is implicitly created by GDK. 
755  * See gdk_window_set_group().
756  * 
757  * Return value: The default group leader window for @display
758  *
759  * Since: 2.4
760  **/
761 GdkWindow *
762 gdk_display_get_default_group (GdkDisplay *display)
763 {
764   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
765
766   return GDK_DISPLAY_X11 (display)->leader_gdk_window;
767 }
768
769 /**
770  * gdk_x11_display_grab:
771  * @display: a #GdkDisplay 
772  * 
773  * Call XGrabServer() on @display. 
774  * To ungrab the display again, use gdk_x11_display_ungrab(). 
775  *
776  * gdk_x11_display_grab()/gdk_x11_display_ungrab() calls can be nested.
777  *
778  * Since: 2.2
779  **/
780 void
781 gdk_x11_display_grab (GdkDisplay *display)
782 {
783   GdkDisplayX11 *display_x11;
784   
785   g_return_if_fail (GDK_IS_DISPLAY (display));
786   
787   display_x11 = GDK_DISPLAY_X11 (display);
788   
789   if (display_x11->grab_count == 0)
790     XGrabServer (display_x11->xdisplay);
791   display_x11->grab_count++;
792 }
793
794 /**
795  * gdk_x11_display_ungrab:
796  * @display: a #GdkDisplay
797  * 
798  * Ungrab @display after it has been grabbed with 
799  * gdk_x11_display_grab(). 
800  *
801  * Since: 2.2
802  **/
803 void
804 gdk_x11_display_ungrab (GdkDisplay *display)
805 {
806   GdkDisplayX11 *display_x11;
807   
808   g_return_if_fail (GDK_IS_DISPLAY (display));
809   
810   display_x11 = GDK_DISPLAY_X11 (display);;
811   g_return_if_fail (display_x11->grab_count > 0);
812   
813   display_x11->grab_count--;
814   if (display_x11->grab_count == 0)
815     {
816       XUngrabServer (display_x11->xdisplay);
817       XFlush (display_x11->xdisplay);
818     }
819 }
820
821 static void
822 gdk_display_x11_dispose (GObject *object)
823 {
824   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
825   gint           i;
826
827   g_list_foreach (display_x11->input_devices, (GFunc) g_object_run_dispose, NULL);
828
829   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
830     _gdk_screen_close (display_x11->screens[i]);
831
832   _gdk_events_uninit (GDK_DISPLAY_OBJECT (object));
833
834   G_OBJECT_CLASS (_gdk_display_x11_parent_class)->dispose (object);
835 }
836
837 static void
838 gdk_display_x11_finalize (GObject *object)
839 {
840   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
841   gint           i;
842
843   /* Keymap */
844   if (display_x11->keymap)
845     g_object_unref (display_x11->keymap);
846
847   /* Free motif Dnd */
848   if (display_x11->motif_target_lists)
849     {
850       for (i = 0; i < display_x11->motif_n_target_lists; i++)
851         g_list_free (display_x11->motif_target_lists[i]);
852       g_free (display_x11->motif_target_lists);
853     }
854
855   _gdk_x11_cursor_display_finalize (GDK_DISPLAY_OBJECT(display_x11));
856
857   /* Atom Hashtable */
858   g_hash_table_destroy (display_x11->atom_from_virtual);
859   g_hash_table_destroy (display_x11->atom_to_virtual);
860
861   /* Leader Window */
862   XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);
863
864   /* list of filters for client messages */
865   g_list_foreach (display_x11->client_filters, (GFunc) g_free, NULL);
866   g_list_free (display_x11->client_filters);
867
868   /* List of event window extraction functions */
869   g_slist_foreach (display_x11->event_types, (GFunc)g_free, NULL);
870   g_slist_free (display_x11->event_types);
871
872   /* input GdkDevice list */
873   g_list_foreach (display_x11->input_devices, (GFunc) g_object_unref, NULL);
874   g_list_free (display_x11->input_devices);
875
876   /* input GdkWindow list */
877   g_list_foreach (display_x11->input_windows, (GFunc) g_free, NULL);
878   g_list_free (display_x11->input_windows);
879
880   /* Free all GdkScreens */
881   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
882     g_object_unref (display_x11->screens[i]);
883   g_free (display_x11->screens);
884
885   g_free (display_x11->startup_notification_id);
886
887   /* X ID hashtable */
888   g_hash_table_destroy (display_x11->xid_ht);
889
890   XCloseDisplay (display_x11->xdisplay);
891
892   G_OBJECT_CLASS (_gdk_display_x11_parent_class)->finalize (object);
893 }
894
895 /**
896  * gdk_x11_lookup_xdisplay:
897  * @xdisplay: a pointer to an X Display
898  * 
899  * Find the #GdkDisplay corresponding to @display, if any exists.
900  * 
901  * Return value: the #GdkDisplay, if found, otherwise %NULL.
902  *
903  * Since: 2.2
904  **/
905 GdkDisplay *
906 gdk_x11_lookup_xdisplay (Display *xdisplay)
907 {
908   GSList *tmp_list;
909
910   for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
911     {
912       if (GDK_DISPLAY_XDISPLAY (tmp_list->data) == xdisplay)
913         return tmp_list->data;
914     }
915   
916   return NULL;
917 }
918
919 /**
920  * _gdk_x11_display_screen_for_xrootwin:
921  * @display: a #GdkDisplay
922  * @xrootwin: window ID for one of of the screen's of the display.
923  * 
924  * Given the root window ID of one of the screen's of a #GdkDisplay,
925  * finds the screen.
926  * 
927  * Return value: the #GdkScreen corresponding to @xrootwin, or %NULL.
928  **/
929 GdkScreen *
930 _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
931                                       Window      xrootwin)
932 {
933   gint i;
934
935   for (i = 0; i < ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay); i++)
936     {
937       GdkScreen *screen = gdk_display_get_screen (display, i);
938       if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
939         return screen;
940     }
941
942   return NULL;
943 }
944
945 /**
946  * gdk_x11_display_get_xdisplay:
947  * @display: a #GdkDisplay
948  * @returns: an X display.
949  *
950  * Returns the X display of a #GdkDisplay.
951  *
952  * Since: 2.2
953  */
954 Display *
955 gdk_x11_display_get_xdisplay (GdkDisplay *display)
956 {
957   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
958   return GDK_DISPLAY_X11 (display)->xdisplay;
959 }
960
961 void
962 _gdk_windowing_set_default_display (GdkDisplay *display)
963 {
964   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
965   const gchar *startup_id;
966   
967   if (!display)
968     {
969       gdk_display = NULL;
970       return;
971     }
972
973   gdk_display = GDK_DISPLAY_XDISPLAY (display);
974
975   g_free (display_x11->startup_notification_id);
976   display_x11->startup_notification_id = NULL;
977   
978   startup_id = g_getenv ("DESKTOP_STARTUP_ID");
979   if (startup_id && *startup_id != '\0')
980     {
981       gchar *time_str;
982
983       if (!g_utf8_validate (startup_id, -1, NULL))
984         g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
985       else
986         display_x11->startup_notification_id = g_strdup (startup_id);
987
988       /* Find the launch time from the startup_id, if it's there.  Newer spec
989        * states that the startup_id is of the form <unique>_TIME<timestamp>
990        */
991       time_str = g_strrstr (startup_id, "_TIME");
992       if (time_str != NULL)
993         {
994           gulong retval;
995           gchar *end;
996           errno = 0;
997
998           /* Skip past the "_TIME" part */
999           time_str += 5;
1000
1001           retval = strtoul (time_str, &end, 0);
1002           if (end != time_str && errno == 0)
1003             display_x11->user_time = retval;
1004         }
1005       
1006       /* Clear the environment variable so it won't be inherited by
1007        * child processes and confuse things.  
1008        */
1009       g_unsetenv ("DESKTOP_STARTUP_ID");
1010
1011       /* Set the startup id on the leader window so it
1012        * applies to all windows we create on this display
1013        */
1014       XChangeProperty (display_x11->xdisplay,
1015                        display_x11->leader_window,
1016                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
1017                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
1018                        PropModeReplace,
1019                        (guchar *)startup_id, strlen (startup_id));
1020     }
1021 }
1022
1023 static void
1024 broadcast_xmessage (GdkDisplay *display,
1025                     const char *message_type,
1026                     const char *message_type_begin,
1027                     const char *message)
1028 {
1029   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1030   GdkScreen *screen = gdk_display_get_default_screen (display);
1031   GdkWindow *root_window = gdk_screen_get_root_window (screen);
1032   Window xroot_window = GDK_WINDOW_XID (root_window);
1033   
1034   Atom type_atom;
1035   Atom type_atom_begin;
1036   Window xwindow;
1037
1038   if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
1039     return;
1040
1041   {
1042     XSetWindowAttributes attrs;
1043
1044     attrs.override_redirect = True;
1045     attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
1046
1047     xwindow =
1048       XCreateWindow (xdisplay,
1049                      xroot_window,
1050                      -100, -100, 1, 1,
1051                      0,
1052                      CopyFromParent,
1053                      CopyFromParent,
1054                      (Visual *)CopyFromParent,
1055                      CWOverrideRedirect | CWEventMask,
1056                      &attrs);
1057   }
1058
1059   type_atom = gdk_x11_get_xatom_by_name_for_display (display,
1060                                                      message_type);
1061   type_atom_begin = gdk_x11_get_xatom_by_name_for_display (display,
1062                                                            message_type_begin);
1063   
1064   {
1065     XClientMessageEvent xclient;
1066     const char *src;
1067     const char *src_end;
1068     char *dest;
1069     char *dest_end;
1070     
1071                 memset(&xclient, 0, sizeof (xclient));
1072     xclient.type = ClientMessage;
1073     xclient.message_type = type_atom_begin;
1074     xclient.display =xdisplay;
1075     xclient.window = xwindow;
1076     xclient.format = 8;
1077
1078     src = message;
1079     src_end = message + strlen (message) + 1; /* +1 to include nul byte */
1080     
1081     while (src != src_end)
1082       {
1083         dest = &xclient.data.b[0];
1084         dest_end = dest + 20;        
1085         
1086         while (dest != dest_end &&
1087                src != src_end)
1088           {
1089             *dest = *src;
1090             ++dest;
1091             ++src;
1092           }
1093
1094         while (dest != dest_end)
1095           {
1096             *dest = 0;
1097             ++dest;
1098           }
1099         
1100         XSendEvent (xdisplay,
1101                     xroot_window,
1102                     False,
1103                     PropertyChangeMask,
1104                     (XEvent *)&xclient);
1105
1106         xclient.message_type = type_atom;
1107       }
1108   }
1109
1110   XDestroyWindow (xdisplay, xwindow);
1111   XFlush (xdisplay);
1112 }
1113
1114 /**
1115  * gdk_x11_display_broadcast_startup_message:
1116  * @display: a #GdkDisplay
1117  * @message_type: startup notification message type ("new", "change",
1118  * or "remove")
1119  * @...: a list of key/value pairs (as strings), terminated by a
1120  * %NULL key. (A %NULL value for a key will cause that key to be
1121  * skipped in the output.)
1122  *
1123  * Sends a startup notification message of type @message_type to
1124  * @display. 
1125  *
1126  * This is a convenience function for use by code that implements the
1127  * freedesktop startup notification specification. Applications should
1128  * not normally need to call it directly. See the <ulink
1129  * url="http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt">Startup
1130  * Notification Protocol specification</ulink> for
1131  * definitions of the message types and keys that can be used.
1132  *
1133  * Since: 2.12
1134  **/
1135 void
1136 gdk_x11_display_broadcast_startup_message (GdkDisplay *display,
1137                                            const char *message_type,
1138                                            ...)
1139 {
1140   GString *message;
1141   va_list ap;
1142   const char *key, *value, *p;
1143
1144   message = g_string_new (message_type);
1145   g_string_append_c (message, ':');
1146
1147   va_start (ap, message_type);
1148   while ((key = va_arg (ap, const char *)))
1149     {
1150       value = va_arg (ap, const char *);
1151       if (!value)
1152         continue;
1153
1154       g_string_append_printf (message, " %s=\"", key);
1155       for (p = value; *p; p++)
1156         {
1157           switch (*p)
1158             {
1159             case ' ':
1160             case '"':
1161             case '\\':
1162               g_string_append_c (message, '\\');
1163               break;
1164             }
1165
1166           g_string_append_c (message, *p);
1167         }
1168       g_string_append_c (message, '\"');
1169     }
1170   va_end (ap);
1171
1172   broadcast_xmessage (display,
1173                       "_NET_STARTUP_INFO",
1174                       "_NET_STARTUP_INFO_BEGIN",
1175                       message->str);
1176
1177   g_string_free (message, TRUE);
1178 }
1179
1180 /**
1181  * gdk_notify_startup_complete:
1182  * 
1183  * Indicates to the GUI environment that the application has finished
1184  * loading. If the applications opens windows, this function is
1185  * normally called after opening the application's initial set of
1186  * windows.
1187  * 
1188  * GTK+ will call this function automatically after opening the first
1189  * #GtkWindow unless gtk_window_set_auto_startup_notification() is called 
1190  * to disable that feature.
1191  *
1192  * Since: 2.2
1193  **/
1194 void
1195 gdk_notify_startup_complete (void)
1196 {
1197   GdkDisplay *display;
1198   GdkDisplayX11 *display_x11;
1199
1200   display = gdk_display_get_default ();
1201   if (!display)
1202     return;
1203   
1204   display_x11 = GDK_DISPLAY_X11 (display);
1205
1206   if (display_x11->startup_notification_id == NULL)
1207     return;
1208
1209   gdk_notify_startup_complete_with_id (display_x11->startup_notification_id);
1210 }
1211
1212 /**
1213  * gdk_notify_startup_complete_with_id:
1214  * @startup_id: a startup-notification identifier, for which notification
1215  *              process should be completed
1216  * 
1217  * Indicates to the GUI environment that the application has finished
1218  * loading, using a given identifier.
1219  * 
1220  * GTK+ will call this function automatically for #GtkWindow with custom
1221  * startup-notification identifier unless
1222  * gtk_window_set_auto_startup_notification() is called to disable
1223  * that feature.
1224  *
1225  * Since: 2.12
1226  **/
1227 void
1228 gdk_notify_startup_complete_with_id (const gchar* startup_id)
1229 {
1230   GdkDisplay *display;
1231
1232   display = gdk_display_get_default ();
1233   if (!display)
1234     return;
1235
1236   gdk_x11_display_broadcast_startup_message (display, "remove",
1237                                              "ID", startup_id,
1238                                              NULL);
1239 }
1240
1241 /**
1242  * gdk_display_supports_selection_notification:
1243  * @display: a #GdkDisplay
1244  * 
1245  * Returns whether #GdkEventOwnerChange events will be 
1246  * sent when the owner of a selection changes.
1247  * 
1248  * Return value: whether #GdkEventOwnerChange events will 
1249  *               be sent.
1250  *
1251  * Since: 2.6
1252  **/
1253 gboolean 
1254 gdk_display_supports_selection_notification (GdkDisplay *display)
1255 {
1256   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1257
1258   return display_x11->have_xfixes;
1259 }
1260
1261 /**
1262  * gdk_display_request_selection_notification:
1263  * @display: a #GdkDisplay
1264  * @selection: the #GdkAtom naming the selection for which
1265  *             ownership change notification is requested
1266  * 
1267  * Request #GdkEventOwnerChange events for ownership changes
1268  * of the selection named by the given atom.
1269  * 
1270  * Return value: whether #GdkEventOwnerChange events will 
1271  *               be sent.
1272  *
1273  * Since: 2.6
1274  **/
1275 gboolean
1276 gdk_display_request_selection_notification (GdkDisplay *display,
1277                                             GdkAtom     selection)
1278
1279 {
1280 #ifdef HAVE_XFIXES
1281   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1282   Atom atom;
1283
1284   if (display_x11->have_xfixes)
1285     {
1286       atom = gdk_x11_atom_to_xatom_for_display (display, 
1287                                                 selection);
1288       XFixesSelectSelectionInput (display_x11->xdisplay, 
1289                                   display_x11->leader_window,
1290                                   atom,
1291                                   XFixesSetSelectionOwnerNotifyMask |
1292                                   XFixesSelectionWindowDestroyNotifyMask |
1293                                   XFixesSelectionClientCloseNotifyMask);
1294       return TRUE;
1295     }
1296   else
1297 #endif
1298     return FALSE;
1299 }
1300
1301 /**
1302  * gdk_display_supports_clipboard_persistence
1303  * @display: a #GdkDisplay
1304  *
1305  * Returns whether the speicifed display supports clipboard
1306  * persistance; i.e. if it's possible to store the clipboard data after an
1307  * application has quit. On X11 this checks if a clipboard daemon is
1308  * running.
1309  *
1310  * Returns: %TRUE if the display supports clipboard persistance.
1311  *
1312  * Since: 2.6
1313  */
1314 gboolean
1315 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
1316 {
1317   Atom clipboard_manager;
1318
1319   /* It might make sense to cache this */
1320   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
1321   return XGetSelectionOwner (GDK_DISPLAY_X11 (display)->xdisplay, clipboard_manager) != None;
1322 }
1323
1324 /**
1325  * gdk_display_store_clipboard
1326  * @display:          a #GdkDisplay
1327  * @clipboard_window: a #GdkWindow belonging to the clipboard owner
1328  * @time_:            a timestamp
1329  * @targets:          an array of targets that should be saved, or %NULL 
1330  *                    if all available targets should be saved.
1331  * @n_targets:        length of the @targets array
1332  *
1333  * Issues a request to the clipboard manager to store the
1334  * clipboard data. On X11, this is a special program that works
1335  * according to the freedesktop clipboard specification, available at
1336  * <ulink url="http://www.freedesktop.org/Standards/clipboard-manager-spec">
1337  * http://www.freedesktop.org/Standards/clipboard-manager-spec</ulink>.
1338  *
1339  * Since: 2.6
1340  */
1341 void
1342 gdk_display_store_clipboard (GdkDisplay    *display,
1343                              GdkWindow     *clipboard_window,
1344                              guint32        time_,
1345                              const GdkAtom *targets,
1346                              gint           n_targets)
1347 {
1348   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1349   Atom clipboard_manager, save_targets;
1350
1351   g_return_if_fail (GDK_WINDOW_IS_X11 (clipboard_window));
1352
1353   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
1354   save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
1355
1356   gdk_error_trap_push ();
1357
1358   if (XGetSelectionOwner (display_x11->xdisplay, clipboard_manager) != None)
1359     {
1360       Atom property_name = None;
1361       Atom *xatoms;
1362       int i;
1363       
1364       if (n_targets > 0)
1365         {
1366           property_name = gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property);
1367
1368           xatoms = g_new (Atom, n_targets);
1369           for (i = 0; i < n_targets; i++)
1370             xatoms[i] = gdk_x11_atom_to_xatom_for_display (display, targets[i]);
1371
1372           XChangeProperty (display_x11->xdisplay, GDK_WINDOW_XID (clipboard_window),
1373                            property_name, XA_ATOM,
1374                            32, PropModeReplace, (guchar *)xatoms, n_targets);
1375           g_free (xatoms);
1376
1377         }
1378       
1379       XConvertSelection (display_x11->xdisplay,
1380                          clipboard_manager, save_targets, property_name,
1381                          GDK_WINDOW_XID (clipboard_window), time_);
1382       
1383     }
1384   gdk_error_trap_pop ();
1385
1386 }
1387
1388 /**
1389  * gdk_x11_display_get_user_time:
1390  * @display: a #GdkDisplay
1391  *
1392  * Returns the timestamp of the last user interaction on 
1393  * @display. The timestamp is taken from events caused
1394  * by user interaction such as key presses or pointer 
1395  * movements. See gdk_x11_window_set_user_time().
1396  *
1397  * Returns: the timestamp of the last user interaction 
1398  *
1399  * Since: 2.8
1400  */
1401 guint32
1402 gdk_x11_display_get_user_time (GdkDisplay *display)
1403 {
1404   return GDK_DISPLAY_X11 (display)->user_time;
1405 }
1406
1407 /**
1408  * gdk_display_supports_shapes:
1409  * @display: a #GdkDisplay
1410  *
1411  * Returns %TRUE if gdk_window_shape_combine_mask() can
1412  * be used to create shaped windows on @display.
1413  *
1414  * Returns: %TRUE if shaped windows are supported 
1415  *
1416  * Since: 2.10
1417  */
1418 gboolean 
1419 gdk_display_supports_shapes (GdkDisplay *display)
1420 {
1421   return GDK_DISPLAY_X11 (display)->have_shapes;
1422 }
1423
1424 /**
1425  * gdk_display_supports_input_shapes:
1426  * @display: a #GdkDisplay
1427  *
1428  * Returns %TRUE if gdk_window_input_shape_combine_mask() can
1429  * be used to modify the input shape of windows on @display.
1430  *
1431  * Returns: %TRUE if windows with modified input shape are supported 
1432  *
1433  * Since: 2.10
1434  */
1435 gboolean 
1436 gdk_display_supports_input_shapes (GdkDisplay *display)
1437 {
1438   return GDK_DISPLAY_X11 (display)->have_input_shapes;
1439 }
1440
1441
1442 /**
1443  * gdk_x11_display_get_startup_notification_id:
1444  * @display: a #GdkDisplay
1445  *
1446  * Gets the startup notification ID for a display.
1447  * 
1448  * Returns: the startup notification ID for @display
1449  *
1450  * Since: 2.12
1451  */
1452 G_CONST_RETURN gchar *
1453 gdk_x11_display_get_startup_notification_id (GdkDisplay *display)
1454 {
1455   return GDK_DISPLAY_X11 (display)->startup_notification_id;
1456 }
1457
1458 /**
1459  * gdk_display_supports_composite:
1460  * @display: a #GdkDisplay
1461  *
1462  * Returns %TRUE if gdk_window_set_composited() can be used
1463  * to redirect drawing on the window using compositing.
1464  *
1465  * Currently this only works on X11 with XComposite and
1466  * XDamage extensions available.
1467  *
1468  * Returns: %TRUE if windows may be composited.
1469  *
1470  * Since: 2.12
1471  */
1472 gboolean
1473 gdk_display_supports_composite (GdkDisplay *display)
1474 {
1475   GdkDisplayX11 *x11_display = GDK_DISPLAY_X11 (display);
1476
1477   return x11_display->have_xcomposite &&
1478          x11_display->have_xdamage &&
1479          x11_display->have_xfixes;
1480 }
1481
1482
1483 #define __GDK_DISPLAY_X11_C__
1484 #include "gdkaliasdef.c"