]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdisplay-x11.c
Handle broken grabs.
[~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                                             "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             XkbSetDetectableAutoRepeat (display_x11->xdisplay,
285                                         True,
286                                         &detectable_autorepeat_supported);
287
288             GDK_NOTE (MISC, g_message ("Detectable autorepeat %s.",
289                                        detectable_autorepeat_supported ? 
290                                        "supported" : "not supported"));
291             
292             display_x11->have_xkb_autorepeat = detectable_autorepeat_supported;
293           }
294       }
295   }
296 #endif
297
298   display_x11->use_sync = FALSE;
299 #ifdef HAVE_XSYNC
300   {
301     int major, minor;
302     int error_base, event_base;
303     
304     if (XSyncQueryExtension (display_x11->xdisplay,
305                              &event_base, &error_base) &&
306         XSyncInitialize (display_x11->xdisplay,
307                          &major, &minor))
308       display_x11->use_sync = TRUE;
309   }
310 #endif
311   
312   _gdk_windowing_image_init (display);
313   _gdk_events_init (display);
314   _gdk_input_init (display);
315   _gdk_dnd_init (display);
316
317   g_signal_emit_by_name (gdk_display_manager_get(),
318                          "display_opened", display);
319
320   return display;
321 }
322
323 #ifdef HAVE_X11R6
324 /*
325  * XLib internal connection handling
326  */
327 typedef struct _GdkInternalConnection GdkInternalConnection;
328
329 struct _GdkInternalConnection
330 {
331   gint           fd;
332   GSource       *source;
333   Display       *display;
334 };
335
336 static gboolean
337 process_internal_connection (GIOChannel  *gioc,
338                              GIOCondition cond,
339                              gpointer     data)
340 {
341   GdkInternalConnection *connection = (GdkInternalConnection *)data;
342
343   GDK_THREADS_ENTER ();
344
345   XProcessInternalConnection ((Display*)connection->display, connection->fd);
346
347   GDK_THREADS_LEAVE ();
348
349   return TRUE;
350 }
351
352 static GdkInternalConnection *
353 gdk_add_connection_handler (Display *display,
354                             guint    fd)
355 {
356   GIOChannel *io_channel;
357   GdkInternalConnection *connection;
358
359   connection = g_new (GdkInternalConnection, 1);
360
361   connection->fd = fd;
362   connection->display = display;
363   
364   io_channel = g_io_channel_unix_new (fd);
365   
366   connection->source = g_io_create_watch (io_channel, G_IO_IN);
367   g_source_set_callback (connection->source,
368                          (GSourceFunc)process_internal_connection, connection, NULL);
369   g_source_attach (connection->source, NULL);
370   
371   g_io_channel_unref (io_channel);
372   
373   return connection;
374 }
375
376 static void
377 gdk_remove_connection_handler (GdkInternalConnection *connection)
378 {
379   g_source_destroy (connection->source);
380   g_free (connection);
381 }
382
383 static void
384 gdk_internal_connection_watch (Display  *display,
385                                XPointer  arg,
386                                gint      fd,
387                                gboolean  opening,
388                                XPointer *watch_data)
389 {
390   if (opening)
391     *watch_data = (XPointer)gdk_add_connection_handler (display, fd);
392   else
393     gdk_remove_connection_handler ((GdkInternalConnection *)*watch_data);
394 }
395 #endif /* HAVE_X11R6 */
396
397 /**
398  * gdk_display_get_name:
399  * @display: a #GdkDisplay
400  *
401  * Gets the name of the display.
402  * 
403  * Returns: a string representing the display name. This string is owned
404  * by GDK and should not be modified or freed.
405  * 
406  * Since: 2.2
407  */
408 G_CONST_RETURN gchar *
409 gdk_display_get_name (GdkDisplay * display)
410 {
411   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
412   
413   return (gchar *) DisplayString (GDK_DISPLAY_X11 (display)->xdisplay);
414 }
415
416 /**
417  * gdk_display_get_n_screens:
418  * @display: a #GdkDisplay
419  *
420  * Gets the number of screen managed by the @display.
421  * 
422  * Returns: number of screens.
423  * 
424  * Since: 2.2
425  */
426 gint
427 gdk_display_get_n_screens (GdkDisplay * display)
428 {
429   g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
430   
431   return ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay);
432 }
433
434 /**
435  * gdk_display_get_screen:
436  * @display: a #GdkDisplay
437  * @screen_num: the screen number
438  *
439  * Returns a screen object for one of the screens of the display.
440  *
441  * Returns: the #GdkScreen object
442  *
443  * Since: 2.2
444  */
445 GdkScreen *
446 gdk_display_get_screen (GdkDisplay * display, gint screen_num)
447 {
448   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
449   g_return_val_if_fail (ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay) > screen_num, NULL);
450   
451   return GDK_DISPLAY_X11 (display)->screens[screen_num];
452 }
453
454 /**
455  * gdk_display_get_default_screen:
456  * @display: a #GdkDisplay
457  *
458  * Get the default #GdkScreen for @display.
459  * 
460  * Returns: the default #GdkScreen object for @display
461  *
462  * Since: 2.2
463  */
464 GdkScreen *
465 gdk_display_get_default_screen (GdkDisplay * display)
466 {
467   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
468   
469   return GDK_DISPLAY_X11 (display)->default_screen;
470 }
471
472 gboolean
473 _gdk_x11_display_is_root_window (GdkDisplay *display,
474                                  Window      xroot_window)
475 {
476   GdkDisplayX11 *display_x11;
477   gint i;
478   
479   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
480   
481   display_x11 = GDK_DISPLAY_X11 (display);
482   
483   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
484     {
485       if (GDK_SCREEN_XROOTWIN (display_x11->screens[i]) == xroot_window)
486         return TRUE;
487     }
488   return FALSE;
489 }
490
491 #define XSERVER_TIME_IS_LATER(time1, time2)                        \
492   ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
493     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
494   )
495
496 /**
497  * gdk_display_pointer_ungrab:
498  * @display: a #GdkDisplay.
499  * @time_: a timestap (e.g. GDK_CURRENT_TIME).
500  *
501  * Release any pointer grab.
502  *
503  * Since: 2.2
504  */
505 void
506 gdk_display_pointer_ungrab (GdkDisplay *display,
507                             guint32     time)
508 {
509   Display *xdisplay;
510   GdkDisplayX11 *display_x11;
511
512   g_return_if_fail (GDK_IS_DISPLAY (display));
513
514   display_x11 = GDK_DISPLAY_X11 (display);
515   xdisplay = GDK_DISPLAY_XDISPLAY (display);
516   
517   _gdk_input_ungrab_pointer (display, time);
518   XUngrabPointer (xdisplay, time);
519   XFlush (xdisplay);
520
521   if (time == GDK_CURRENT_TIME || 
522       display_x11->pointer_xgrab_time == GDK_CURRENT_TIME ||
523       !XSERVER_TIME_IS_LATER (display_x11->pointer_xgrab_time, time))
524     display_x11->pointer_xgrab_window = NULL;
525 }
526
527 /**
528  * gdk_display_pointer_is_grabbed:
529  * @display: a #GdkDisplay
530  *
531  * Test if the pointer is grabbed.
532  *
533  * Returns: %TRUE if an active X pointer grab is in effect
534  *
535  * Since: 2.2
536  */
537 gboolean
538 gdk_display_pointer_is_grabbed (GdkDisplay * display)
539 {
540   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
541   
542   return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL &&
543           !GDK_DISPLAY_X11 (display)->pointer_xgrab_implicit);
544 }
545
546 /**
547  * gdk_display_keyboard_ungrab:
548  * @display: a #GdkDisplay.
549  * @time_: a timestap (e.g #GDK_CURRENT_TIME).
550  *
551  * Release any keyboard grab
552  *
553  * Since: 2.2
554  */
555 void
556 gdk_display_keyboard_ungrab (GdkDisplay *display,
557                              guint32     time)
558 {
559   Display *xdisplay;
560   GdkDisplayX11 *display_x11;
561   
562   g_return_if_fail (GDK_IS_DISPLAY (display));
563
564   display_x11 = GDK_DISPLAY_X11 (display);
565   xdisplay = GDK_DISPLAY_XDISPLAY (display);
566   
567   XUngrabKeyboard (xdisplay, time);
568   XFlush (xdisplay);
569   
570   if (time == GDK_CURRENT_TIME || 
571       display_x11->keyboard_xgrab_time == GDK_CURRENT_TIME ||
572       !XSERVER_TIME_IS_LATER (display_x11->keyboard_xgrab_time, time))
573     display_x11->keyboard_xgrab_window = NULL;
574 }
575
576 /**
577  * gdk_display_beep:
578  * @display: a #GdkDisplay
579  *
580  * Emits a short beep on @display
581  *
582  * Since: 2.2
583  */
584 void
585 gdk_display_beep (GdkDisplay * display)
586 {
587   g_return_if_fail (GDK_IS_DISPLAY (display));
588   
589   XBell (GDK_DISPLAY_XDISPLAY (display), 0);
590 }
591
592 /**
593  * gdk_display_sync:
594  * @display: a #GdkDisplay
595  *
596  * Flushes any requests queued for the windowing system and waits until all
597  * requests have been handled. This is often used for making sure that the
598  * display is synchronized with the current state of the program. Calling
599  * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors
600  * generated from earlier requests are handled before the error trap is 
601  * removed.
602  *
603  * This is most useful for X11. On windowing systems where requests are
604  * handled synchronously, this function will do nothing.
605  *
606  * Since: 2.2
607  */
608 void
609 gdk_display_sync (GdkDisplay * display)
610 {
611   g_return_if_fail (GDK_IS_DISPLAY (display));
612   
613   XSync (GDK_DISPLAY_XDISPLAY (display), False);
614 }
615
616 /**
617  * gdk_display_flush:
618  * @display: a #GdkDisplay
619  *
620  * Flushes any requests queued for the windowing system; this happens automatically
621  * when the main loop blocks waiting for new events, but if your application
622  * is drawing without returning control to the main loop, you may need
623  * to call this function explicitely. A common case where this function
624  * needs to be called is when an application is executing drawing commands
625  * from a thread other than the thread where the main loop is running.
626  *
627  * This is most useful for X11. On windowing systems where requests are
628  * handled synchronously, this function will do nothing.
629  *
630  * Since: 2.4
631  */
632 void 
633 gdk_display_flush (GdkDisplay *display)
634 {
635   g_return_if_fail (GDK_IS_DISPLAY (display));
636
637   if (!display->closed)
638     XFlush (GDK_DISPLAY_XDISPLAY (display));
639 }
640
641 /**
642  * gdk_display_get_default_group:
643  * @display: a #GdkDisplay
644  * 
645  * Returns the default group leader window for all toplevel windows
646  * on @display. This window is implicitly created by GDK. 
647  * See gdk_window_set_group().
648  * 
649  * Return value: The default group leader window for @display
650  *
651  * Since: 2.4
652  **/
653 GdkWindow *gdk_display_get_default_group (GdkDisplay *display)
654 {
655   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
656
657   return GDK_DISPLAY_X11 (display)->leader_gdk_window;
658 }
659
660 /**
661  * gdk_x11_display_grab:
662  * @display: a #GdkDisplay 
663  * 
664  * Call XGrabServer() on @display. 
665  * To ungrab the display again, use gdk_x11_display_ungrab(). 
666  *
667  * gdk_x11_display_grab()/gdk_x11_display_ungrab() calls can be nested.
668  *
669  * Since: 2.2
670  **/
671 void
672 gdk_x11_display_grab (GdkDisplay * display)
673 {
674   GdkDisplayX11 *display_x11;
675   
676   g_return_if_fail (GDK_IS_DISPLAY (display));
677   
678   display_x11 = GDK_DISPLAY_X11 (display);
679   
680   if (display_x11->grab_count == 0)
681     XGrabServer (display_x11->xdisplay);
682   display_x11->grab_count++;
683 }
684
685 /**
686  * gdk_x11_display_ungrab:
687  * @display: a #GdkDisplay
688  * 
689  * Ungrab @display after it has been grabbed with 
690  * gdk_x11_display_grab(). 
691  *
692  * Since: 2.2
693  **/
694 void
695 gdk_x11_display_ungrab (GdkDisplay * display)
696 {
697   GdkDisplayX11 *display_x11;
698   
699   g_return_if_fail (GDK_IS_DISPLAY (display));
700   
701   display_x11 = GDK_DISPLAY_X11 (display);;
702   g_return_if_fail (display_x11->grab_count > 0);
703   
704   display_x11->grab_count--;
705   if (display_x11->grab_count == 0)
706     {
707       XUngrabServer (display_x11->xdisplay);
708       XFlush (display_x11->xdisplay);
709     }
710 }
711
712 static void
713 gdk_display_x11_dispose (GObject *object)
714 {
715   GdkDisplayX11 *display_x11;
716   gint i;
717   
718   display_x11 = GDK_DISPLAY_X11 (object);
719   
720   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
721     _gdk_screen_close (display_x11->screens[i]);
722
723   g_source_destroy (display_x11->event_source);
724
725   XCloseDisplay (display_x11->xdisplay);
726   display_x11->xdisplay = NULL;
727
728   G_OBJECT_CLASS (parent_class)->dispose (object);
729 }
730
731 static void
732 gdk_display_x11_finalize (GObject *object)
733 {
734   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
735   int i;
736   GList *tmp;
737   /* FIXME need to write GdkKeymap finalize fct 
738      g_object_unref (display_x11->keymap);
739    */
740   /* Free motif Dnd */
741   if (display_x11->motif_target_lists)
742     {
743       for (i = 0; i < display_x11->motif_n_target_lists; i++)
744         g_list_free (display_x11->motif_target_lists[i]);
745       g_free (display_x11->motif_target_lists);
746     }
747
748   /* Atom Hashtable */
749   g_hash_table_destroy (display_x11->atom_from_virtual);
750   g_hash_table_destroy (display_x11->atom_to_virtual);
751   /* Leader Window */
752   XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);
753   /* list of filters for client messages */
754   g_list_free (display_x11->client_filters);
755   /* List of event window extraction functions */
756   g_slist_foreach (display_x11->event_types, (GFunc)g_free, NULL);
757   g_slist_free (display_x11->event_types);
758   /* X ID hashtable */
759   g_hash_table_destroy (display_x11->xid_ht);
760   /* input GdkDevice list */
761   /* FIXME need to write finalize fct */
762   for (tmp = display_x11->input_devices; tmp; tmp = tmp->next)
763     g_object_unref (tmp->data);
764   g_list_free (display_x11->input_devices);
765   /* input GdkWindow list */
766   for (tmp = display_x11->input_windows; tmp; tmp = tmp->next)
767     g_object_unref (tmp->data);
768   g_list_free (display_x11->input_windows);
769   /* Free all GdkScreens */
770   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
771     g_object_unref (display_x11->screens[i]);
772   g_free (display_x11->screens);
773   g_free (display_x11->startup_notification_id);
774   
775   G_OBJECT_CLASS (parent_class)->finalize (object);
776 }
777
778 /**
779  * gdk_x11_lookup_xdisplay:
780  * @xdisplay: a pointer to an X Display
781  * 
782  * Find the #GdkDisplay corresponding to @display, if any exists.
783  * 
784  * Return value: the #GdkDisplay, if found, otherwise %NULL.
785  *
786  * Since: 2.2
787  **/
788 GdkDisplay *
789 gdk_x11_lookup_xdisplay (Display *xdisplay)
790 {
791   GSList *tmp_list;
792
793   for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
794     {
795       if (GDK_DISPLAY_XDISPLAY (tmp_list->data) == xdisplay)
796         return tmp_list->data;
797     }
798   
799   return NULL;
800 }
801
802 /**
803  * _gdk_x11_display_screen_for_xrootwin:
804  * @display: a #Display
805  * @xrootwin: window ID for one of of the screen's of the display.
806  * 
807  * Given the root window ID of one of the screen's of a #GdkDisplay,
808  * finds the screen.
809  * 
810  * Return value: the #GdkScreen corresponding to @xrootwin, or %NULL.
811  **/
812 GdkScreen *
813 _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
814                                       Window      xrootwin)
815 {
816   gint n_screens, i;
817
818   n_screens = gdk_display_get_n_screens (display);
819   for (i = 0; i < n_screens; i++)
820     {
821       GdkScreen *screen = gdk_display_get_screen (display, i);
822       if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
823         return screen;
824     }
825
826   return NULL;
827 }
828
829 /**
830  * gdk_x11_display_get_xdisplay:
831  * @display: a #GdkDisplay
832  * @returns: an X display.
833  *
834  * Returns the X display of a #GdkDisplay.
835  *
836  * Since: 2.2
837  */
838 Display *
839 gdk_x11_display_get_xdisplay (GdkDisplay  *display)
840 {
841   return GDK_DISPLAY_X11 (display)->xdisplay;
842 }
843
844 void
845 _gdk_windowing_set_default_display (GdkDisplay *display)
846 {
847   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
848   const gchar *startup_id;
849   
850   if (display)
851     gdk_display = GDK_DISPLAY_XDISPLAY (display);
852   else
853     gdk_display = NULL;
854
855   g_free (display_x11->startup_notification_id);
856   display_x11->startup_notification_id = NULL;
857   
858   startup_id = g_getenv ("DESKTOP_STARTUP_ID");
859   if (startup_id && *startup_id != '\0')
860     {
861       gchar *time_str;
862
863       if (!g_utf8_validate (startup_id, -1, NULL))
864         g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
865       else
866         display_x11->startup_notification_id = g_strdup (startup_id);
867
868       /* Find the launch time from the startup_id, if it's there.  Newer spec
869        * states that the startup_id is of the form <unique>_TIME<timestamp>
870        */
871       time_str = g_strrstr (startup_id, "_TIME");
872       if (time_str != NULL)
873         {
874           gulong retval;
875           gchar *end;
876           errno = 0;
877
878           /* Skip past the "_TIME" part */
879           time_str += 5;
880
881           retval = strtoul (time_str, &end, 0);
882           if (end != time_str && errno == 0)
883             display_x11->user_time = retval;
884         }
885       
886       /* Clear the environment variable so it won't be inherited by
887        * child processes and confuse things.  
888        */
889       g_unsetenv ("DESKTOP_STARTUP_ID");
890
891       /* Set the startup id on the leader window so it
892        * applies to all windows we create on this display
893        */
894       XChangeProperty (display_x11->xdisplay,
895                        display_x11->leader_window,
896                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
897                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
898                        PropModeReplace,
899                        startup_id, strlen (startup_id));
900     }
901 }
902
903 static char*
904 escape_for_xmessage (const char *str)
905 {
906   GString *retval;
907   const char *p;
908   
909   retval = g_string_new (NULL);
910
911   p = str;
912   while (*p)
913     {
914       switch (*p)
915         {
916         case ' ':
917         case '"':
918         case '\\':
919           g_string_append_c (retval, '\\');
920           break;
921         }
922
923       g_string_append_c (retval, *p);
924       ++p;
925     }
926
927   return g_string_free (retval, FALSE);
928 }
929
930 static void
931 broadcast_xmessage   (GdkDisplay   *display,
932                       const char   *message_type,
933                       const char   *message_type_begin,
934                       const char   *message)
935 {
936   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
937   GdkScreen *screen = gdk_display_get_default_screen (display);
938   GdkWindow *root_window = gdk_screen_get_root_window (screen);
939   Window xroot_window = GDK_WINDOW_XID (root_window);
940   
941   Atom type_atom;
942   Atom type_atom_begin;
943   Window xwindow;
944
945   {
946     XSetWindowAttributes attrs;
947
948     attrs.override_redirect = True;
949     attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
950
951     xwindow =
952       XCreateWindow (xdisplay,
953                      xroot_window,
954                      -100, -100, 1, 1,
955                      0,
956                      CopyFromParent,
957                      CopyFromParent,
958                      (Visual *)CopyFromParent,
959                      CWOverrideRedirect | CWEventMask,
960                      &attrs);
961   }
962
963   type_atom = gdk_x11_get_xatom_by_name_for_display (display,
964                                                      message_type);
965   type_atom_begin = gdk_x11_get_xatom_by_name_for_display (display,
966                                                            message_type_begin);
967   
968   {
969     XEvent xevent;
970     const char *src;
971     const char *src_end;
972     char *dest;
973     char *dest_end;
974     
975     xevent.xclient.type = ClientMessage;
976     xevent.xclient.message_type = type_atom_begin;
977     xevent.xclient.display =xdisplay;
978     xevent.xclient.window = xwindow;
979     xevent.xclient.format = 8;
980
981     src = message;
982     src_end = message + strlen (message) + 1; /* +1 to include nul byte */
983     
984     while (src != src_end)
985       {
986         dest = &xevent.xclient.data.b[0];
987         dest_end = dest + 20;        
988         
989         while (dest != dest_end &&
990                src != src_end)
991           {
992             *dest = *src;
993             ++dest;
994             ++src;
995           }
996
997         while (dest != dest_end)
998           {
999             *dest = 0;
1000             ++dest;
1001           }
1002         
1003         XSendEvent (xdisplay,
1004                     xroot_window,
1005                     False,
1006                     PropertyChangeMask,
1007                     &xevent);
1008
1009         xevent.xclient.message_type = type_atom;
1010       }
1011   }
1012
1013   XDestroyWindow (xdisplay, xwindow);
1014   XFlush (xdisplay);
1015 }
1016
1017 /**
1018  * gdk_notify_startup_complete:
1019  * 
1020  * Indicates to the GUI environment that the application has finished
1021  * loading. If the applications opens windows, this function is
1022  * normally called after opening the application's initial set of
1023  * windows.
1024  * 
1025  * GTK+ will call this function automatically after opening the first
1026  * #GtkWindow unless gtk_window_set_auto_startup_notification() is called 
1027  * to disable that feature.
1028  *
1029  * Since: 2.2
1030  **/
1031 void
1032 gdk_notify_startup_complete (void)
1033 {
1034   GdkDisplay *display;
1035   GdkDisplayX11 *display_x11;
1036   gchar *escaped_id;
1037   gchar *message;
1038
1039   display = gdk_display_get_default ();
1040   if (!display)
1041     return;
1042   
1043   display_x11 = GDK_DISPLAY_X11 (display);
1044
1045   if (display_x11->startup_notification_id == NULL)
1046     return;
1047
1048   escaped_id = escape_for_xmessage (display_x11->startup_notification_id);
1049   message = g_strdup_printf ("remove: ID=%s", escaped_id);
1050   g_free (escaped_id);
1051
1052   broadcast_xmessage (display,
1053                       "_NET_STARTUP_INFO",
1054                       "_NET_STARTUP_INFO_BEGIN",
1055                       message);
1056
1057   g_free (message);
1058 }
1059
1060
1061 /**
1062  * gdk_display_supports_selection_notification:
1063  * @display: a #GdkDisplay
1064  * 
1065  * Returns whether #GdkEventOwnerChange events will be 
1066  * sent when the owner of a selection changes.
1067  * 
1068  * Return value: whether #GdkEventOwnerChange events will 
1069  *               be sent.
1070  *
1071  * Since: 2.6
1072  **/
1073 gboolean 
1074 gdk_display_supports_selection_notification (GdkDisplay *display)
1075 {
1076   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1077
1078   return display_x11->have_xfixes;
1079 }
1080
1081 /**
1082  * gdk_display_request_selection_notification:
1083  * @display: a #GdkDisplay
1084  * @selection: the #GdkAtom naming the selection for which
1085  *             ownership change notification is requested
1086  * 
1087  * Request #GdkEventOwnerChange events for ownership changes
1088  * of the selection named by the given atom.
1089  * 
1090  * Return value: whether #GdkEventOwnerChange events will 
1091  *               be sent.
1092  *
1093  * Since: 2.6
1094  **/
1095 gboolean gdk_display_request_selection_notification  (GdkDisplay *display,
1096                                                       GdkAtom     selection)
1097
1098 {
1099 #ifdef HAVE_XFIXES
1100   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1101   Atom atom;
1102
1103   if (display_x11->have_xfixes)
1104     {
1105       atom = gdk_x11_atom_to_xatom_for_display (display, 
1106                                                 selection);
1107       XFixesSelectSelectionInput (display_x11->xdisplay, 
1108                                   display_x11->leader_window,
1109                                   atom,
1110                                   XFixesSetSelectionOwnerNotifyMask |
1111                                   XFixesSelectionWindowDestroyNotifyMask |
1112                                   XFixesSelectionClientCloseNotifyMask);
1113       return TRUE;
1114     }
1115   else
1116 #endif
1117     return FALSE;
1118 }
1119
1120 /**
1121  * gdk_display_supports_clipboard_persistence
1122  * @display: a #GdkDisplay
1123  *
1124  * Returns whether the speicifed display supports clipboard
1125  * persistance; i.e. if it's possible to store the clipboard data after an
1126  * application has quit. On X11 this checks if a clipboard daemon is
1127  * running.
1128  *
1129  * Returns: %TRUE if the display supports clipboard persistance.
1130  *
1131  * Since: 2.6
1132  */
1133 gboolean
1134 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
1135 {
1136   /* It might make sense to cache this */
1137   return XGetSelectionOwner (GDK_DISPLAY_X11 (display)->xdisplay,
1138                              gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER")) != None;
1139 }
1140
1141 /**
1142  * gdk_display_store_clipboard
1143  * @display:          a #GdkDisplay
1144  * @clipboard_window: a #GdkWindow belonging to the clipboard owner
1145  * @time_:            a timestamp
1146  * @targets:          an array of targets that should be saved, or %NULL 
1147  *                    if all available targets should be saved.
1148  * @n_targets:        length of the @targets array
1149  *
1150  * Issues a request to the clipboard manager to store the
1151  * clipboard data. On X11, this is a special program that works
1152  * according to the freedesktop clipboard specification, available at
1153  * <ulink url="http://www.freedesktop.org/Standards/clipboard-manager-spec">
1154  * http://www.freedesktop.org/Standards/clipboard-manager-spec</ulink>.
1155  *
1156  * Since: 2.6
1157  */
1158 void
1159 gdk_display_store_clipboard (GdkDisplay *display,
1160                              GdkWindow  *clipboard_window,
1161                              guint32     time_,
1162                              GdkAtom    *targets,
1163                              gint        n_targets)
1164 {
1165   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1166   Atom clipboard_manager, save_targets;
1167   
1168   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
1169   save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
1170
1171   gdk_error_trap_push ();
1172
1173   if (XGetSelectionOwner (display_x11->xdisplay, clipboard_manager) != None)
1174     {
1175       Atom property_name = None;
1176       Atom *xatoms;
1177       int i;
1178       
1179       if (n_targets > 0)
1180         {
1181           property_name = gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property);
1182
1183           xatoms = g_new (Atom, n_targets);
1184           for (i = 0; i < n_targets; i++)
1185             xatoms[i] = gdk_x11_atom_to_xatom_for_display (display, targets[i]);
1186
1187           XChangeProperty (display_x11->xdisplay, GDK_WINDOW_XID (clipboard_window),
1188                            property_name, XA_ATOM,
1189                            32, PropModeReplace, (guchar *)xatoms, n_targets);
1190           g_free (xatoms);
1191
1192         }
1193       
1194       XConvertSelection (display_x11->xdisplay,
1195                          clipboard_manager, save_targets, property_name,
1196                          GDK_WINDOW_XID (clipboard_window), time_);
1197       
1198     }
1199   gdk_error_trap_pop ();
1200
1201 }
1202
1203 /**
1204  * gdk_x11_display_get_user_time:
1205  * @display: a #GdkDisplay
1206  *
1207  * Returns the timestamp of the last user interaction on 
1208  * @display. The timestamp is taken from events caused
1209  * by user interaction such as key presses or pointer 
1210  * movements. See gdk_x11_window_set_user_time().
1211  *
1212  * Returns: the timestamp of the last user interaction 
1213  *
1214  * Since: 2.8
1215  */
1216 guint32
1217 gdk_x11_display_get_user_time (GdkDisplay *display)
1218 {
1219   return GDK_DISPLAY_X11 (display)->user_time;
1220 }
1221
1222 #define __GDK_DISPLAY_X11_C__
1223 #include "gdkaliasdef.c"