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