]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdisplay-x11.c
destroy display->xid_ht as late as possible (right before XCloseDisplay)
[~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   display_x11->leader_gdk_window = gdk_window_new (GDK_SCREEN_X11 (display_x11->default_screen)->root_window, 
203                                                    &attr, GDK_WA_X | GDK_WA_Y);
204   (_gdk_x11_window_get_toplevel (display_x11->leader_gdk_window))->is_leader = TRUE;
205
206   display_x11->leader_window = GDK_WINDOW_XID (display_x11->leader_gdk_window);
207
208   display_x11->leader_window_title_set = FALSE;
209
210   display_x11->have_render = GDK_UNKNOWN;
211
212 #ifdef HAVE_XFIXES
213   if (XFixesQueryExtension (display_x11->xdisplay, 
214                             &display_x11->xfixes_event_base, 
215                             &ignore))
216     {
217       display_x11->have_xfixes = TRUE;
218
219       gdk_x11_register_standard_event_type (display,
220                                             display_x11->xfixes_event_base, 
221                                             XFixesNumberEvents);
222     }
223   else
224 #endif
225   display_x11->have_xfixes = FALSE;
226
227   if (_gdk_synchronize)
228     XSynchronize (display_x11->xdisplay, True);
229   
230   _gdk_x11_precache_atoms (display, precache_atoms, G_N_ELEMENTS (precache_atoms));
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   if (display_x11->event_source)
730     {
731       g_source_destroy (display_x11->event_source);
732       display_x11->event_source = NULL;
733     }
734
735   G_OBJECT_CLASS (parent_class)->dispose (object);
736 }
737
738 static void
739 gdk_display_x11_finalize (GObject *object)
740 {
741   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
742   gint           n_screens;
743   gint           i;
744
745   /* Keymap */
746   if (display_x11->keymap)
747     g_object_unref (display_x11->keymap);
748
749   /* Free motif Dnd */
750   if (display_x11->motif_target_lists)
751     {
752       for (i = 0; i < display_x11->motif_n_target_lists; i++)
753         g_list_free (display_x11->motif_target_lists[i]);
754       g_free (display_x11->motif_target_lists);
755     }
756
757   /* Atom Hashtable */
758   g_hash_table_destroy (display_x11->atom_from_virtual);
759   g_hash_table_destroy (display_x11->atom_to_virtual);
760
761   /* Leader Window */
762   XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);
763
764   /* list of filters for client messages */
765   g_list_foreach (display_x11->client_filters, (GFunc) g_free, NULL);
766   g_list_free (display_x11->client_filters);
767
768   /* List of event window extraction functions */
769   g_slist_foreach (display_x11->event_types, (GFunc)g_free, NULL);
770   g_slist_free (display_x11->event_types);
771
772   /* input GdkDevice list */
773   /* FIXME need to write finalize fct */
774   g_list_foreach (display_x11->input_devices, (GFunc) g_object_unref, NULL);
775   g_list_free (display_x11->input_devices);
776
777   /* input GdkWindow list */
778   g_list_foreach (display_x11->input_windows, (GFunc) g_object_unref, NULL);
779   g_list_free (display_x11->input_windows);
780
781   /* Free all GdkScreens */
782   n_screens = ScreenCount (display_x11->xdisplay);
783   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
784     g_object_unref (display_x11->screens[i]);
785   g_free (display_x11->screens);
786
787   g_free (display_x11->startup_notification_id);
788
789   /* X ID hashtable */
790   g_hash_table_destroy (display_x11->xid_ht);
791
792   XCloseDisplay (display_x11->xdisplay);
793
794   G_OBJECT_CLASS (parent_class)->finalize (object);
795 }
796
797 /**
798  * gdk_x11_lookup_xdisplay:
799  * @xdisplay: a pointer to an X Display
800  * 
801  * Find the #GdkDisplay corresponding to @display, if any exists.
802  * 
803  * Return value: the #GdkDisplay, if found, otherwise %NULL.
804  *
805  * Since: 2.2
806  **/
807 GdkDisplay *
808 gdk_x11_lookup_xdisplay (Display *xdisplay)
809 {
810   GSList *tmp_list;
811
812   for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
813     {
814       if (GDK_DISPLAY_XDISPLAY (tmp_list->data) == xdisplay)
815         return tmp_list->data;
816     }
817   
818   return NULL;
819 }
820
821 /**
822  * _gdk_x11_display_screen_for_xrootwin:
823  * @display: a #Display
824  * @xrootwin: window ID for one of of the screen's of the display.
825  * 
826  * Given the root window ID of one of the screen's of a #GdkDisplay,
827  * finds the screen.
828  * 
829  * Return value: the #GdkScreen corresponding to @xrootwin, or %NULL.
830  **/
831 GdkScreen *
832 _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
833                                       Window      xrootwin)
834 {
835   gint n_screens, i;
836
837   n_screens = gdk_display_get_n_screens (display);
838   for (i = 0; i < n_screens; i++)
839     {
840       GdkScreen *screen = gdk_display_get_screen (display, i);
841       if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
842         return screen;
843     }
844
845   return NULL;
846 }
847
848 /**
849  * gdk_x11_display_get_xdisplay:
850  * @display: a #GdkDisplay
851  * @returns: an X display.
852  *
853  * Returns the X display of a #GdkDisplay.
854  *
855  * Since: 2.2
856  */
857 Display *
858 gdk_x11_display_get_xdisplay (GdkDisplay  *display)
859 {
860   return GDK_DISPLAY_X11 (display)->xdisplay;
861 }
862
863 void
864 _gdk_windowing_set_default_display (GdkDisplay *display)
865 {
866   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
867   const gchar *startup_id;
868   
869   if (!display)
870     {
871       gdk_display = NULL;
872       return;
873     }
874
875   gdk_display = GDK_DISPLAY_XDISPLAY (display);
876
877   g_free (display_x11->startup_notification_id);
878   display_x11->startup_notification_id = NULL;
879   
880   startup_id = g_getenv ("DESKTOP_STARTUP_ID");
881   if (startup_id && *startup_id != '\0')
882     {
883       gchar *time_str;
884
885       if (!g_utf8_validate (startup_id, -1, NULL))
886         g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
887       else
888         display_x11->startup_notification_id = g_strdup (startup_id);
889
890       /* Find the launch time from the startup_id, if it's there.  Newer spec
891        * states that the startup_id is of the form <unique>_TIME<timestamp>
892        */
893       time_str = g_strrstr (startup_id, "_TIME");
894       if (time_str != NULL)
895         {
896           gulong retval;
897           gchar *end;
898           errno = 0;
899
900           /* Skip past the "_TIME" part */
901           time_str += 5;
902
903           retval = strtoul (time_str, &end, 0);
904           if (end != time_str && errno == 0)
905             display_x11->user_time = retval;
906         }
907       
908       /* Clear the environment variable so it won't be inherited by
909        * child processes and confuse things.  
910        */
911       g_unsetenv ("DESKTOP_STARTUP_ID");
912
913       /* Set the startup id on the leader window so it
914        * applies to all windows we create on this display
915        */
916       XChangeProperty (display_x11->xdisplay,
917                        display_x11->leader_window,
918                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
919                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
920                        PropModeReplace,
921                        (guchar *)startup_id, strlen (startup_id));
922     }
923 }
924
925 static char*
926 escape_for_xmessage (const char *str)
927 {
928   GString *retval;
929   const char *p;
930   
931   retval = g_string_new (NULL);
932
933   p = str;
934   while (*p)
935     {
936       switch (*p)
937         {
938         case ' ':
939         case '"':
940         case '\\':
941           g_string_append_c (retval, '\\');
942           break;
943         }
944
945       g_string_append_c (retval, *p);
946       ++p;
947     }
948
949   return g_string_free (retval, FALSE);
950 }
951
952 static void
953 broadcast_xmessage   (GdkDisplay   *display,
954                       const char   *message_type,
955                       const char   *message_type_begin,
956                       const char   *message)
957 {
958   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
959   GdkScreen *screen = gdk_display_get_default_screen (display);
960   GdkWindow *root_window = gdk_screen_get_root_window (screen);
961   Window xroot_window = GDK_WINDOW_XID (root_window);
962   
963   Atom type_atom;
964   Atom type_atom_begin;
965   Window xwindow;
966
967   {
968     XSetWindowAttributes attrs;
969
970     attrs.override_redirect = True;
971     attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
972
973     xwindow =
974       XCreateWindow (xdisplay,
975                      xroot_window,
976                      -100, -100, 1, 1,
977                      0,
978                      CopyFromParent,
979                      CopyFromParent,
980                      (Visual *)CopyFromParent,
981                      CWOverrideRedirect | CWEventMask,
982                      &attrs);
983   }
984
985   type_atom = gdk_x11_get_xatom_by_name_for_display (display,
986                                                      message_type);
987   type_atom_begin = gdk_x11_get_xatom_by_name_for_display (display,
988                                                            message_type_begin);
989   
990   {
991     XEvent xevent;
992     const char *src;
993     const char *src_end;
994     char *dest;
995     char *dest_end;
996     
997     xevent.xclient.type = ClientMessage;
998     xevent.xclient.message_type = type_atom_begin;
999     xevent.xclient.display =xdisplay;
1000     xevent.xclient.window = xwindow;
1001     xevent.xclient.format = 8;
1002
1003     src = message;
1004     src_end = message + strlen (message) + 1; /* +1 to include nul byte */
1005     
1006     while (src != src_end)
1007       {
1008         dest = &xevent.xclient.data.b[0];
1009         dest_end = dest + 20;        
1010         
1011         while (dest != dest_end &&
1012                src != src_end)
1013           {
1014             *dest = *src;
1015             ++dest;
1016             ++src;
1017           }
1018
1019         while (dest != dest_end)
1020           {
1021             *dest = 0;
1022             ++dest;
1023           }
1024         
1025         XSendEvent (xdisplay,
1026                     xroot_window,
1027                     False,
1028                     PropertyChangeMask,
1029                     &xevent);
1030
1031         xevent.xclient.message_type = type_atom;
1032       }
1033   }
1034
1035   XDestroyWindow (xdisplay, xwindow);
1036   XFlush (xdisplay);
1037 }
1038
1039 /**
1040  * gdk_notify_startup_complete:
1041  * 
1042  * Indicates to the GUI environment that the application has finished
1043  * loading. If the applications opens windows, this function is
1044  * normally called after opening the application's initial set of
1045  * windows.
1046  * 
1047  * GTK+ will call this function automatically after opening the first
1048  * #GtkWindow unless gtk_window_set_auto_startup_notification() is called 
1049  * to disable that feature.
1050  *
1051  * Since: 2.2
1052  **/
1053 void
1054 gdk_notify_startup_complete (void)
1055 {
1056   GdkDisplay *display;
1057   GdkDisplayX11 *display_x11;
1058   gchar *escaped_id;
1059   gchar *message;
1060
1061   display = gdk_display_get_default ();
1062   if (!display)
1063     return;
1064   
1065   display_x11 = GDK_DISPLAY_X11 (display);
1066
1067   if (display_x11->startup_notification_id == NULL)
1068     return;
1069
1070   escaped_id = escape_for_xmessage (display_x11->startup_notification_id);
1071   message = g_strdup_printf ("remove: ID=%s", escaped_id);
1072   g_free (escaped_id);
1073
1074   broadcast_xmessage (display,
1075                       "_NET_STARTUP_INFO",
1076                       "_NET_STARTUP_INFO_BEGIN",
1077                       message);
1078
1079   g_free (message);
1080 }
1081
1082
1083 /**
1084  * gdk_display_supports_selection_notification:
1085  * @display: a #GdkDisplay
1086  * 
1087  * Returns whether #GdkEventOwnerChange events will be 
1088  * sent when the owner of a selection changes.
1089  * 
1090  * Return value: whether #GdkEventOwnerChange events will 
1091  *               be sent.
1092  *
1093  * Since: 2.6
1094  **/
1095 gboolean 
1096 gdk_display_supports_selection_notification (GdkDisplay *display)
1097 {
1098   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1099
1100   return display_x11->have_xfixes;
1101 }
1102
1103 /**
1104  * gdk_display_request_selection_notification:
1105  * @display: a #GdkDisplay
1106  * @selection: the #GdkAtom naming the selection for which
1107  *             ownership change notification is requested
1108  * 
1109  * Request #GdkEventOwnerChange events for ownership changes
1110  * of the selection named by the given atom.
1111  * 
1112  * Return value: whether #GdkEventOwnerChange events will 
1113  *               be sent.
1114  *
1115  * Since: 2.6
1116  **/
1117 gboolean gdk_display_request_selection_notification  (GdkDisplay *display,
1118                                                       GdkAtom     selection)
1119
1120 {
1121 #ifdef HAVE_XFIXES
1122   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1123   Atom atom;
1124
1125   if (display_x11->have_xfixes)
1126     {
1127       atom = gdk_x11_atom_to_xatom_for_display (display, 
1128                                                 selection);
1129       XFixesSelectSelectionInput (display_x11->xdisplay, 
1130                                   display_x11->leader_window,
1131                                   atom,
1132                                   XFixesSetSelectionOwnerNotifyMask |
1133                                   XFixesSelectionWindowDestroyNotifyMask |
1134                                   XFixesSelectionClientCloseNotifyMask);
1135       return TRUE;
1136     }
1137   else
1138 #endif
1139     return FALSE;
1140 }
1141
1142 /**
1143  * gdk_display_supports_clipboard_persistence
1144  * @display: a #GdkDisplay
1145  *
1146  * Returns whether the speicifed display supports clipboard
1147  * persistance; i.e. if it's possible to store the clipboard data after an
1148  * application has quit. On X11 this checks if a clipboard daemon is
1149  * running.
1150  *
1151  * Returns: %TRUE if the display supports clipboard persistance.
1152  *
1153  * Since: 2.6
1154  */
1155 gboolean
1156 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
1157 {
1158   /* It might make sense to cache this */
1159   return XGetSelectionOwner (GDK_DISPLAY_X11 (display)->xdisplay,
1160                              gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER")) != None;
1161 }
1162
1163 /**
1164  * gdk_display_store_clipboard
1165  * @display:          a #GdkDisplay
1166  * @clipboard_window: a #GdkWindow belonging to the clipboard owner
1167  * @time_:            a timestamp
1168  * @targets:          an array of targets that should be saved, or %NULL 
1169  *                    if all available targets should be saved.
1170  * @n_targets:        length of the @targets array
1171  *
1172  * Issues a request to the clipboard manager to store the
1173  * clipboard data. On X11, this is a special program that works
1174  * according to the freedesktop clipboard specification, available at
1175  * <ulink url="http://www.freedesktop.org/Standards/clipboard-manager-spec">
1176  * http://www.freedesktop.org/Standards/clipboard-manager-spec</ulink>.
1177  *
1178  * Since: 2.6
1179  */
1180 void
1181 gdk_display_store_clipboard (GdkDisplay *display,
1182                              GdkWindow  *clipboard_window,
1183                              guint32     time_,
1184                              GdkAtom    *targets,
1185                              gint        n_targets)
1186 {
1187   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1188   Atom clipboard_manager, save_targets;
1189   
1190   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
1191   save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
1192
1193   gdk_error_trap_push ();
1194
1195   if (XGetSelectionOwner (display_x11->xdisplay, clipboard_manager) != None)
1196     {
1197       Atom property_name = None;
1198       Atom *xatoms;
1199       int i;
1200       
1201       if (n_targets > 0)
1202         {
1203           property_name = gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property);
1204
1205           xatoms = g_new (Atom, n_targets);
1206           for (i = 0; i < n_targets; i++)
1207             xatoms[i] = gdk_x11_atom_to_xatom_for_display (display, targets[i]);
1208
1209           XChangeProperty (display_x11->xdisplay, GDK_WINDOW_XID (clipboard_window),
1210                            property_name, XA_ATOM,
1211                            32, PropModeReplace, (guchar *)xatoms, n_targets);
1212           g_free (xatoms);
1213
1214         }
1215       
1216       XConvertSelection (display_x11->xdisplay,
1217                          clipboard_manager, save_targets, property_name,
1218                          GDK_WINDOW_XID (clipboard_window), time_);
1219       
1220     }
1221   gdk_error_trap_pop ();
1222
1223 }
1224
1225 /**
1226  * gdk_x11_display_get_user_time:
1227  * @display: a #GdkDisplay
1228  *
1229  * Returns the timestamp of the last user interaction on 
1230  * @display. The timestamp is taken from events caused
1231  * by user interaction such as key presses or pointer 
1232  * movements. See gdk_x11_window_set_user_time().
1233  *
1234  * Returns: the timestamp of the last user interaction 
1235  *
1236  * Since: 2.8
1237  */
1238 guint32
1239 gdk_x11_display_get_user_time (GdkDisplay *display)
1240 {
1241   return GDK_DISPLAY_X11 (display)->user_time;
1242 }
1243
1244 #define __GDK_DISPLAY_X11_C__
1245 #include "gdkaliasdef.c"