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