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