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