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