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