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