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