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