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