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