]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdisplay-x11.c
Bug 143330, support update counter spec.
[~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  *
6  * Erwann Chenede <erwann.chenede@sun.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include <config.h>
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include <glib.h>
31 #include "gdkx.h"
32 #include "gdkdisplay.h"
33 #include "gdkdisplay-x11.h"
34 #include "gdkscreen.h"
35 #include "gdkscreen-x11.h"
36 #include "gdkinternals.h"
37 #include "gdkinputprivate.h"
38 #include "xsettings-client.h"
39
40 #include <X11/Xatom.h>
41
42 #ifdef HAVE_XKB
43 #include <X11/XKBlib.h>
44 #endif
45
46 #ifdef HAVE_XFIXES
47 #include <X11/extensions/Xfixes.h>
48 #endif
49
50 static void                 gdk_display_x11_class_init         (GdkDisplayX11Class *class);
51 static void                 gdk_display_x11_dispose            (GObject            *object);
52 static void                 gdk_display_x11_finalize           (GObject            *object);
53
54 #ifdef HAVE_X11R6
55 static void gdk_internal_connection_watch (Display  *display,
56                                            XPointer  arg,
57                                            gint      fd,
58                                            gboolean  opening,
59                                            XPointer *watch_data);
60 #endif /* HAVE_X11R6 */
61
62 static gpointer parent_class = NULL;
63
64 /* Note that we never *directly* use WM_LOCALE_NAME, WM_PROTOCOLS,
65  * but including them here has the side-effect of getting them
66  * into the internal Xlib cache
67  */
68 static const char *const precache_atoms[] = {
69   "UTF8_STRING",
70   "WM_CLIENT_LEADER",
71   "WM_DELETE_WINDOW",
72   "WM_LOCALE_NAME",
73   "WM_PROTOCOLS",
74   "WM_TAKE_FOCUS",
75   "_NET_WM_DESKTOP",
76   "_NET_WM_ICON",
77   "_NET_WM_ICON_NAME",
78   "_NET_WM_NAME",
79   "_NET_WM_PID",
80   "_NET_WM_PING",
81   "_NET_WM_STATE",
82   "_NET_WM_STATE_STICKY",
83   "_NET_WM_STATE_MAXIMIZED_VERT",
84   "_NET_WM_STATE_MAXIMIZED_HORZ",
85   "_NET_WM_STATE_FULLSCREEN",
86   "_NET_WM_SYNC_REQUEST",
87   "_NET_WM_SYNC_REQUEST_COUNTER",
88   "_NET_WM_WINDOW_TYPE",
89   "_NET_WM_WINDOW_TYPE_NORMAL",
90   "_NET_WM_USER_TIME",
91 };
92
93 GType
94 _gdk_display_x11_get_type (void)
95 {
96   static GType object_type = 0;
97
98   if (!object_type)
99     {
100       static const GTypeInfo object_info =
101         {
102           sizeof (GdkDisplayX11Class),
103           (GBaseInitFunc) NULL,
104           (GBaseFinalizeFunc) NULL,
105           (GClassInitFunc) gdk_display_x11_class_init,
106           NULL,                 /* class_finalize */
107           NULL,                 /* class_data */
108           sizeof (GdkDisplayX11),
109           0,                    /* n_preallocs */
110           (GInstanceInitFunc) NULL,
111         };
112       
113       object_type = g_type_register_static (GDK_TYPE_DISPLAY,
114                                             "GdkDisplayX11",
115                                             &object_info, 0);
116     }
117   
118   return object_type;
119 }
120
121 static void
122 gdk_display_x11_class_init (GdkDisplayX11Class * class)
123 {
124   GObjectClass *object_class = G_OBJECT_CLASS (class);
125   
126   object_class->dispose = gdk_display_x11_dispose;
127   object_class->finalize = gdk_display_x11_finalize;
128   
129   parent_class = g_type_class_peek_parent (class);
130 }
131
132 /**
133  * gdk_display_open:
134  * @display_name: the name of the display to open
135  * @returns: a #GdkDisplay, or %NULL if the display
136  *  could not be opened.
137  *
138  * Opens a display.
139  *
140  * Since: 2.2
141  */
142 GdkDisplay *
143 gdk_display_open (const gchar *display_name)
144 {
145   Display *xdisplay;
146   GdkDisplay *display;
147   GdkDisplayX11 *display_x11;
148   GdkWindowAttr attr;
149   gint argc;
150   gchar **argv;
151   const char *sm_client_id;
152   
153   XClassHint *class_hint;
154   gulong pid;
155   gint i;
156 #ifdef HAVE_XFIXES
157   gint ignore;
158 #endif
159
160   xdisplay = XOpenDisplay (display_name);
161   if (!xdisplay)
162     return NULL;
163   
164   display = g_object_new (GDK_TYPE_DISPLAY_X11, NULL);
165   display_x11 = GDK_DISPLAY_X11 (display);
166
167   display_x11->use_xshm = TRUE;
168   display_x11->xdisplay = xdisplay;
169
170 #ifdef HAVE_X11R6  
171   /* Set up handlers for Xlib internal connections */
172   XAddConnectionWatch (xdisplay, gdk_internal_connection_watch, NULL);
173 #endif /* HAVE_X11R6 */
174   
175   /* initialize the display's screens */ 
176   display_x11->screens = g_new (GdkScreen *, ScreenCount (display_x11->xdisplay));
177   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
178     display_x11->screens[i] = _gdk_x11_screen_new (display, i);
179
180   /* We need to initialize events after we have the screen
181    * structures in places
182    */
183   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
184     _gdk_x11_events_init_screen (display_x11->screens[i]);
185   
186   /*set the default screen */
187   display_x11->default_screen = display_x11->screens[DefaultScreen (display_x11->xdisplay)];
188
189   attr.window_type = GDK_WINDOW_TOPLEVEL;
190   attr.wclass = GDK_INPUT_OUTPUT;
191   attr.x = 10;
192   attr.y = 10;
193   attr.width = 10;
194   attr.height = 10;
195   attr.event_mask = 0;
196
197   display_x11->leader_gdk_window = gdk_window_new (GDK_SCREEN_X11 (display_x11->default_screen)->root_window, 
198                                                    &attr, GDK_WA_X | GDK_WA_Y);
199   display_x11->leader_window = GDK_WINDOW_XID (display_x11->leader_gdk_window);
200
201   display_x11->leader_window_title_set = FALSE;
202
203   display_x11->have_render = GDK_UNKNOWN;
204
205 #ifdef HAVE_XFIXES
206   if (XFixesQueryExtension (display_x11->xdisplay, 
207                             &display_x11->xfixes_event_base, 
208                             &ignore))
209     {
210       display_x11->have_xfixes = TRUE;
211
212       gdk_x11_register_standard_event_type (display,
213                                             display_x11->xfixes_event_base, 
214                                             XFixesNumberEvents);
215     }
216   else
217 #endif
218   display_x11->have_xfixes = FALSE;
219
220   if (_gdk_synchronize)
221     XSynchronize (display_x11->xdisplay, True);
222   
223   _gdk_x11_precache_atoms (display, precache_atoms, G_N_ELEMENTS (precache_atoms));
224
225   class_hint = XAllocClassHint();
226   class_hint->res_name = g_get_prgname ();
227   
228   class_hint->res_class = (char *)gdk_get_program_class ();
229   _gdk_get_command_line_args (&argc, &argv);
230   XmbSetWMProperties (display_x11->xdisplay,
231                       display_x11->leader_window,
232                       NULL, NULL, argv, argc, NULL, NULL,
233                       class_hint);
234   XFree (class_hint);
235
236   sm_client_id = _gdk_get_sm_client_id ();
237   if (sm_client_id)
238     _gdk_windowing_display_set_sm_client_id (display, sm_client_id);
239
240   pid = getpid ();
241   XChangeProperty (display_x11->xdisplay,
242                    display_x11->leader_window,
243                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"),
244                    XA_CARDINAL, 32, PropModeReplace, (guchar *) & pid, 1);
245
246   /* We don't yet know a valid time. */
247   display_x11->user_time = 0;
248   
249 #ifdef HAVE_XKB
250   {
251     gint xkb_major = XkbMajorVersion;
252     gint xkb_minor = XkbMinorVersion;
253     if (XkbLibraryVersion (&xkb_major, &xkb_minor))
254       {
255         xkb_major = XkbMajorVersion;
256         xkb_minor = XkbMinorVersion;
257             
258         if (XkbQueryExtension (display_x11->xdisplay, 
259                                NULL, &display_x11->xkb_event_type, NULL,
260                                &xkb_major, &xkb_minor))
261           {
262             Bool detectable_autorepeat_supported;
263             
264             display_x11->use_xkb = TRUE;
265
266             XkbSelectEvents (display_x11->xdisplay,
267                              XkbUseCoreKbd,
268                              XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask,
269                              XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask);
270
271             XkbSetDetectableAutoRepeat (display_x11->xdisplay,
272                                         True,
273                                         &detectable_autorepeat_supported);
274
275             GDK_NOTE (MISC, g_message ("Detectable autorepeat %s.",
276                                        detectable_autorepeat_supported ? 
277                                        "supported" : "not supported"));
278             
279             display_x11->have_xkb_autorepeat = detectable_autorepeat_supported;
280           }
281       }
282   }
283 #endif
284
285   display_x11->use_sync = FALSE;
286 #ifdef HAVE_XSYNC
287   {
288     int major, minor;
289     int error_base, event_base;
290     
291     if (XSyncQueryExtension (display_x11->xdisplay,
292                              &event_base, &error_base) &&
293         XSyncInitialize (display_x11->xdisplay,
294                          &major, &minor))
295       display_x11->use_sync = TRUE;
296   }
297 #endif
298   
299   _gdk_windowing_image_init (display);
300   _gdk_events_init (display);
301   _gdk_input_init (display);
302   _gdk_dnd_init (display);
303
304   g_signal_emit_by_name (gdk_display_manager_get(),
305                          "display_opened", display);
306
307   return display;
308 }
309
310 #ifdef HAVE_X11R6
311 /*
312  * XLib internal connection handling
313  */
314 typedef struct _GdkInternalConnection GdkInternalConnection;
315
316 struct _GdkInternalConnection
317 {
318   gint           fd;
319   GSource       *source;
320   Display       *display;
321 };
322
323 static gboolean
324 process_internal_connection (GIOChannel  *gioc,
325                              GIOCondition cond,
326                              gpointer     data)
327 {
328   GdkInternalConnection *connection = (GdkInternalConnection *)data;
329
330   GDK_THREADS_ENTER ();
331
332   XProcessInternalConnection ((Display*)connection->display, connection->fd);
333
334   GDK_THREADS_LEAVE ();
335
336   return TRUE;
337 }
338
339 static GdkInternalConnection *
340 gdk_add_connection_handler (Display *display,
341                             guint    fd)
342 {
343   GIOChannel *io_channel;
344   GdkInternalConnection *connection;
345
346   connection = g_new (GdkInternalConnection, 1);
347
348   connection->fd = fd;
349   connection->display = display;
350   
351   io_channel = g_io_channel_unix_new (fd);
352   
353   connection->source = g_io_create_watch (io_channel, G_IO_IN);
354   g_source_set_callback (connection->source,
355                          (GSourceFunc)process_internal_connection, connection, NULL);
356   g_source_attach (connection->source, NULL);
357   
358   g_io_channel_unref (io_channel);
359   
360   return connection;
361 }
362
363 static void
364 gdk_remove_connection_handler (GdkInternalConnection *connection)
365 {
366   g_source_destroy (connection->source);
367   g_free (connection);
368 }
369
370 static void
371 gdk_internal_connection_watch (Display  *display,
372                                XPointer  arg,
373                                gint      fd,
374                                gboolean  opening,
375                                XPointer *watch_data)
376 {
377   if (opening)
378     *watch_data = (XPointer)gdk_add_connection_handler (display, fd);
379   else
380     gdk_remove_connection_handler ((GdkInternalConnection *)*watch_data);
381 }
382 #endif /* HAVE_X11R6 */
383
384 /**
385  * gdk_display_get_name:
386  * @display: a #GdkDisplay
387  *
388  * Gets the name of the display.
389  * 
390  * Returns: a string representing the display name. This string is owned
391  * by GDK and should not be modified or freed.
392  * 
393  * Since: 2.2
394  */
395 G_CONST_RETURN gchar *
396 gdk_display_get_name (GdkDisplay * display)
397 {
398   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
399   
400   return (gchar *) DisplayString (GDK_DISPLAY_X11 (display)->xdisplay);
401 }
402
403 /**
404  * gdk_display_get_n_screens:
405  * @display: a #GdkDisplay
406  *
407  * Gets the number of screen managed by the @display.
408  * 
409  * Returns: number of screens.
410  * 
411  * Since: 2.2
412  */
413 gint
414 gdk_display_get_n_screens (GdkDisplay * display)
415 {
416   g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
417   
418   return ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay);
419 }
420
421 /**
422  * gdk_display_get_screen:
423  * @display: a #GdkDisplay
424  * @screen_num: the screen number
425  *
426  * Returns a screen object for one of the screens of the display.
427  *
428  * Returns: the #GdkScreen object
429  *
430  * Since: 2.2
431  */
432 GdkScreen *
433 gdk_display_get_screen (GdkDisplay * display, gint screen_num)
434 {
435   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
436   g_return_val_if_fail (ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay) > screen_num, NULL);
437   
438   return GDK_DISPLAY_X11 (display)->screens[screen_num];
439 }
440
441 /**
442  * gdk_display_get_default_screen:
443  * @display: a #GdkDisplay
444  *
445  * Get the default #GdkScreen for @display.
446  * 
447  * Returns: the default #GdkScreen object for @display
448  *
449  * Since: 2.2
450  */
451 GdkScreen *
452 gdk_display_get_default_screen (GdkDisplay * display)
453 {
454   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
455   
456   return GDK_DISPLAY_X11 (display)->default_screen;
457 }
458
459 gboolean
460 _gdk_x11_display_is_root_window (GdkDisplay *display,
461                                  Window      xroot_window)
462 {
463   GdkDisplayX11 *display_x11;
464   gint i;
465   
466   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
467   
468   display_x11 = GDK_DISPLAY_X11 (display);
469   
470   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
471     {
472       if (GDK_SCREEN_XROOTWIN (display_x11->screens[i]) == xroot_window)
473         return TRUE;
474     }
475   return FALSE;
476 }
477
478 /**
479  * gdk_display_pointer_ungrab:
480  * @display: a #GdkDisplay.
481  * @time_: a timestap (e.g. GDK_CURRENT_TIME).
482  *
483  * Release any pointer grab.
484  *
485  * Since: 2.2
486  */
487 void
488 gdk_display_pointer_ungrab (GdkDisplay *display,
489                             guint32     time)
490 {
491   Display *xdisplay;
492   
493   g_return_if_fail (GDK_IS_DISPLAY (display));
494
495   xdisplay = GDK_DISPLAY_XDISPLAY (display);
496   
497   _gdk_input_ungrab_pointer (display, time);
498   XUngrabPointer (xdisplay, time);
499   XFlush (xdisplay);
500   
501   GDK_DISPLAY_X11 (display)->pointer_xgrab_window = NULL;
502 }
503
504 /**
505  * gdk_display_pointer_is_grabbed:
506  * @display: a #GdkDisplay
507  *
508  * Test if the pointer is grabbed.
509  *
510  * Returns: %TRUE if an active X pointer grab is in effect
511  *
512  * Since: 2.2
513  */
514 gboolean
515 gdk_display_pointer_is_grabbed (GdkDisplay * display)
516 {
517   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
518   
519   return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL);
520 }
521
522 /**
523  * gdk_display_keyboard_ungrab:
524  * @display: a #GdkDisplay.
525  * @time_: a timestap (e.g #GDK_CURRENT_TIME).
526  *
527  * Release any keyboard grab
528  *
529  * Since: 2.2
530  */
531 void
532 gdk_display_keyboard_ungrab (GdkDisplay *display,
533                              guint32     time)
534 {
535   Display *xdisplay;
536   
537   g_return_if_fail (GDK_IS_DISPLAY (display));
538
539   xdisplay = GDK_DISPLAY_XDISPLAY (display);
540   
541   XUngrabKeyboard (xdisplay, time);
542   XFlush (xdisplay);
543   
544   GDK_DISPLAY_X11 (display)->keyboard_xgrab_window = NULL;
545 }
546
547 /**
548  * gdk_display_beep:
549  * @display: a #GdkDisplay
550  *
551  * Emits a short beep on @display
552  *
553  * Since: 2.2
554  */
555 void
556 gdk_display_beep (GdkDisplay * display)
557 {
558   g_return_if_fail (GDK_IS_DISPLAY (display));
559   
560   XBell (GDK_DISPLAY_XDISPLAY (display), 0);
561 }
562
563 /**
564  * gdk_display_sync:
565  * @display: a #GdkDisplay
566  *
567  * Flushes any requests queued for the windowing system and waits until all
568  * requests have been handled. This is often used for making sure that the
569  * display is synchronized with the current state of the program. Calling
570  * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors
571  * generated from earlier requests are handled before the error trap is 
572  * removed.
573  *
574  * This is most useful for X11. On windowing systems where requests are
575  * handled synchronously, this function will do nothing.
576  *
577  * Since: 2.2
578  */
579 void
580 gdk_display_sync (GdkDisplay * display)
581 {
582   g_return_if_fail (GDK_IS_DISPLAY (display));
583   
584   XSync (GDK_DISPLAY_XDISPLAY (display), False);
585 }
586
587 /**
588  * gdk_display_flush:
589  * @display: a #GdkDisplay
590  *
591  * Flushes any requests queued for the windowing system; this happens automatically
592  * when the main loop blocks waiting for new events, but if your application
593  * is drawing without returning control to the main loop, you may need
594  * to call this function explicitely. A common case where this function
595  * needs to be called is when an application is executing drawing commands
596  * from a thread other than the thread where the main loop is running.
597  *
598  * This is most useful for X11. On windowing systems where requests are
599  * handled synchronously, this function will do nothing.
600  *
601  * Since: 2.4
602  */
603 void 
604 gdk_display_flush (GdkDisplay *display)
605 {
606   g_return_if_fail (GDK_IS_DISPLAY (display));
607
608   if (!display->closed)
609     XFlush (GDK_DISPLAY_XDISPLAY (display));
610 }
611
612 /**
613  * gdk_display_get_default_group:
614  * @display: a #GdkDisplay
615  * 
616  * Returns the default group leader window for all toplevel windows
617  * on @display. This window is implicitly created by GDK. 
618  * See gdk_window_set_group().
619  * 
620  * Return value: The default group leader window for @display
621  *
622  * Since: 2.4
623  **/
624 GdkWindow *gdk_display_get_default_group (GdkDisplay *display)
625 {
626   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
627
628   return GDK_DISPLAY_X11 (display)->leader_gdk_window;
629 }
630
631 /**
632  * gdk_x11_display_grab:
633  * @display: a #GdkDisplay 
634  * 
635  * Call XGrabServer() on @display. 
636  * To ungrab the display again, use gdk_x11_display_ungrab(). 
637  *
638  * gdk_x11_display_grab()/gdk_x11_display_ungrab() calls can be nested.
639  *
640  * Since: 2.2
641  **/
642 void
643 gdk_x11_display_grab (GdkDisplay * display)
644 {
645   GdkDisplayX11 *display_x11;
646   
647   g_return_if_fail (GDK_IS_DISPLAY (display));
648   
649   display_x11 = GDK_DISPLAY_X11 (display);
650   
651   if (display_x11->grab_count == 0)
652     XGrabServer (display_x11->xdisplay);
653   display_x11->grab_count++;
654 }
655
656 /**
657  * gdk_x11_display_ungrab:
658  * @display: a #GdkDisplay
659  * 
660  * Ungrab @display after it has been grabbed with 
661  * gdk_x11_display_grab(). 
662  *
663  * Since: 2.2
664  **/
665 void
666 gdk_x11_display_ungrab (GdkDisplay * display)
667 {
668   GdkDisplayX11 *display_x11;
669   
670   g_return_if_fail (GDK_IS_DISPLAY (display));
671   
672   display_x11 = GDK_DISPLAY_X11 (display);;
673   g_return_if_fail (display_x11->grab_count > 0);
674   
675   display_x11->grab_count--;
676   if (display_x11->grab_count == 0)
677     {
678       XUngrabServer (display_x11->xdisplay);
679       XFlush (display_x11->xdisplay);
680     }
681 }
682
683 static void
684 gdk_display_x11_dispose (GObject *object)
685 {
686   GdkDisplayX11 *display_x11;
687   gint i;
688   
689   display_x11 = GDK_DISPLAY_X11 (object);
690   
691   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
692     _gdk_screen_close (display_x11->screens[i]);
693
694   g_source_destroy (display_x11->event_source);
695
696   XCloseDisplay (display_x11->xdisplay);
697   display_x11->xdisplay = NULL;
698
699   G_OBJECT_CLASS (parent_class)->dispose (object);
700 }
701
702 static void
703 gdk_display_x11_finalize (GObject *object)
704 {
705   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
706   int i;
707   GList *tmp;
708   /* FIXME need to write GdkKeymap finalize fct 
709      g_object_unref (display_x11->keymap);
710    */
711   /* Free motif Dnd */
712   if (display_x11->motif_target_lists)
713     {
714       for (i = 0; i < display_x11->motif_n_target_lists; i++)
715         g_list_free (display_x11->motif_target_lists[i]);
716       g_free (display_x11->motif_target_lists);
717     }
718
719   /* Atom Hashtable */
720   g_hash_table_destroy (display_x11->atom_from_virtual);
721   g_hash_table_destroy (display_x11->atom_to_virtual);
722   /* Leader Window */
723   XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);
724   /* list of filters for client messages */
725   g_list_free (display_x11->client_filters);
726   /* List of event window extraction functions */
727   g_slist_foreach (display_x11->event_types, (GFunc)g_free, NULL);
728   g_slist_free (display_x11->event_types);
729   /* X ID hashtable */
730   g_hash_table_destroy (display_x11->xid_ht);
731   /* input GdkDevice list */
732   /* FIXME need to write finalize fct */
733   for (tmp = display_x11->input_devices; tmp; tmp = tmp->next)
734     g_object_unref (tmp->data);
735   g_list_free (display_x11->input_devices);
736   /* input GdkWindow list */
737   for (tmp = display_x11->input_windows; tmp; tmp = tmp->next)
738     g_object_unref (tmp->data);
739   g_list_free (display_x11->input_windows);
740   /* Free all GdkScreens */
741   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
742     g_object_unref (display_x11->screens[i]);
743   g_free (display_x11->screens);
744   g_free (display_x11->startup_notification_id);
745   
746   G_OBJECT_CLASS (parent_class)->finalize (object);
747 }
748
749 /**
750  * gdk_x11_lookup_xdisplay:
751  * @xdisplay: a pointer to an X Display
752  * 
753  * Find the #GdkDisplay corresponding to @display, if any exists.
754  * 
755  * Return value: the #GdkDisplay, if found, otherwise %NULL.
756  *
757  * Since: 2.2
758  **/
759 GdkDisplay *
760 gdk_x11_lookup_xdisplay (Display *xdisplay)
761 {
762   GSList *tmp_list;
763
764   for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
765     {
766       if (GDK_DISPLAY_XDISPLAY (tmp_list->data) == xdisplay)
767         return tmp_list->data;
768     }
769   
770   return NULL;
771 }
772
773 /**
774  * _gdk_x11_display_screen_for_xrootwin:
775  * @display: a #Display
776  * @xrootwin: window ID for one of of the screen's of the display.
777  * 
778  * Given the root window ID of one of the screen's of a #GdkDisplay,
779  * finds the screen.
780  * 
781  * Return value: the #GdkScreen corresponding to @xrootwin, or %NULL.
782  **/
783 GdkScreen *
784 _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
785                                       Window      xrootwin)
786 {
787   gint n_screens, i;
788
789   n_screens = gdk_display_get_n_screens (display);
790   for (i = 0; i < n_screens; i++)
791     {
792       GdkScreen *screen = gdk_display_get_screen (display, i);
793       if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
794         return screen;
795     }
796
797   return NULL;
798 }
799
800 /**
801  * gdk_x11_display_get_xdisplay:
802  * @display: a #GdkDisplay
803  * @returns: an X display.
804  *
805  * Returns the X display of a #GdkDisplay.
806  *
807  * Since: 2.2
808  */
809 Display *
810 gdk_x11_display_get_xdisplay (GdkDisplay  *display)
811 {
812   return GDK_DISPLAY_X11 (display)->xdisplay;
813 }
814
815 void
816 _gdk_windowing_set_default_display (GdkDisplay *display)
817 {
818   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
819   const gchar *startup_id;
820   
821   if (display)
822     gdk_display = GDK_DISPLAY_XDISPLAY (display);
823   else
824     gdk_display = NULL;
825
826   g_free (display_x11->startup_notification_id);
827   display_x11->startup_notification_id = NULL;
828   
829   startup_id = g_getenv ("DESKTOP_STARTUP_ID");
830   if (startup_id && *startup_id != '\0')
831     {
832       if (!g_utf8_validate (startup_id, -1, NULL))
833         g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
834       else
835         display_x11->startup_notification_id = g_strdup (startup_id);
836       
837       /* Clear the environment variable so it won't be inherited by
838        * child processes and confuse things.  
839        */
840       g_unsetenv ("DESKTOP_STARTUP_ID");
841
842       /* Set the startup id on the leader window so it
843        * applies to all windows we create on this display
844        */
845       XChangeProperty (display_x11->xdisplay,
846                        display_x11->leader_window,
847                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
848                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
849                        PropModeReplace,
850                        startup_id, strlen (startup_id));
851     }
852 }
853
854 static char*
855 escape_for_xmessage (const char *str)
856 {
857   GString *retval;
858   const char *p;
859   
860   retval = g_string_new (NULL);
861
862   p = str;
863   while (*p)
864     {
865       switch (*p)
866         {
867         case ' ':
868         case '"':
869         case '\\':
870           g_string_append_c (retval, '\\');
871           break;
872         }
873
874       g_string_append_c (retval, *p);
875       ++p;
876     }
877
878   return g_string_free (retval, FALSE);
879 }
880
881 static void
882 broadcast_xmessage   (GdkDisplay   *display,
883                       const char   *message_type,
884                       const char   *message_type_begin,
885                       const char   *message)
886 {
887   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
888   GdkScreen *screen = gdk_display_get_default_screen (display);
889   GdkWindow *root_window = gdk_screen_get_root_window (screen);
890   Window xroot_window = GDK_WINDOW_XID (root_window);
891   
892   Atom type_atom;
893   Atom type_atom_begin;
894   Window xwindow;
895
896   {
897     XSetWindowAttributes attrs;
898
899     attrs.override_redirect = True;
900     attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
901
902     xwindow =
903       XCreateWindow (xdisplay,
904                      xroot_window,
905                      -100, -100, 1, 1,
906                      0,
907                      CopyFromParent,
908                      CopyFromParent,
909                      CopyFromParent,
910                      CWOverrideRedirect | CWEventMask,
911                      &attrs);
912   }
913
914   type_atom = gdk_x11_get_xatom_by_name_for_display (display,
915                                                      message_type);
916   type_atom_begin = gdk_x11_get_xatom_by_name_for_display (display,
917                                                            message_type_begin);
918   
919   {
920     XEvent xevent;
921     const char *src;
922     const char *src_end;
923     char *dest;
924     char *dest_end;
925     
926     xevent.xclient.type = ClientMessage;
927     xevent.xclient.message_type = type_atom_begin;
928     xevent.xclient.display =xdisplay;
929     xevent.xclient.window = xwindow;
930     xevent.xclient.format = 8;
931
932     src = message;
933     src_end = message + strlen (message) + 1; /* +1 to include nul byte */
934     
935     while (src != src_end)
936       {
937         dest = &xevent.xclient.data.b[0];
938         dest_end = dest + 20;        
939         
940         while (dest != dest_end &&
941                src != src_end)
942           {
943             *dest = *src;
944             ++dest;
945             ++src;
946           }
947
948         while (dest != dest_end)
949           {
950             *dest = 0;
951             ++dest;
952           }
953         
954         XSendEvent (xdisplay,
955                     xroot_window,
956                     False,
957                     PropertyChangeMask,
958                     &xevent);
959
960         xevent.xclient.message_type = type_atom;
961       }
962   }
963
964   XDestroyWindow (xdisplay, xwindow);
965   XFlush (xdisplay);
966 }
967
968 /**
969  * gdk_notify_startup_complete:
970  * 
971  * Indicates to the GUI environment that the application has finished
972  * loading. If the applications opens windows, this function is
973  * normally called after opening the application's initial set of
974  * windows.
975  * 
976  * GTK+ will call this function automatically after opening the first
977  * #GtkWindow unless gtk_window_set_auto_startup_notification() is called 
978  * to disable that feature.
979  *
980  * Since: 2.2
981  **/
982 void
983 gdk_notify_startup_complete (void)
984 {
985   GdkDisplay *display;
986   GdkDisplayX11 *display_x11;
987   gchar *escaped_id;
988   gchar *message;
989
990   display = gdk_display_get_default ();
991   if (!display)
992     return;
993   
994   display_x11 = GDK_DISPLAY_X11 (display);
995
996   if (display_x11->startup_notification_id == NULL)
997     return;
998
999   escaped_id = escape_for_xmessage (display_x11->startup_notification_id);
1000   message = g_strdup_printf ("remove: ID=%s", escaped_id);
1001   g_free (escaped_id);
1002
1003   broadcast_xmessage (display,
1004                       "_NET_STARTUP_INFO",
1005                       "_NET_STARTUP_INFO_BEGIN",
1006                       message);
1007
1008   g_free (message);
1009 }
1010
1011
1012 /**
1013  * gdk_display_supports_selection_notification:
1014  * @display: a #GdkDisplay
1015  * 
1016  * Returns whether #GdkEventOwnerChange events will be 
1017  * sent when the owner of a selection changes.
1018  * 
1019  * Return value: whether #GdkEventOwnerChange events will 
1020  *               be sent.
1021  *
1022  * Since: 2.6
1023  **/
1024 gboolean 
1025 gdk_display_supports_selection_notification (GdkDisplay *display)
1026 {
1027   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1028
1029   return display_x11->have_xfixes;
1030 }
1031
1032 /**
1033  * gdk_display_request_selection_notification:
1034  * @display: a #GdkDisplay
1035  * @selection: the #GdkAtom naming the selection for which
1036  *             ownership change notification is requested
1037  * 
1038  * Request #GdkEventOwnerChange events for ownership changes
1039  * of the selection named by the given atom.
1040  * 
1041  * Return value: whether #GdkEventOwnerChange events will 
1042  *               be sent.
1043  *
1044  * Since: 2.6
1045  **/
1046 gboolean gdk_display_request_selection_notification  (GdkDisplay *display,
1047                                                       GdkAtom     selection)
1048
1049 {
1050 #ifdef HAVE_XFIXES
1051   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1052   Atom atom;
1053
1054   if (display_x11->have_xfixes)
1055     {
1056       atom = gdk_x11_atom_to_xatom_for_display (display, 
1057                                                 selection);
1058       XFixesSelectSelectionInput (display_x11->xdisplay, 
1059                                   display_x11->leader_window,
1060                                   atom,
1061                                   XFixesSetSelectionOwnerNotifyMask |
1062                                   XFixesSelectionWindowDestroyNotifyMask |
1063                                   XFixesSelectionClientCloseNotifyMask);
1064       return TRUE;
1065     }
1066   else
1067 #endif
1068     return FALSE;
1069 }