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