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