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