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