]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdisplay-x11.c
Merge branch 'master' into broadway
[~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 "gdkasync.h"
28 #include "gdkdisplay.h"
29 #include "gdkeventsource.h"
30 #include "gdkeventtranslator.h"
31 #include "gdkinternals.h"
32 #include "gdkscreen.h"
33 #include "gdkinternals.h"
34 #include "gdkdeviceprivate.h"
35 #include "gdkkeysprivate.h"
36 #include "gdkdevicemanager.h"
37 #include "xsettings-client.h"
38 #include "gdkdisplay-x11.h"
39 #include "gdkprivate-x11.h"
40 #include "gdkscreen-x11.h"
41
42 #include <glib.h>
43 #include <glib/gprintf.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <errno.h>
47 #include <unistd.h>
48
49 #include <X11/Xatom.h>
50
51 #ifdef HAVE_XKB
52 #include <X11/XKBlib.h>
53 #endif
54
55 #ifdef HAVE_XFIXES
56 #include <X11/extensions/Xfixes.h>
57 #endif
58
59 #include <X11/extensions/shape.h>
60
61 #ifdef HAVE_XCOMPOSITE
62 #include <X11/extensions/Xcomposite.h>
63 #endif
64
65 #ifdef HAVE_XDAMAGE
66 #include <X11/extensions/Xdamage.h>
67 #endif
68
69 #ifdef HAVE_RANDR
70 #include <X11/extensions/Xrandr.h>
71 #endif
72
73 typedef struct _GdkErrorTrap  GdkErrorTrap;
74
75 struct _GdkErrorTrap
76 {
77   /* Next sequence when trap was pushed, i.e. first sequence to
78    * ignore
79    */
80   gulong start_sequence;
81
82   /* Next sequence when trap was popped, i.e. first sequence
83    * to not ignore. 0 if trap is still active.
84    */
85   gulong end_sequence;
86
87   /* Most recent error code within the sequence */
88   int error_code;
89 };
90
91 static void   gdk_x11_display_dispose            (GObject            *object);
92 static void   gdk_x11_display_finalize           (GObject            *object);
93
94 static void     gdk_x11_display_event_translator_init (GdkEventTranslatorIface *iface);
95
96 static gboolean gdk_x11_display_translate_event (GdkEventTranslator *translator,
97                                                  GdkDisplay         *display,
98                                                  GdkEvent           *event,
99                                                  XEvent             *xevent);
100
101 #ifdef HAVE_X11R6
102 static void gdk_internal_connection_watch (Display  *display,
103                                            XPointer  arg,
104                                            gint      fd,
105                                            gboolean  opening,
106                                            XPointer *watch_data);
107 #endif /* HAVE_X11R6 */
108
109 typedef struct _GdkEventTypeX11 GdkEventTypeX11;
110
111 struct _GdkEventTypeX11
112 {
113   gint base;
114   gint n_events;
115 };
116
117 /* Note that we never *directly* use WM_LOCALE_NAME, WM_PROTOCOLS,
118  * but including them here has the side-effect of getting them
119  * into the internal Xlib cache
120  */
121 static const char *const precache_atoms[] = {
122   "UTF8_STRING",
123   "WM_CLIENT_LEADER",
124   "WM_DELETE_WINDOW",
125   "WM_ICON_NAME",
126   "WM_LOCALE_NAME",
127   "WM_NAME",
128   "WM_PROTOCOLS",
129   "WM_TAKE_FOCUS",
130   "WM_WINDOW_ROLE",
131   "_NET_ACTIVE_WINDOW",
132   "_NET_CURRENT_DESKTOP",
133   "_NET_FRAME_EXTENTS",
134   "_NET_STARTUP_ID",
135   "_NET_WM_CM_S0",
136   "_NET_WM_DESKTOP",
137   "_NET_WM_ICON",
138   "_NET_WM_ICON_NAME",
139   "_NET_WM_NAME",
140   "_NET_WM_PID",
141   "_NET_WM_PING",
142   "_NET_WM_STATE",
143   "_NET_WM_STATE_ABOVE",
144   "_NET_WM_STATE_BELOW",
145   "_NET_WM_STATE_FULLSCREEN",
146   "_NET_WM_STATE_MODAL",
147   "_NET_WM_STATE_MAXIMIZED_VERT",
148   "_NET_WM_STATE_MAXIMIZED_HORZ",
149   "_NET_WM_STATE_SKIP_TASKBAR",
150   "_NET_WM_STATE_SKIP_PAGER",
151   "_NET_WM_STATE_STICKY",
152   "_NET_WM_SYNC_REQUEST",
153   "_NET_WM_SYNC_REQUEST_COUNTER",
154   "_NET_WM_WINDOW_TYPE",
155   "_NET_WM_WINDOW_TYPE_NORMAL",
156   "_NET_WM_USER_TIME",
157   "_NET_VIRTUAL_ROOTS",
158   "GDK_SELECTION"
159 };
160
161 static char *gdk_sm_client_id;
162
163 G_DEFINE_TYPE_WITH_CODE (GdkX11Display, gdk_x11_display, GDK_TYPE_DISPLAY,
164                          G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
165                                                 gdk_x11_display_event_translator_init))
166
167
168 static void
169 gdk_x11_display_init (GdkX11Display *display)
170 {
171   _gdk_x11_display_manager_add_display (gdk_display_manager_get (),
172                                         GDK_DISPLAY (display));
173 }
174
175 static void
176 gdk_x11_display_event_translator_init (GdkEventTranslatorIface *iface)
177 {
178   iface->translate_event = gdk_x11_display_translate_event;
179 }
180
181 static void
182 do_net_wm_state_changes (GdkWindow *window)
183 {
184   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
185   GdkWindowState old_state;
186
187   if (GDK_WINDOW_DESTROYED (window) ||
188       gdk_window_get_window_type (window) != GDK_WINDOW_TOPLEVEL)
189     return;
190
191   old_state = gdk_window_get_state (window);
192
193   /* For found_sticky to remain TRUE, we have to also be on desktop
194    * 0xFFFFFFFF
195    */
196   if (old_state & GDK_WINDOW_STATE_STICKY)
197     {
198       if (!(toplevel->have_sticky && toplevel->on_all_desktops))
199         gdk_synthesize_window_state (window,
200                                      GDK_WINDOW_STATE_STICKY,
201                                      0);
202     }
203   else
204     {
205       if (toplevel->have_sticky || toplevel->on_all_desktops)
206         gdk_synthesize_window_state (window,
207                                      0,
208                                      GDK_WINDOW_STATE_STICKY);
209     }
210
211   if (old_state & GDK_WINDOW_STATE_FULLSCREEN)
212     {
213       if (!toplevel->have_fullscreen)
214         gdk_synthesize_window_state (window,
215                                      GDK_WINDOW_STATE_FULLSCREEN,
216                                      0);
217     }
218   else
219     {
220       if (toplevel->have_fullscreen)
221         gdk_synthesize_window_state (window,
222                                      0,
223                                      GDK_WINDOW_STATE_FULLSCREEN);
224     }
225
226   /* Our "maximized" means both vertical and horizontal; if only one,
227    * we don't expose that via GDK
228    */
229   if (old_state & GDK_WINDOW_STATE_MAXIMIZED)
230     {
231       if (!(toplevel->have_maxvert && toplevel->have_maxhorz))
232         gdk_synthesize_window_state (window,
233                                      GDK_WINDOW_STATE_MAXIMIZED,
234                                      0);
235     }
236   else
237     {
238       if (toplevel->have_maxvert && toplevel->have_maxhorz)
239         gdk_synthesize_window_state (window,
240                                      0,
241                                      GDK_WINDOW_STATE_MAXIMIZED);
242     }
243 }
244
245 static void
246 gdk_check_wm_desktop_changed (GdkWindow *window)
247 {
248   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
249   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
250
251   Atom type;
252   gint format;
253   gulong nitems;
254   gulong bytes_after;
255   guchar *data;
256   gulong *desktop;
257
258   type = None;
259   gdk_x11_display_error_trap_push (display);
260   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
261                       GDK_WINDOW_XID (window),
262                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
263                       0, G_MAXLONG, False, XA_CARDINAL, &type,
264                       &format, &nitems,
265                       &bytes_after, &data);
266   gdk_x11_display_error_trap_pop_ignored (display);
267
268   if (type != None)
269     {
270       desktop = (gulong *)data;
271       toplevel->on_all_desktops = (*desktop == 0xFFFFFFFF);
272       XFree (desktop);
273     }
274   else
275     toplevel->on_all_desktops = FALSE;
276
277   do_net_wm_state_changes (window);
278 }
279
280 static void
281 gdk_check_wm_state_changed (GdkWindow *window)
282 {
283   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
284   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
285
286   Atom type;
287   gint format;
288   gulong nitems;
289   gulong bytes_after;
290   guchar *data;
291   Atom *atoms = NULL;
292   gulong i;
293
294   gboolean had_sticky = toplevel->have_sticky;
295
296   toplevel->have_sticky = FALSE;
297   toplevel->have_maxvert = FALSE;
298   toplevel->have_maxhorz = FALSE;
299   toplevel->have_fullscreen = FALSE;
300
301   type = None;
302   gdk_x11_display_error_trap_push (display);
303   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
304                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
305                       0, G_MAXLONG, False, XA_ATOM, &type, &format, &nitems,
306                       &bytes_after, &data);
307   gdk_x11_display_error_trap_pop_ignored (display);
308
309   if (type != None)
310     {
311       Atom sticky_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_STICKY");
312       Atom maxvert_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT");
313       Atom maxhorz_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ");
314       Atom fullscreen_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FULLSCREEN");
315
316       atoms = (Atom *)data;
317
318       i = 0;
319       while (i < nitems)
320         {
321           if (atoms[i] == sticky_atom)
322             toplevel->have_sticky = TRUE;
323           else if (atoms[i] == maxvert_atom)
324             toplevel->have_maxvert = TRUE;
325           else if (atoms[i] == maxhorz_atom)
326             toplevel->have_maxhorz = TRUE;
327           else if (atoms[i] == fullscreen_atom)
328             toplevel->have_fullscreen = TRUE;
329
330           ++i;
331         }
332
333       XFree (atoms);
334     }
335
336   /* When have_sticky is turned on, we have to check the DESKTOP property
337    * as well.
338    */
339   if (toplevel->have_sticky && !had_sticky)
340     gdk_check_wm_desktop_changed (window);
341   else
342     do_net_wm_state_changes (window);
343 }
344
345 static GdkWindow *
346 get_event_window (GdkEventTranslator *translator,
347                   XEvent             *xevent)
348 {
349   GdkDisplay *display;
350   Window xwindow;
351
352   display = (GdkDisplay *) translator;
353
354   switch (xevent->type)
355     {
356     case DestroyNotify:
357       xwindow = xevent->xdestroywindow.window;
358       break;
359     case UnmapNotify:
360       xwindow = xevent->xunmap.window;
361       break;
362     case MapNotify:
363       xwindow = xevent->xmap.window;
364       break;
365     case ConfigureNotify:
366       xwindow = xevent->xconfigure.window;
367       break;
368     default:
369       xwindow = xevent->xany.window;
370     }
371
372   return gdk_x11_window_lookup_for_display (display, xwindow);
373 }
374
375 static gboolean
376 gdk_x11_display_translate_event (GdkEventTranslator *translator,
377                                  GdkDisplay         *display,
378                                  GdkEvent           *event,
379                                  XEvent             *xevent)
380 {
381   GdkWindow *window;
382   GdkWindowImplX11 *window_impl = NULL;
383   GdkScreen *screen = NULL;
384   GdkX11Screen *x11_screen = NULL;
385   GdkToplevelX11 *toplevel = NULL;
386   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
387   gboolean return_val;
388   Window xwindow = None;
389
390   /* Find the GdkWindow that this event relates to.
391    * Basically this means substructure events
392    * are reported same as structure events
393    */
394   window = get_event_window (translator, xevent);
395
396   if (window)
397     {
398       /* We may receive events such as NoExpose/GraphicsExpose
399        * and ShmCompletion for pixmaps
400        */
401       if (!GDK_IS_WINDOW (window))
402         return FALSE;
403
404       screen = GDK_WINDOW_SCREEN (window);
405       x11_screen = GDK_X11_SCREEN (screen);
406       toplevel = _gdk_x11_window_get_toplevel (window);
407       window_impl = GDK_WINDOW_IMPL_X11 (window->impl);
408       xwindow = GDK_WINDOW_XID (window);
409
410       g_object_ref (window);
411     }
412
413   event->any.window = window;
414   event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
415
416   if (window && GDK_WINDOW_DESTROYED (window))
417     {
418       if (xevent->type != DestroyNotify)
419         {
420           return_val = FALSE;
421           goto done;
422         }
423     }
424
425   if (xevent->type == DestroyNotify)
426     {
427       int i, n;
428
429       n = gdk_display_get_n_screens (display);
430       for (i = 0; i < n; i++)
431         {
432           screen = gdk_display_get_screen (display, i);
433           x11_screen = GDK_X11_SCREEN (screen);
434
435           if (x11_screen->wmspec_check_window == xwindow)
436             {
437               x11_screen->wmspec_check_window = None;
438               x11_screen->last_wmspec_check_time = 0;
439               g_free (x11_screen->window_manager_name);
440               x11_screen->window_manager_name = g_strdup ("unknown");
441
442               /* careful, reentrancy */
443               _gdk_x11_screen_window_manager_changed (screen);
444
445               return_val = FALSE;
446               goto done;
447             }
448         }
449     }
450
451   /* We do a "manual" conversion of the XEvent to a
452    *  GdkEvent. The structures are mostly the same so
453    *  the conversion is fairly straightforward. We also
454    *  optionally print debugging info regarding events
455    *  received.
456    */
457
458   return_val = TRUE;
459
460   switch (xevent->type)
461     {
462     case KeymapNotify:
463       GDK_NOTE (EVENTS,
464                 g_message ("keymap notify"));
465
466       /* Not currently handled */
467       return_val = FALSE;
468       break;
469
470     case Expose:
471       GDK_NOTE (EVENTS,
472                 g_message ("expose:\t\twindow: %ld  %d  x,y: %d %d  w,h: %d %d%s",
473                            xevent->xexpose.window, xevent->xexpose.count,
474                            xevent->xexpose.x, xevent->xexpose.y,
475                            xevent->xexpose.width, xevent->xexpose.height,
476                            event->any.send_event ? " (send)" : ""));
477
478       if (window == NULL)
479         {
480           return_val = FALSE;
481           break;
482         }
483
484       {
485         GdkRectangle expose_rect;
486
487         expose_rect.x = xevent->xexpose.x;
488         expose_rect.y = xevent->xexpose.y;
489         expose_rect.width = xevent->xexpose.width;
490         expose_rect.height = xevent->xexpose.height;
491
492         _gdk_x11_window_process_expose (window, xevent->xexpose.serial, &expose_rect);
493         return_val = FALSE;
494       }
495
496       break;
497
498     case GraphicsExpose:
499       {
500         GdkRectangle expose_rect;
501
502         GDK_NOTE (EVENTS,
503                   g_message ("graphics expose:\tdrawable: %ld",
504                              xevent->xgraphicsexpose.drawable));
505
506         if (window == NULL)
507           {
508             return_val = FALSE;
509             break;
510           }
511
512         expose_rect.x = xevent->xgraphicsexpose.x;
513         expose_rect.y = xevent->xgraphicsexpose.y;
514         expose_rect.width = xevent->xgraphicsexpose.width;
515         expose_rect.height = xevent->xgraphicsexpose.height;
516
517         _gdk_x11_window_process_expose (window, xevent->xgraphicsexpose.serial, &expose_rect);
518         return_val = FALSE;
519       }
520       break;
521
522     case VisibilityNotify:
523 #ifdef G_ENABLE_DEBUG
524       if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
525         switch (xevent->xvisibility.state)
526           {
527           case VisibilityFullyObscured:
528             g_message ("visibility notify:\twindow: %ld  none",
529                        xevent->xvisibility.window);
530             break;
531           case VisibilityPartiallyObscured:
532             g_message ("visibility notify:\twindow: %ld  partial",
533                        xevent->xvisibility.window);
534             break;
535           case VisibilityUnobscured:
536             g_message ("visibility notify:\twindow: %ld  full",
537                        xevent->xvisibility.window);
538             break;
539           }
540 #endif /* G_ENABLE_DEBUG */
541
542       if (window == NULL)
543         {
544           return_val = FALSE;
545           break;
546         }
547
548       event->visibility.type = GDK_VISIBILITY_NOTIFY;
549       event->visibility.window = window;
550
551       switch (xevent->xvisibility.state)
552         {
553         case VisibilityFullyObscured:
554           event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
555           break;
556
557         case VisibilityPartiallyObscured:
558           event->visibility.state = GDK_VISIBILITY_PARTIAL;
559           break;
560
561         case VisibilityUnobscured:
562           event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
563           break;
564         }
565
566       break;
567
568     case CreateNotify:
569       GDK_NOTE (EVENTS,
570                 g_message ("create notify:\twindow: %ld  x,y: %d %d     w,h: %d %d  b-w: %d  parent: %ld         ovr: %d",
571                            xevent->xcreatewindow.window,
572                            xevent->xcreatewindow.x,
573                            xevent->xcreatewindow.y,
574                            xevent->xcreatewindow.width,
575                            xevent->xcreatewindow.height,
576                            xevent->xcreatewindow.border_width,
577                            xevent->xcreatewindow.parent,
578                            xevent->xcreatewindow.override_redirect));
579       /* not really handled */
580       break;
581
582     case DestroyNotify:
583       GDK_NOTE (EVENTS,
584                 g_message ("destroy notify:\twindow: %ld",
585                            xevent->xdestroywindow.window));
586
587       /* Ignore DestroyNotify from SubstructureNotifyMask */
588       if (xevent->xdestroywindow.window == xevent->xdestroywindow.event)
589         {
590           event->any.type = GDK_DESTROY;
591           event->any.window = window;
592
593           return_val = window && !GDK_WINDOW_DESTROYED (window);
594
595           if (window && GDK_WINDOW_XID (window) != x11_screen->xroot_window)
596             gdk_window_destroy_notify (window);
597         }
598       else
599         return_val = FALSE;
600
601       break;
602
603     case UnmapNotify:
604       GDK_NOTE (EVENTS,
605                 g_message ("unmap notify:\t\twindow: %ld",
606                            xevent->xmap.window));
607
608       event->any.type = GDK_UNMAP;
609       event->any.window = window;
610
611       /* If we are shown (not withdrawn) and get an unmap, it means we
612        * were iconified in the X sense. If we are withdrawn, and get
613        * an unmap, it means we hid the window ourselves, so we
614        * will have already flipped the iconified bit off.
615        */
616       if (window)
617         {
618           if (GDK_WINDOW_IS_MAPPED (window))
619             gdk_synthesize_window_state (window,
620                                          0,
621                                          GDK_WINDOW_STATE_ICONIFIED);
622
623           _gdk_x11_window_grab_check_unmap (window, xevent->xany.serial);
624         }
625
626       break;
627
628     case MapNotify:
629       GDK_NOTE (EVENTS,
630                 g_message ("map notify:\t\twindow: %ld",
631                            xevent->xmap.window));
632
633       event->any.type = GDK_MAP;
634       event->any.window = window;
635
636       /* Unset iconified if it was set */
637       if (window && (window->state & GDK_WINDOW_STATE_ICONIFIED))
638         gdk_synthesize_window_state (window,
639                                      GDK_WINDOW_STATE_ICONIFIED,
640                                      0);
641
642       break;
643
644     case ReparentNotify:
645       GDK_NOTE (EVENTS,
646                 g_message ("reparent notify:\twindow: %ld  x,y: %d %d  parent: %ld      ovr: %d",
647                            xevent->xreparent.window,
648                            xevent->xreparent.x,
649                            xevent->xreparent.y,
650                            xevent->xreparent.parent,
651                            xevent->xreparent.override_redirect));
652
653       /* Not currently handled */
654       return_val = FALSE;
655       break;
656
657     case ConfigureNotify:
658       GDK_NOTE (EVENTS,
659                 g_message ("configure notify:\twindow: %ld  x,y: %d %d  w,h: %d %d  b-w: %d  above: %ld  ovr: %d%s",
660                            xevent->xconfigure.window,
661                            xevent->xconfigure.x,
662                            xevent->xconfigure.y,
663                            xevent->xconfigure.width,
664                            xevent->xconfigure.height,
665                            xevent->xconfigure.border_width,
666                            xevent->xconfigure.above,
667                            xevent->xconfigure.override_redirect,
668                            !window
669                            ? " (discarding)"
670                            : window->window_type == GDK_WINDOW_CHILD
671                            ? " (discarding child)"
672                            : xevent->xconfigure.event != xevent->xconfigure.window
673                            ? " (discarding substructure)"
674                            : ""));
675       if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
676         {
677           window->width = xevent->xconfigure.width;
678           window->height = xevent->xconfigure.height;
679
680           _gdk_window_update_size (window);
681           _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
682           _gdk_x11_screen_size_changed (screen, xevent);
683         }
684
685 #ifdef HAVE_XSYNC
686       if (toplevel && display_x11->use_sync && !XSyncValueIsZero (toplevel->pending_counter_value))
687         {
688           toplevel->current_counter_value = toplevel->pending_counter_value;
689           XSyncIntToValue (&toplevel->pending_counter_value, 0);
690         }
691 #endif
692
693     if (!window ||
694           xevent->xconfigure.event != xevent->xconfigure.window ||
695           GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
696           GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
697         return_val = FALSE;
698       else
699         {
700           event->configure.type = GDK_CONFIGURE;
701           event->configure.window = window;
702           event->configure.width = xevent->xconfigure.width;
703           event->configure.height = xevent->xconfigure.height;
704
705           if (!xevent->xconfigure.send_event &&
706               !xevent->xconfigure.override_redirect &&
707               !GDK_WINDOW_DESTROYED (window))
708             {
709               gint tx = 0;
710               gint ty = 0;
711               Window child_window = 0;
712
713               gdk_x11_display_error_trap_push (display);
714               if (XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
715                                          GDK_WINDOW_XID (window),
716                                          x11_screen->xroot_window,
717                                          0, 0,
718                                          &tx, &ty,
719                                          &child_window))
720                 {
721                   event->configure.x = tx;
722                   event->configure.y = ty;
723                 }
724               gdk_x11_display_error_trap_pop_ignored (display);
725             }
726           else
727             {
728               event->configure.x = xevent->xconfigure.x;
729               event->configure.y = xevent->xconfigure.y;
730             }
731           window->x = event->configure.x;
732           window->y = event->configure.y;
733           window->width = xevent->xconfigure.width;
734           window->height = xevent->xconfigure.height;
735
736           _gdk_window_update_size (window);
737           _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
738
739           if (window->resize_count >= 1)
740             {
741               window->resize_count -= 1;
742
743               if (window->resize_count == 0)
744                 _gdk_x11_moveresize_configure_done (display, window);
745             }
746         }
747       break;
748
749     case PropertyNotify:
750       GDK_NOTE (EVENTS,
751                 g_message ("property notify:\twindow: %ld, atom(%ld): %s%s%s",
752                            xevent->xproperty.window,
753                            xevent->xproperty.atom,
754                            "\"",
755                            gdk_x11_get_xatom_name_for_display (display, xevent->xproperty.atom),
756                            "\""));
757
758       if (window == NULL)
759         {
760           return_val = FALSE;
761           break;
762         }
763
764       /* We compare with the serial of the last time we mapped the
765        * window to avoid refetching properties that we set ourselves
766        */
767       if (toplevel &&
768           xevent->xproperty.serial >= toplevel->map_serial)
769         {
770           if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"))
771             gdk_check_wm_state_changed (window);
772
773           if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"))
774             gdk_check_wm_desktop_changed (window);
775         }
776
777       if (window->event_mask & GDK_PROPERTY_CHANGE_MASK)
778         {
779           event->property.type = GDK_PROPERTY_NOTIFY;
780           event->property.window = window;
781           event->property.atom = gdk_x11_xatom_to_atom_for_display (display, xevent->xproperty.atom);
782           event->property.time = xevent->xproperty.time;
783           event->property.state = xevent->xproperty.state;
784         }
785       else
786         return_val = FALSE;
787
788       break;
789
790     case SelectionClear:
791       GDK_NOTE (EVENTS,
792                 g_message ("selection clear:\twindow: %ld",
793                            xevent->xproperty.window));
794
795       if (_gdk_x11_selection_filter_clear_event (&xevent->xselectionclear))
796         {
797           event->selection.type = GDK_SELECTION_CLEAR;
798           event->selection.window = window;
799           event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionclear.selection);
800           event->selection.time = xevent->xselectionclear.time;
801         }
802       else
803         return_val = FALSE;
804
805       break;
806
807     case SelectionRequest:
808       GDK_NOTE (EVENTS,
809                 g_message ("selection request:\twindow: %ld",
810                            xevent->xproperty.window));
811
812       event->selection.type = GDK_SELECTION_REQUEST;
813       event->selection.window = window;
814       event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.selection);
815       event->selection.target = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.target);
816       event->selection.property = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.property);
817       if (xevent->xselectionrequest.requestor != None)
818         event->selection.requestor = gdk_x11_window_foreign_new_for_display (display,
819                                                                              xevent->xselectionrequest.requestor);
820       else
821         event->selection.requestor = NULL;
822       event->selection.time = xevent->xselectionrequest.time;
823
824       break;
825
826     case SelectionNotify:
827       GDK_NOTE (EVENTS,
828                 g_message ("selection notify:\twindow: %ld",
829                            xevent->xproperty.window));
830
831       event->selection.type = GDK_SELECTION_NOTIFY;
832       event->selection.window = window;
833       event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.selection);
834       event->selection.target = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.target);
835       if (xevent->xselection.property == None)
836         event->selection.property = GDK_NONE;
837       else
838         event->selection.property = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.property);
839       event->selection.time = xevent->xselection.time;
840
841       break;
842
843     case ColormapNotify:
844       GDK_NOTE (EVENTS,
845                 g_message ("colormap notify:\twindow: %ld",
846                            xevent->xcolormap.window));
847
848       /* Not currently handled */
849       return_val = FALSE;
850       break;
851
852     case ClientMessage:
853       GDK_NOTE (EVENTS,
854                 g_message ("client message:\twindow: %ld",
855                            xevent->xclient.window));
856
857       /* Not currently handled */
858       return_val = FALSE;
859       break;
860
861     case MappingNotify:
862       GDK_NOTE (EVENTS,
863                 g_message ("mapping notify"));
864
865       /* Let XLib know that there is a new keyboard mapping.
866        */
867       XRefreshKeyboardMapping (&xevent->xmapping);
868       _gdk_x11_keymap_keys_changed (display);
869       return_val = FALSE;
870       break;
871
872     default:
873 #ifdef HAVE_XFIXES
874       if (xevent->type - display_x11->xfixes_event_base == XFixesSelectionNotify)
875         {
876           XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)xevent;
877
878           _gdk_x11_screen_process_owner_change (screen, xevent);
879           
880           event->owner_change.type = GDK_OWNER_CHANGE;
881           event->owner_change.window = window;
882           if (selection_notify->owner != None)
883             event->owner_change.owner = gdk_x11_window_foreign_new_for_display (display,
884                                                                                 selection_notify->owner);
885           else
886             event->owner_change.owner = NULL;
887           event->owner_change.reason = selection_notify->subtype;
888           event->owner_change.selection = 
889             gdk_x11_xatom_to_atom_for_display (display, 
890                                                selection_notify->selection);
891           event->owner_change.time = selection_notify->timestamp;
892           event->owner_change.selection_time = selection_notify->selection_timestamp;
893           
894           return_val = TRUE;
895         }
896       else
897 #endif
898 #ifdef HAVE_RANDR
899       if (xevent->type - display_x11->xrandr_event_base == RRScreenChangeNotify ||
900           xevent->type - display_x11->xrandr_event_base == RRNotify)
901         {
902           if (screen)
903             _gdk_x11_screen_size_changed (screen, xevent);
904         }
905       else
906 #endif
907 #if defined(HAVE_XCOMPOSITE) && defined (HAVE_XDAMAGE) && defined (HAVE_XFIXES)
908       if (display_x11->have_xdamage && window && window->composited &&
909           xevent->type == display_x11->xdamage_event_base + XDamageNotify &&
910           ((XDamageNotifyEvent *) xevent)->damage == window_impl->damage)
911         {
912           XDamageNotifyEvent *damage_event = (XDamageNotifyEvent *) xevent;
913           XserverRegion repair;
914           GdkRectangle rect;
915
916           rect.x = window->x + damage_event->area.x;
917           rect.y = window->y + damage_event->area.y;
918           rect.width = damage_event->area.width;
919           rect.height = damage_event->area.height;
920
921           repair = XFixesCreateRegion (display_x11->xdisplay,
922                                        &damage_event->area, 1);
923           XDamageSubtract (display_x11->xdisplay,
924                            window_impl->damage,
925                            repair, None);
926           XFixesDestroyRegion (display_x11->xdisplay, repair);
927
928           if (window->parent != NULL)
929            _gdk_x11_window_process_expose (window->parent,
930                                            damage_event->serial, &rect);
931
932           return_val = TRUE;
933         }
934       else
935 #endif
936 #ifdef HAVE_XKB
937       if (xevent->type == display_x11->xkb_event_type)
938         {
939           XkbEvent *xkb_event = (XkbEvent *) xevent;
940
941           switch (xkb_event->any.xkb_type)
942             {
943             case XkbNewKeyboardNotify:
944             case XkbMapNotify:
945               _gdk_x11_keymap_keys_changed (display);
946
947               return_val = FALSE;
948               break;
949
950             case XkbStateNotify:
951               _gdk_x11_keymap_state_changed (display, xevent);
952               break;
953             }
954         }
955       else
956 #endif
957         return_val = FALSE;
958     }
959
960  done:
961   if (return_val)
962     {
963       if (event->any.window)
964         g_object_ref (event->any.window);
965     }
966   else
967     {
968       /* Mark this event as having no resources to be freed */
969       event->any.window = NULL;
970       event->any.type = GDK_NOTHING;
971     }
972
973   if (window)
974     g_object_unref (window);
975
976   return return_val;
977 }
978
979 GdkFilterReturn
980 _gdk_wm_protocols_filter (GdkXEvent *xev,
981                           GdkEvent  *event,
982                           gpointer   data)
983 {
984   XEvent *xevent = (XEvent *)xev;
985   GdkWindow *win = event->any.window;
986   GdkDisplay *display;
987   Atom atom;
988
989   if (!GDK_IS_X11_WINDOW (win))
990     return GDK_FILTER_CONTINUE;
991
992   if (xevent->type != ClientMessage)
993     return GDK_FILTER_CONTINUE;
994
995   display = GDK_WINDOW_DISPLAY (win);
996
997   if (xevent->xclient.message_type != gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS"))
998     return GDK_FILTER_CONTINUE;
999
1000   atom = (Atom) xevent->xclient.data.l[0];
1001
1002   if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
1003     {
1004   /* The delete window request specifies a window
1005    *  to delete. We don't actually destroy the
1006    *  window because "it is only a request". (The
1007    *  window might contain vital data that the
1008    *  program does not want destroyed). Instead
1009    *  the event is passed along to the program,
1010    *  which should then destroy the window.
1011    */
1012       GDK_NOTE (EVENTS,
1013                 g_message ("delete window:\t\twindow: %ld",
1014                            xevent->xclient.window));
1015
1016       event->any.type = GDK_DELETE;
1017
1018       gdk_x11_window_set_user_time (win, xevent->xclient.data.l[1]);
1019
1020       return GDK_FILTER_TRANSLATE;
1021     }
1022   else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"))
1023     {
1024       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window);
1025
1026       /* There is no way of knowing reliably whether we are viewable;
1027        * _gdk_x11_set_input_focus_safe() traps errors asynchronously.
1028        */
1029       if (toplevel && win->accept_focus)
1030         _gdk_x11_set_input_focus_safe (display, toplevel->focus_window,
1031                                        RevertToParent,
1032                                        xevent->xclient.data.l[1]);
1033
1034       return GDK_FILTER_REMOVE;
1035     }
1036   else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING") &&
1037            !_gdk_x11_display_is_root_window (display,
1038                                              xevent->xclient.window))
1039     {
1040       XClientMessageEvent xclient = xevent->xclient;
1041
1042       xclient.window = GDK_WINDOW_XROOTWIN (win);
1043       XSendEvent (GDK_WINDOW_XDISPLAY (win),
1044                   xclient.window,
1045                   False,
1046                   SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xclient);
1047
1048       return GDK_FILTER_REMOVE;
1049     }
1050   else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST") &&
1051            GDK_X11_DISPLAY (display)->use_sync)
1052     {
1053       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window);
1054       if (toplevel)
1055         {
1056 #ifdef HAVE_XSYNC
1057           XSyncIntsToValue (&toplevel->pending_counter_value,
1058                             xevent->xclient.data.l[2],
1059                             xevent->xclient.data.l[3]);
1060 #endif
1061         }
1062       return GDK_FILTER_REMOVE;
1063     }
1064
1065   return GDK_FILTER_CONTINUE;
1066 }
1067
1068 static void
1069 gdk_event_init (GdkDisplay *display)
1070 {
1071   GdkX11Display *display_x11;
1072   GdkDeviceManager *device_manager;
1073
1074   display_x11 = GDK_X11_DISPLAY (display);
1075   display_x11->event_source = gdk_x11_event_source_new (display);
1076
1077   gdk_x11_event_source_add_translator ((GdkEventSource *) display_x11->event_source,
1078                                        GDK_EVENT_TRANSLATOR (display));
1079
1080   device_manager = gdk_display_get_device_manager (display);
1081   gdk_x11_event_source_add_translator ((GdkEventSource *) display_x11->event_source,
1082                                         GDK_EVENT_TRANSLATOR (device_manager));
1083 }
1084
1085 static void
1086 gdk_x11_display_init_input (GdkDisplay *display)
1087 {
1088   GdkX11Display *display_x11;
1089   GdkDeviceManager *device_manager;
1090   GdkDevice *device;
1091   GList *list, *l;
1092
1093   display_x11 = GDK_X11_DISPLAY (display);
1094   device_manager = gdk_display_get_device_manager (display);
1095
1096   /* For backwards compatibility, just add
1097    * floating devices that are not keyboards.
1098    */
1099   list = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING);
1100
1101   for (l = list; l; l = l->next)
1102     {
1103       device = l->data;
1104
1105       if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
1106         continue;
1107
1108       display_x11->input_devices = g_list_prepend (display_x11->input_devices,
1109                                                    g_object_ref (l->data));
1110     }
1111
1112   g_list_free (list);
1113
1114   /* Now set "core" pointer to the first
1115    * master device that is a pointer.
1116    */
1117   list = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
1118
1119   for (l = list; l; l = l->next)
1120     {
1121       device = l->data;
1122
1123       if (gdk_device_get_source (device) != GDK_SOURCE_MOUSE)
1124         continue;
1125
1126       display->core_pointer = device;
1127       break;
1128     }
1129
1130   /* Add the core pointer to the devices list */
1131   display_x11->input_devices = g_list_prepend (display_x11->input_devices,
1132                                                g_object_ref (display->core_pointer));
1133
1134   g_list_free (list);
1135 }
1136
1137 static void
1138 set_sm_client_id (GdkDisplay  *display,
1139                   const gchar *sm_client_id)
1140 {
1141   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
1142
1143   if (gdk_display_is_closed (display))
1144     return;
1145
1146   if (sm_client_id && strcmp (sm_client_id, ""))
1147     XChangeProperty (display_x11->xdisplay, display_x11->leader_window,
1148                      gdk_x11_get_xatom_by_name_for_display (display, "SM_CLIENT_ID"),
1149                      XA_STRING, 8, PropModeReplace, (guchar *)sm_client_id,
1150                      strlen (sm_client_id));
1151   else
1152     XDeleteProperty (display_x11->xdisplay, display_x11->leader_window,
1153                      gdk_x11_get_xatom_by_name_for_display (display, "SM_CLIENT_ID"));
1154 }
1155
1156 GdkDisplay *
1157 _gdk_x11_display_open (const gchar *display_name)
1158 {
1159   Display *xdisplay;
1160   GdkDisplay *display;
1161   GdkX11Display *display_x11;
1162   GdkWindowAttr attr;
1163   gint argc;
1164   gchar *argv[1];
1165
1166   XClassHint *class_hint;
1167   gulong pid;
1168   gint i;
1169   gint ignore;
1170   gint maj, min;
1171
1172   xdisplay = XOpenDisplay (display_name);
1173   if (!xdisplay)
1174     return NULL;
1175   
1176   display = g_object_new (GDK_TYPE_X11_DISPLAY, NULL);
1177   display_x11 = GDK_X11_DISPLAY (display);
1178
1179   display_x11->xdisplay = xdisplay;
1180
1181 #ifdef HAVE_X11R6  
1182   /* Set up handlers for Xlib internal connections */
1183   XAddConnectionWatch (xdisplay, gdk_internal_connection_watch, NULL);
1184 #endif /* HAVE_X11R6 */
1185   
1186   _gdk_x11_precache_atoms (display, precache_atoms, G_N_ELEMENTS (precache_atoms));
1187
1188   /* RandR must be initialized before we initialize the screens */
1189   display_x11->have_randr12 = FALSE;
1190   display_x11->have_randr13 = FALSE;
1191 #ifdef HAVE_RANDR
1192   if (XRRQueryExtension (display_x11->xdisplay,
1193                          &display_x11->xrandr_event_base, &ignore))
1194   {
1195       int major, minor;
1196
1197       XRRQueryVersion (display_x11->xdisplay, &major, &minor);
1198
1199       if ((major == 1 && minor >= 2) || major > 1) {
1200           display_x11->have_randr12 = TRUE;
1201           if (minor >= 3 || major > 1)
1202               display_x11->have_randr13 = TRUE;
1203       }
1204
1205        gdk_x11_register_standard_event_type (display, display_x11->xrandr_event_base, RRNumberEvents);
1206   }
1207 #endif
1208
1209   /* initialize the display's screens */ 
1210   display_x11->screens = g_new (GdkScreen *, ScreenCount (display_x11->xdisplay));
1211   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
1212     display_x11->screens[i] = _gdk_x11_screen_new (display, i);
1213
1214   /* We need to initialize events after we have the screen
1215    * structures in places
1216    */
1217   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
1218     _gdk_x11_screen_init_events (display_x11->screens[i]);
1219
1220   /*set the default screen */
1221   display_x11->default_screen = display_x11->screens[DefaultScreen (display_x11->xdisplay)];
1222
1223   display->device_manager = _gdk_x11_device_manager_new (display);
1224
1225   gdk_event_init (display);
1226
1227   attr.window_type = GDK_WINDOW_TOPLEVEL;
1228   attr.wclass = GDK_INPUT_OUTPUT;
1229   attr.x = 10;
1230   attr.y = 10;
1231   attr.width = 10;
1232   attr.height = 10;
1233   attr.event_mask = 0;
1234
1235   display_x11->leader_gdk_window = gdk_window_new (GDK_X11_SCREEN (display_x11->default_screen)->root_window, 
1236                                                    &attr, GDK_WA_X | GDK_WA_Y);
1237   (_gdk_x11_window_get_toplevel (display_x11->leader_gdk_window))->is_leader = TRUE;
1238
1239   display_x11->leader_window = GDK_WINDOW_XID (display_x11->leader_gdk_window);
1240
1241   display_x11->leader_window_title_set = FALSE;
1242
1243 #ifdef HAVE_XFIXES
1244   if (XFixesQueryExtension (display_x11->xdisplay, 
1245                             &display_x11->xfixes_event_base, 
1246                             &ignore))
1247     {
1248       display_x11->have_xfixes = TRUE;
1249
1250       gdk_x11_register_standard_event_type (display,
1251                                             display_x11->xfixes_event_base, 
1252                                             XFixesNumberEvents);
1253     }
1254   else
1255 #endif
1256     display_x11->have_xfixes = FALSE;
1257
1258 #ifdef HAVE_XCOMPOSITE
1259   if (XCompositeQueryExtension (display_x11->xdisplay,
1260                                 &ignore, &ignore))
1261     {
1262       int major, minor;
1263
1264       XCompositeQueryVersion (display_x11->xdisplay, &major, &minor);
1265
1266       /* Prior to Composite version 0.4, composited windows clipped their
1267        * parents, so you had to use IncludeInferiors to draw to the parent
1268        * This isn't useful for our purposes, so require 0.4
1269        */
1270       display_x11->have_xcomposite = major > 0 || (major == 0 && minor >= 4);
1271     }
1272   else
1273 #endif
1274     display_x11->have_xcomposite = FALSE;
1275
1276 #ifdef HAVE_XDAMAGE
1277   if (XDamageQueryExtension (display_x11->xdisplay,
1278                              &display_x11->xdamage_event_base,
1279                              &ignore))
1280     {
1281       display_x11->have_xdamage = TRUE;
1282
1283       gdk_x11_register_standard_event_type (display,
1284                                             display_x11->xdamage_event_base,
1285                                             XDamageNumberEvents);
1286     }
1287   else
1288 #endif
1289     display_x11->have_xdamage = FALSE;
1290
1291   display_x11->have_shapes = FALSE;
1292   display_x11->have_input_shapes = FALSE;
1293
1294   if (XShapeQueryExtension (GDK_DISPLAY_XDISPLAY (display), &display_x11->shape_event_base, &ignore))
1295     {
1296       display_x11->have_shapes = TRUE;
1297 #ifdef ShapeInput
1298       if (XShapeQueryVersion (GDK_DISPLAY_XDISPLAY (display), &maj, &min))
1299         display_x11->have_input_shapes = (maj == 1 && min >= 1);
1300 #endif
1301     }
1302
1303   display_x11->trusted_client = TRUE;
1304   {
1305     Window root, child;
1306     int rootx, rooty, winx, winy;
1307     unsigned int xmask;
1308
1309     gdk_x11_display_error_trap_push (display);
1310     XQueryPointer (display_x11->xdisplay,
1311                    GDK_X11_SCREEN (display_x11->default_screen)->xroot_window,
1312                    &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
1313     if (G_UNLIKELY (gdk_x11_display_error_trap_pop (display) == BadWindow))
1314       {
1315         g_warning ("Connection to display %s appears to be untrusted. Pointer and keyboard grabs and inter-client communication may not work as expected.", gdk_display_get_name (display));
1316         display_x11->trusted_client = FALSE;
1317       }
1318   }
1319
1320   if (g_getenv ("GDK_SYNCHRONIZE"))
1321     XSynchronize (display_x11->xdisplay, True);
1322
1323   class_hint = XAllocClassHint();
1324   class_hint->res_name = g_get_prgname ();
1325
1326   class_hint->res_class = (char *)gdk_get_program_class ();
1327
1328   /* XmbSetWMProperties sets the RESOURCE_NAME environment variable
1329    * from argv[0], so we just synthesize an argument array here.
1330    */
1331   argc = 1;
1332   argv[0] = g_get_prgname ();
1333
1334   XmbSetWMProperties (display_x11->xdisplay,
1335                       display_x11->leader_window,
1336                       NULL, NULL, argv, argc, NULL, NULL,
1337                       class_hint);
1338   XFree (class_hint);
1339
1340   if (gdk_sm_client_id)
1341     set_sm_client_id (display, gdk_sm_client_id);
1342
1343   pid = getpid ();
1344   XChangeProperty (display_x11->xdisplay,
1345                    display_x11->leader_window,
1346                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"),
1347                    XA_CARDINAL, 32, PropModeReplace, (guchar *) & pid, 1);
1348
1349   /* We don't yet know a valid time. */
1350   display_x11->user_time = 0;
1351   
1352 #ifdef HAVE_XKB
1353   {
1354     gint xkb_major = XkbMajorVersion;
1355     gint xkb_minor = XkbMinorVersion;
1356     if (XkbLibraryVersion (&xkb_major, &xkb_minor))
1357       {
1358         xkb_major = XkbMajorVersion;
1359         xkb_minor = XkbMinorVersion;
1360             
1361         if (XkbQueryExtension (display_x11->xdisplay, 
1362                                NULL, &display_x11->xkb_event_type, NULL,
1363                                &xkb_major, &xkb_minor))
1364           {
1365             Bool detectable_autorepeat_supported;
1366             
1367             display_x11->use_xkb = TRUE;
1368
1369             XkbSelectEvents (display_x11->xdisplay,
1370                              XkbUseCoreKbd,
1371                              XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask,
1372                              XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask);
1373
1374             /* keep this in sync with _gdk_x11_keymap_state_changed() */
1375             XkbSelectEventDetails (display_x11->xdisplay,
1376                                    XkbUseCoreKbd, XkbStateNotify,
1377                                    XkbAllStateComponentsMask,
1378                                    XkbGroupLockMask|XkbModifierLockMask);
1379
1380             XkbSetDetectableAutoRepeat (display_x11->xdisplay,
1381                                         True,
1382                                         &detectable_autorepeat_supported);
1383
1384             GDK_NOTE (MISC, g_message ("Detectable autorepeat %s.",
1385                                        detectable_autorepeat_supported ?
1386                                        "supported" : "not supported"));
1387             
1388             display_x11->have_xkb_autorepeat = detectable_autorepeat_supported;
1389           }
1390       }
1391   }
1392 #endif
1393
1394   display_x11->use_sync = FALSE;
1395 #ifdef HAVE_XSYNC
1396   {
1397     int major, minor;
1398     int error_base, event_base;
1399     
1400     if (XSyncQueryExtension (display_x11->xdisplay,
1401                              &event_base, &error_base) &&
1402         XSyncInitialize (display_x11->xdisplay,
1403                          &major, &minor))
1404       display_x11->use_sync = TRUE;
1405   }
1406 #endif
1407
1408   gdk_x11_display_init_input (display);
1409
1410   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
1411     _gdk_x11_screen_setup (display_x11->screens[i]);
1412
1413   g_signal_emit_by_name (display, "opened");
1414   g_signal_emit_by_name (gdk_display_manager_get (), "display-opened", display);
1415
1416   return display;
1417 }
1418
1419 #ifdef HAVE_X11R6
1420 /*
1421  * XLib internal connection handling
1422  */
1423 typedef struct _GdkInternalConnection GdkInternalConnection;
1424
1425 struct _GdkInternalConnection
1426 {
1427   gint           fd;
1428   GSource       *source;
1429   Display       *display;
1430 };
1431
1432 static gboolean
1433 process_internal_connection (GIOChannel  *gioc,
1434                              GIOCondition cond,
1435                              gpointer     data)
1436 {
1437   GdkInternalConnection *connection = (GdkInternalConnection *)data;
1438
1439   GDK_THREADS_ENTER ();
1440
1441   XProcessInternalConnection ((Display*)connection->display, connection->fd);
1442
1443   GDK_THREADS_LEAVE ();
1444
1445   return TRUE;
1446 }
1447
1448 static gulong
1449 gdk_x11_display_get_next_serial (GdkDisplay *display)
1450 {
1451   return NextRequest (GDK_DISPLAY_XDISPLAY (display));
1452 }
1453
1454
1455 static GdkInternalConnection *
1456 gdk_add_connection_handler (Display *display,
1457                             guint    fd)
1458 {
1459   GIOChannel *io_channel;
1460   GdkInternalConnection *connection;
1461
1462   connection = g_new (GdkInternalConnection, 1);
1463
1464   connection->fd = fd;
1465   connection->display = display;
1466   
1467   io_channel = g_io_channel_unix_new (fd);
1468   
1469   connection->source = g_io_create_watch (io_channel, G_IO_IN);
1470   g_source_set_callback (connection->source,
1471                          (GSourceFunc)process_internal_connection, connection, NULL);
1472   g_source_attach (connection->source, NULL);
1473   
1474   g_io_channel_unref (io_channel);
1475   
1476   return connection;
1477 }
1478
1479 static void
1480 gdk_remove_connection_handler (GdkInternalConnection *connection)
1481 {
1482   g_source_destroy (connection->source);
1483   g_free (connection);
1484 }
1485
1486 static void
1487 gdk_internal_connection_watch (Display  *display,
1488                                XPointer  arg,
1489                                gint      fd,
1490                                gboolean  opening,
1491                                XPointer *watch_data)
1492 {
1493   if (opening)
1494     *watch_data = (XPointer)gdk_add_connection_handler (display, fd);
1495   else
1496     gdk_remove_connection_handler ((GdkInternalConnection *)*watch_data);
1497 }
1498 #endif /* HAVE_X11R6 */
1499
1500 static G_CONST_RETURN gchar *
1501 gdk_x11_display_get_name (GdkDisplay *display)
1502 {
1503   return (gchar *) DisplayString (GDK_X11_DISPLAY (display)->xdisplay);
1504 }
1505
1506 static gint
1507 gdk_x11_display_get_n_screens (GdkDisplay *display)
1508 {
1509   return ScreenCount (GDK_X11_DISPLAY (display)->xdisplay);
1510 }
1511
1512 static GdkScreen *
1513 gdk_x11_display_get_screen (GdkDisplay *display,
1514                             gint        screen_num)
1515 {
1516   g_return_val_if_fail (ScreenCount (GDK_X11_DISPLAY (display)->xdisplay) > screen_num, NULL);
1517
1518   return GDK_X11_DISPLAY (display)->screens[screen_num];
1519 }
1520
1521 static GdkScreen *
1522 gdk_x11_display_get_default_screen (GdkDisplay *display)
1523 {
1524   return GDK_X11_DISPLAY (display)->default_screen;
1525 }
1526
1527 gboolean
1528 _gdk_x11_display_is_root_window (GdkDisplay *display,
1529                                  Window      xroot_window)
1530 {
1531   GdkX11Display *display_x11;
1532   gint i;
1533
1534   display_x11 = GDK_X11_DISPLAY (display);
1535
1536   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
1537     {
1538       if (GDK_SCREEN_XROOTWIN (display_x11->screens[i]) == xroot_window)
1539         return TRUE;
1540     }
1541   return FALSE;
1542 }
1543
1544 struct XPointerUngrabInfo {
1545   GdkDisplay *display;
1546   guint32 time;
1547 };
1548
1549 static void
1550 device_grab_update_callback (GdkDisplay *display,
1551                              gpointer    data,
1552                              gulong      serial)
1553 {
1554   GdkDevice *device = data;
1555
1556   _gdk_display_device_grab_update (display, device, NULL, serial);
1557 }
1558
1559 #define XSERVER_TIME_IS_LATER(time1, time2)                        \
1560   ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
1561     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
1562   )
1563
1564 void
1565 _gdk_x11_display_update_grab_info (GdkDisplay *display,
1566                                    GdkDevice  *device,
1567                                    gint        status)
1568 {
1569   if (status == GrabSuccess)
1570     _gdk_x11_roundtrip_async (display, device_grab_update_callback, device);
1571 }
1572
1573 void
1574 _gdk_x11_display_update_grab_info_ungrab (GdkDisplay *display,
1575                                           GdkDevice  *device,
1576                                           guint32     time,
1577                                           gulong      serial)
1578 {
1579   GdkDeviceGrabInfo *grab;
1580
1581   XFlush (GDK_DISPLAY_XDISPLAY (display));
1582
1583   grab = _gdk_display_get_last_device_grab (display, device);
1584   if (grab &&
1585       (time == GDK_CURRENT_TIME ||
1586        grab->time == GDK_CURRENT_TIME ||
1587        !XSERVER_TIME_IS_LATER (grab->time, time)))
1588     {
1589       grab->serial_end = serial;
1590       _gdk_x11_roundtrip_async (display, device_grab_update_callback, device);
1591     }
1592 }
1593
1594 static void
1595 gdk_x11_display_beep (GdkDisplay *display)
1596 {
1597 #ifdef HAVE_XKB
1598   XkbBell (GDK_DISPLAY_XDISPLAY (display), None, 0, None);
1599 #else
1600   XBell (GDK_DISPLAY_XDISPLAY (display), 0);
1601 #endif
1602 }
1603
1604 static void
1605 gdk_x11_display_sync (GdkDisplay *display)
1606 {
1607   XSync (GDK_DISPLAY_XDISPLAY (display), False);
1608 }
1609
1610 static void
1611 gdk_x11_display_flush (GdkDisplay *display)
1612 {
1613   if (!display->closed)
1614     XFlush (GDK_DISPLAY_XDISPLAY (display));
1615 }
1616
1617 static gboolean
1618 gdk_x11_display_has_pending (GdkDisplay *display)
1619 {
1620   return XPending (GDK_DISPLAY_XDISPLAY (display));
1621 }
1622
1623 static GdkWindow *
1624 gdk_x11_display_get_default_group (GdkDisplay *display)
1625 {
1626   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1627
1628   return GDK_X11_DISPLAY (display)->leader_gdk_window;
1629 }
1630
1631 /**
1632  * gdk_x11_display_grab:
1633  * @display: a #GdkDisplay 
1634  * 
1635  * Call XGrabServer() on @display. 
1636  * To ungrab the display again, use gdk_x11_display_ungrab(). 
1637  *
1638  * gdk_x11_display_grab()/gdk_x11_display_ungrab() calls can be nested.
1639  *
1640  * Since: 2.2
1641  **/
1642 void
1643 gdk_x11_display_grab (GdkDisplay *display)
1644 {
1645   GdkX11Display *display_x11;
1646   
1647   g_return_if_fail (GDK_IS_DISPLAY (display));
1648   
1649   display_x11 = GDK_X11_DISPLAY (display);
1650   
1651   if (display_x11->grab_count == 0)
1652     XGrabServer (display_x11->xdisplay);
1653   display_x11->grab_count++;
1654 }
1655
1656 /**
1657  * gdk_x11_display_ungrab:
1658  * @display: a #GdkDisplay
1659  * 
1660  * Ungrab @display after it has been grabbed with 
1661  * gdk_x11_display_grab(). 
1662  *
1663  * Since: 2.2
1664  **/
1665 void
1666 gdk_x11_display_ungrab (GdkDisplay *display)
1667 {
1668   GdkX11Display *display_x11;
1669   
1670   g_return_if_fail (GDK_IS_DISPLAY (display));
1671   
1672   display_x11 = GDK_X11_DISPLAY (display);;
1673   g_return_if_fail (display_x11->grab_count > 0);
1674   
1675   display_x11->grab_count--;
1676   if (display_x11->grab_count == 0)
1677     {
1678       XUngrabServer (display_x11->xdisplay);
1679       XFlush (display_x11->xdisplay);
1680     }
1681 }
1682
1683 static void
1684 gdk_x11_display_dispose (GObject *object)
1685 {
1686   GdkDisplay *display = GDK_DISPLAY (object);
1687   GdkX11Display *display_x11 = GDK_X11_DISPLAY (object);
1688   gint           i;
1689
1690   _gdk_x11_display_manager_remove_display (gdk_display_manager_get (), display);
1691
1692   g_list_foreach (display_x11->input_devices, (GFunc) g_object_run_dispose, NULL);
1693
1694   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
1695     _gdk_screen_close (display_x11->screens[i]);
1696
1697   if (display_x11->event_source)
1698     {
1699       g_source_destroy (display_x11->event_source);
1700       g_source_unref (display_x11->event_source);
1701       display_x11->event_source = NULL;
1702     }
1703
1704   G_OBJECT_CLASS (gdk_x11_display_parent_class)->dispose (object);
1705 }
1706
1707 static void
1708 gdk_x11_display_finalize (GObject *object)
1709 {
1710   GdkX11Display *display_x11 = GDK_X11_DISPLAY (object);
1711   gint           i;
1712
1713   /* Keymap */
1714   if (display_x11->keymap)
1715     g_object_unref (display_x11->keymap);
1716
1717   /* Free motif Dnd */
1718   if (display_x11->motif_target_lists)
1719     {
1720       for (i = 0; i < display_x11->motif_n_target_lists; i++)
1721         g_list_free (display_x11->motif_target_lists[i]);
1722       g_free (display_x11->motif_target_lists);
1723     }
1724
1725   _gdk_x11_cursor_display_finalize (GDK_DISPLAY (display_x11));
1726
1727   /* Atom Hashtable */
1728   g_hash_table_destroy (display_x11->atom_from_virtual);
1729   g_hash_table_destroy (display_x11->atom_to_virtual);
1730
1731   /* Leader Window */
1732   XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);
1733
1734   /* List of event window extraction functions */
1735   g_slist_foreach (display_x11->event_types, (GFunc)g_free, NULL);
1736   g_slist_free (display_x11->event_types);
1737
1738   /* input GdkDevice list */
1739   g_list_foreach (display_x11->input_devices, (GFunc) g_object_unref, NULL);
1740   g_list_free (display_x11->input_devices);
1741
1742   /* input GdkWindow list */
1743   g_list_foreach (display_x11->input_windows, (GFunc) g_free, NULL);
1744   g_list_free (display_x11->input_windows);
1745
1746   /* Free all GdkScreens */
1747   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
1748     g_object_unref (display_x11->screens[i]);
1749   g_free (display_x11->screens);
1750
1751   g_free (display_x11->startup_notification_id);
1752
1753   /* X ID hashtable */
1754   g_hash_table_destroy (display_x11->xid_ht);
1755
1756   XCloseDisplay (display_x11->xdisplay);
1757
1758   /* error traps */
1759   while (display_x11->error_traps != NULL)
1760     {
1761       GdkErrorTrap *trap = display_x11->error_traps->data;
1762
1763       display_x11->error_traps =
1764         g_slist_delete_link (display_x11->error_traps,
1765                              display_x11->error_traps);
1766
1767       if (trap->end_sequence == 0)
1768         g_warning ("Display finalized with an unpopped error trap");
1769
1770       g_slice_free (GdkErrorTrap, trap);
1771     }
1772
1773   G_OBJECT_CLASS (gdk_x11_display_parent_class)->finalize (object);
1774 }
1775
1776 /**
1777  * gdk_x11_lookup_xdisplay:
1778  * @xdisplay: a pointer to an X Display
1779  * 
1780  * Find the #GdkDisplay corresponding to @display, if any exists.
1781  * 
1782  * Return value: (transfer none): the #GdkDisplay, if found, otherwise %NULL.
1783  *
1784  * Since: 2.2
1785  **/
1786 GdkDisplay *
1787 gdk_x11_lookup_xdisplay (Display *xdisplay)
1788 {
1789   GSList *list, *l;
1790   GdkDisplay *display;
1791
1792   display = NULL;
1793
1794   list = gdk_display_manager_list_displays (gdk_display_manager_get ());
1795
1796   for (l = list; l; l = l->next)
1797     {
1798       if (GDK_DISPLAY_XDISPLAY (l->data) == xdisplay)
1799         {
1800           display = l->data;
1801           break;
1802         }
1803     }
1804
1805   g_slist_free (list);
1806
1807   return display;
1808 }
1809
1810 /**
1811  * _gdk_x11_display_screen_for_xrootwin:
1812  * @display: a #GdkDisplay
1813  * @xrootwin: window ID for one of of the screen's of the display.
1814  * 
1815  * Given the root window ID of one of the screen's of a #GdkDisplay,
1816  * finds the screen.
1817  * 
1818  * Return value: (transfer none): the #GdkScreen corresponding to
1819  *     @xrootwin, or %NULL.
1820  **/
1821 GdkScreen *
1822 _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
1823                                       Window      xrootwin)
1824 {
1825   gint i;
1826
1827   for (i = 0; i < ScreenCount (GDK_X11_DISPLAY (display)->xdisplay); i++)
1828     {
1829       GdkScreen *screen = gdk_display_get_screen (display, i);
1830       if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
1831         return screen;
1832     }
1833
1834   return NULL;
1835 }
1836
1837 /**
1838  * gdk_x11_display_get_xdisplay: (skip)
1839  * @display: a #GdkDisplay
1840  * @returns: an X display.
1841  *
1842  * Returns the X display of a #GdkDisplay.
1843  *
1844  * Since: 2.2
1845  */
1846 Display *
1847 gdk_x11_display_get_xdisplay (GdkDisplay *display)
1848 {
1849   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1850   return GDK_X11_DISPLAY (display)->xdisplay;
1851 }
1852
1853 void
1854 _gdk_x11_display_make_default (GdkDisplay *display)
1855 {
1856   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
1857   const gchar *startup_id;
1858
1859   g_free (display_x11->startup_notification_id);
1860   display_x11->startup_notification_id = NULL;
1861
1862   startup_id = g_getenv ("DESKTOP_STARTUP_ID");
1863   if (startup_id && *startup_id != '\0')
1864     {
1865       if (!g_utf8_validate (startup_id, -1, NULL))
1866         g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
1867       else
1868         gdk_x11_display_set_startup_notification_id (display, startup_id);
1869
1870       /* Clear the environment variable so it won't be inherited by
1871        * child processes and confuse things.
1872        */
1873       g_unsetenv ("DESKTOP_STARTUP_ID");
1874     }
1875 }
1876
1877 static void
1878 broadcast_xmessage (GdkDisplay *display,
1879                     const char *message_type,
1880                     const char *message_type_begin,
1881                     const char *message)
1882 {
1883   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1884   GdkScreen *screen = gdk_display_get_default_screen (display);
1885   GdkWindow *root_window = gdk_screen_get_root_window (screen);
1886   Window xroot_window = GDK_WINDOW_XID (root_window);
1887   
1888   Atom type_atom;
1889   Atom type_atom_begin;
1890   Window xwindow;
1891
1892   if (!G_LIKELY (GDK_X11_DISPLAY (display)->trusted_client))
1893     return;
1894
1895   {
1896     XSetWindowAttributes attrs;
1897
1898     attrs.override_redirect = True;
1899     attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
1900
1901     xwindow =
1902       XCreateWindow (xdisplay,
1903                      xroot_window,
1904                      -100, -100, 1, 1,
1905                      0,
1906                      CopyFromParent,
1907                      CopyFromParent,
1908                      (Visual *)CopyFromParent,
1909                      CWOverrideRedirect | CWEventMask,
1910                      &attrs);
1911   }
1912
1913   type_atom = gdk_x11_get_xatom_by_name_for_display (display,
1914                                                      message_type);
1915   type_atom_begin = gdk_x11_get_xatom_by_name_for_display (display,
1916                                                            message_type_begin);
1917   
1918   {
1919     XClientMessageEvent xclient;
1920     const char *src;
1921     const char *src_end;
1922     char *dest;
1923     char *dest_end;
1924     
1925                 memset(&xclient, 0, sizeof (xclient));
1926     xclient.type = ClientMessage;
1927     xclient.message_type = type_atom_begin;
1928     xclient.display =xdisplay;
1929     xclient.window = xwindow;
1930     xclient.format = 8;
1931
1932     src = message;
1933     src_end = message + strlen (message) + 1; /* +1 to include nul byte */
1934     
1935     while (src != src_end)
1936       {
1937         dest = &xclient.data.b[0];
1938         dest_end = dest + 20;        
1939         
1940         while (dest != dest_end &&
1941                src != src_end)
1942           {
1943             *dest = *src;
1944             ++dest;
1945             ++src;
1946           }
1947
1948         while (dest != dest_end)
1949           {
1950             *dest = 0;
1951             ++dest;
1952           }
1953         
1954         XSendEvent (xdisplay,
1955                     xroot_window,
1956                     False,
1957                     PropertyChangeMask,
1958                     (XEvent *)&xclient);
1959
1960         xclient.message_type = type_atom;
1961       }
1962   }
1963
1964   XDestroyWindow (xdisplay, xwindow);
1965   XFlush (xdisplay);
1966 }
1967
1968 /**
1969  * gdk_x11_display_broadcast_startup_message:
1970  * @display: a #GdkDisplay
1971  * @message_type: startup notification message type ("new", "change",
1972  * or "remove")
1973  * @...: a list of key/value pairs (as strings), terminated by a
1974  * %NULL key. (A %NULL value for a key will cause that key to be
1975  * skipped in the output.)
1976  *
1977  * Sends a startup notification message of type @message_type to
1978  * @display. 
1979  *
1980  * This is a convenience function for use by code that implements the
1981  * freedesktop startup notification specification. Applications should
1982  * not normally need to call it directly. See the <ulink
1983  * url="http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt">Startup
1984  * Notification Protocol specification</ulink> for
1985  * definitions of the message types and keys that can be used.
1986  *
1987  * Since: 2.12
1988  **/
1989 void
1990 gdk_x11_display_broadcast_startup_message (GdkDisplay *display,
1991                                            const char *message_type,
1992                                            ...)
1993 {
1994   GString *message;
1995   va_list ap;
1996   const char *key, *value, *p;
1997
1998   message = g_string_new (message_type);
1999   g_string_append_c (message, ':');
2000
2001   va_start (ap, message_type);
2002   while ((key = va_arg (ap, const char *)))
2003     {
2004       value = va_arg (ap, const char *);
2005       if (!value)
2006         continue;
2007
2008       g_string_append_printf (message, " %s=\"", key);
2009       for (p = value; *p; p++)
2010         {
2011           switch (*p)
2012             {
2013             case ' ':
2014             case '"':
2015             case '\\':
2016               g_string_append_c (message, '\\');
2017               break;
2018             }
2019
2020           g_string_append_c (message, *p);
2021         }
2022       g_string_append_c (message, '\"');
2023     }
2024   va_end (ap);
2025
2026   broadcast_xmessage (display,
2027                       "_NET_STARTUP_INFO",
2028                       "_NET_STARTUP_INFO_BEGIN",
2029                       message->str);
2030
2031   g_string_free (message, TRUE);
2032 }
2033
2034 static void
2035 gdk_x11_display_notify_startup_complete (GdkDisplay  *display,
2036                                          const gchar *startup_id)
2037 {
2038   if (startup_id == NULL)
2039     {
2040       startup_id = GDK_X11_DISPLAY (display)->startup_notification_id;
2041       if (startup_id == NULL)
2042         return;
2043     }
2044
2045   gdk_x11_display_broadcast_startup_message (display, "remove",
2046                                              "ID", startup_id,
2047                                              NULL);
2048 }
2049
2050 static gboolean
2051 gdk_x11_display_supports_selection_notification (GdkDisplay *display)
2052 {
2053   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
2054
2055   return display_x11->have_xfixes;
2056 }
2057
2058 static gboolean
2059 gdk_x11_display_request_selection_notification (GdkDisplay *display,
2060                                                 GdkAtom     selection)
2061
2062 {
2063 #ifdef HAVE_XFIXES
2064   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
2065   Atom atom;
2066
2067   if (display_x11->have_xfixes)
2068     {
2069       atom = gdk_x11_atom_to_xatom_for_display (display, 
2070                                                 selection);
2071       XFixesSelectSelectionInput (display_x11->xdisplay, 
2072                                   display_x11->leader_window,
2073                                   atom,
2074                                   XFixesSetSelectionOwnerNotifyMask |
2075                                   XFixesSelectionWindowDestroyNotifyMask |
2076                                   XFixesSelectionClientCloseNotifyMask);
2077       return TRUE;
2078     }
2079   else
2080 #endif
2081     return FALSE;
2082 }
2083
2084 static gboolean
2085 gdk_x11_display_supports_clipboard_persistence (GdkDisplay *display)
2086 {
2087   Atom clipboard_manager;
2088
2089   /* It might make sense to cache this */
2090   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
2091   return XGetSelectionOwner (GDK_X11_DISPLAY (display)->xdisplay, clipboard_manager) != None;
2092 }
2093
2094 static void
2095 gdk_x11_display_store_clipboard (GdkDisplay    *display,
2096                                  GdkWindow     *clipboard_window,
2097                                  guint32        time_,
2098                                  const GdkAtom *targets,
2099                                  gint           n_targets)
2100 {
2101   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
2102   Atom clipboard_manager, save_targets;
2103
2104   g_return_if_fail (GDK_WINDOW_IS_X11 (clipboard_window));
2105
2106   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
2107   save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
2108
2109   gdk_x11_display_error_trap_push (display);
2110
2111   if (XGetSelectionOwner (display_x11->xdisplay, clipboard_manager) != None)
2112     {
2113       Atom property_name = None;
2114       Atom *xatoms;
2115       int i;
2116
2117       if (n_targets > 0)
2118         {
2119           property_name = gdk_x11_get_xatom_by_name_for_display (display, "GDK_SELECTION");
2120
2121           xatoms = g_new (Atom, n_targets);
2122           for (i = 0; i < n_targets; i++)
2123             xatoms[i] = gdk_x11_atom_to_xatom_for_display (display, targets[i]);
2124
2125           XChangeProperty (display_x11->xdisplay, GDK_WINDOW_XID (clipboard_window),
2126                            property_name, XA_ATOM,
2127                            32, PropModeReplace, (guchar *)xatoms, n_targets);
2128           g_free (xatoms);
2129
2130         }
2131
2132       XConvertSelection (display_x11->xdisplay,
2133                          clipboard_manager, save_targets, property_name,
2134                          GDK_WINDOW_XID (clipboard_window), time_);
2135
2136     }
2137   gdk_x11_display_error_trap_pop_ignored (display);
2138
2139 }
2140
2141 /**
2142  * gdk_x11_display_get_user_time:
2143  * @display: a #GdkDisplay
2144  *
2145  * Returns the timestamp of the last user interaction on 
2146  * @display. The timestamp is taken from events caused
2147  * by user interaction such as key presses or pointer 
2148  * movements. See gdk_x11_window_set_user_time().
2149  *
2150  * Returns: the timestamp of the last user interaction 
2151  *
2152  * Since: 2.8
2153  */
2154 guint32
2155 gdk_x11_display_get_user_time (GdkDisplay *display)
2156 {
2157   return GDK_X11_DISPLAY (display)->user_time;
2158 }
2159
2160 static gboolean
2161 gdk_x11_display_supports_shapes (GdkDisplay *display)
2162 {
2163   return GDK_X11_DISPLAY (display)->have_shapes;
2164 }
2165
2166 static gboolean
2167 gdk_x11_display_supports_input_shapes (GdkDisplay *display)
2168 {
2169   return GDK_X11_DISPLAY (display)->have_input_shapes;
2170 }
2171
2172
2173 /**
2174  * gdk_x11_display_get_startup_notification_id:
2175  * @display: a #GdkDisplay
2176  *
2177  * Gets the startup notification ID for a display.
2178  * 
2179  * Returns: the startup notification ID for @display
2180  *
2181  * Since: 2.12
2182  */
2183 G_CONST_RETURN gchar *
2184 gdk_x11_display_get_startup_notification_id (GdkDisplay *display)
2185 {
2186   return GDK_X11_DISPLAY (display)->startup_notification_id;
2187 }
2188
2189 /**
2190  * gdk_x11_display_set_startup_notification_id:
2191  * @display: a #GdkDisplay
2192  * @startup_id: the startup notification ID (must be valid utf8)
2193  *
2194  * Sets the startup notification ID for a display.
2195  *
2196  * This is usually taken from the value of the DESKTOP_STARTUP_ID
2197  * environment variable, but in some cases (such as the application not
2198  * being launched using exec()) it can come from other sources.
2199  *
2200  * If the ID contains the string "_TIME" then the portion following that
2201  * string is taken to be the X11 timestamp of the event that triggered
2202  * the application to be launched and the GDK current event time is set
2203  * accordingly.
2204  *
2205  * The startup ID is also what is used to signal that the startup is
2206  * complete (for example, when opening a window or when calling
2207  * gdk_notify_startup_complete()).
2208  *
2209  * Since: 3.0
2210  **/
2211 void
2212 gdk_x11_display_set_startup_notification_id (GdkDisplay  *display,
2213                                              const gchar *startup_id)
2214 {
2215   GdkX11Display *display_x11;
2216   gchar *time_str;
2217
2218   display_x11 = GDK_X11_DISPLAY (display);
2219
2220   g_free (display_x11->startup_notification_id);
2221   display_x11->startup_notification_id = g_strdup (startup_id);
2222
2223   /* Find the launch time from the startup_id, if it's there.  Newer spec
2224    * states that the startup_id is of the form <unique>_TIME<timestamp>
2225    */
2226   time_str = g_strrstr (startup_id, "_TIME");
2227   if (time_str != NULL)
2228     {
2229       gulong retval;
2230       gchar *end;
2231       errno = 0;
2232
2233       /* Skip past the "_TIME" part */
2234       time_str += 5;
2235
2236       retval = strtoul (time_str, &end, 0);
2237       if (end != time_str && errno == 0)
2238         display_x11->user_time = retval;
2239     }
2240
2241   /* Set the startup id on the leader window so it
2242    * applies to all windows we create on this display
2243    */
2244   XChangeProperty (display_x11->xdisplay,
2245                    display_x11->leader_window,
2246                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
2247                    gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2248                    PropModeReplace,
2249                    (guchar *)startup_id, strlen (startup_id));
2250 }
2251
2252 static gboolean
2253 gdk_x11_display_supports_composite (GdkDisplay *display)
2254 {
2255   GdkX11Display *x11_display = GDK_X11_DISPLAY (display);
2256
2257   return x11_display->have_xcomposite &&
2258          x11_display->have_xdamage &&
2259          x11_display->have_xfixes;
2260 }
2261
2262 static GList *
2263 gdk_x11_display_list_devices (GdkDisplay *display)
2264 {
2265   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2266
2267   return GDK_X11_DISPLAY (display)->input_devices;
2268 }
2269
2270 /**
2271  * gdk_x11_register_standard_event_type:
2272  * @display: a #GdkDisplay
2273  * @event_base: first event type code to register
2274  * @n_events: number of event type codes to register
2275  *
2276  * Registers interest in receiving extension events with type codes
2277  * between @event_base and <literal>event_base + n_events - 1</literal>.
2278  * The registered events must have the window field in the same place
2279  * as core X events (this is not the case for e.g. XKB extension events).
2280  *
2281  * If an event type is registered, events of this type will go through
2282  * global and window-specific filters (see gdk_window_add_filter()).
2283  * Unregistered events will only go through global filters.
2284  * GDK may register the events of some X extensions on its own.
2285  *
2286  * This function should only be needed in unusual circumstances, e.g.
2287  * when filtering XInput extension events on the root window.
2288  *
2289  * Since: 2.4
2290  **/
2291 void
2292 gdk_x11_register_standard_event_type (GdkDisplay *display,
2293                                       gint        event_base,
2294                                       gint        n_events)
2295 {
2296   GdkEventTypeX11 *event_type;
2297   GdkX11Display *display_x11;
2298
2299   display_x11 = GDK_X11_DISPLAY (display);
2300   event_type = g_new (GdkEventTypeX11, 1);
2301
2302   event_type->base = event_base;
2303   event_type->n_events = n_events;
2304
2305   display_x11->event_types = g_slist_prepend (display_x11->event_types, event_type);
2306 }
2307
2308 /* compare X sequence numbers handling wraparound */
2309 #define SEQUENCE_COMPARE(a,op,b) (((long) (a) - (long) (b)) op 0)
2310
2311 /* delivers an error event from the error handler in gdkmain-x11.c */
2312 void
2313 _gdk_x11_display_error_event (GdkDisplay  *display,
2314                               XErrorEvent *error)
2315 {
2316   GdkX11Display *display_x11;
2317   GSList *tmp_list;
2318   gboolean ignore;
2319
2320   display_x11 = GDK_X11_DISPLAY (display);
2321
2322   ignore = FALSE;
2323   for (tmp_list = display_x11->error_traps;
2324        tmp_list != NULL;
2325        tmp_list = tmp_list->next)
2326     {
2327       GdkErrorTrap *trap;
2328
2329       trap = tmp_list->data;
2330
2331       if (SEQUENCE_COMPARE (trap->start_sequence, <=, error->serial) &&
2332           (trap->end_sequence == 0 ||
2333            SEQUENCE_COMPARE (trap->end_sequence, >, error->serial)))
2334         {
2335           ignore = TRUE;
2336           trap->error_code = error->error_code;
2337           break; /* only innermost trap gets the error code */
2338         }
2339     }
2340
2341   if (!ignore)
2342     {
2343       gchar buf[64];
2344       gchar *msg;
2345
2346       XGetErrorText (display_x11->xdisplay, error->error_code, buf, 63);
2347
2348       msg =
2349         g_strdup_printf ("The program '%s' received an X Window System error.\n"
2350                          "This probably reflects a bug in the program.\n"
2351                          "The error was '%s'.\n"
2352                          "  (Details: serial %ld error_code %d request_code %d minor_code %d)\n"
2353                          "  (Note to programmers: normally, X errors are reported asynchronously;\n"
2354                          "   that is, you will receive the error a while after causing it.\n"
2355                          "   To debug your program, run it with the --sync command line\n"
2356                          "   option to change this behavior. You can then get a meaningful\n"
2357                          "   backtrace from your debugger if you break on the gdk_x_error() function.)",
2358                          g_get_prgname (),
2359                          buf,
2360                          error->serial,
2361                          error->error_code,
2362                          error->request_code,
2363                          error->minor_code);
2364
2365 #ifdef G_ENABLE_DEBUG
2366       g_error ("%s", msg);
2367 #else /* !G_ENABLE_DEBUG */
2368       g_warning ("%s\n", msg);
2369
2370       exit (1);
2371 #endif /* G_ENABLE_DEBUG */
2372     }
2373 }
2374
2375 static void
2376 delete_outdated_error_traps (GdkX11Display *display_x11)
2377 {
2378   GSList *tmp_list;
2379   gulong processed_sequence;
2380
2381   processed_sequence = XLastKnownRequestProcessed (display_x11->xdisplay);
2382
2383   tmp_list = display_x11->error_traps;
2384   while (tmp_list != NULL)
2385     {
2386       GdkErrorTrap *trap = tmp_list->data;
2387
2388       if (trap->end_sequence != 0 &&
2389           SEQUENCE_COMPARE (trap->end_sequence, <=, processed_sequence))
2390         {
2391           GSList *free_me = tmp_list;
2392
2393           tmp_list = tmp_list->next;
2394           display_x11->error_traps =
2395             g_slist_delete_link (display_x11->error_traps, free_me);
2396           g_slice_free (GdkErrorTrap, trap);
2397         }
2398       else
2399         {
2400           tmp_list = tmp_list->next;
2401         }
2402     }
2403 }
2404
2405 /**
2406  * gdk_x11_display_error_trap_push:
2407  * @display: a #GdkDisplay
2408  *
2409  * Begins a range of X requests on @display for which X error events
2410  * will be ignored. Unignored errors (when no trap is pushed) will abort
2411  * the application. Use gdk_x11_display_error_trap_pop() or
2412  * gdk_x11_display_error_trap_pop_ignored()to lift a trap pushed
2413  * with this function.
2414  *
2415  * See also gdk_error_trap_push() to push a trap on all displays.
2416  *
2417  * Since: 3.0
2418  */
2419 void
2420 gdk_x11_display_error_trap_push (GdkDisplay *display)
2421 {
2422   GdkX11Display *display_x11;
2423   GdkErrorTrap *trap;
2424
2425   display_x11 = GDK_X11_DISPLAY (display);
2426
2427   delete_outdated_error_traps (display_x11);
2428
2429   /* set up the Xlib callback to tell us about errors */
2430   _gdk_x11_error_handler_push ();
2431
2432   trap = g_slice_new0 (GdkErrorTrap);
2433
2434   trap->start_sequence = XNextRequest (display_x11->xdisplay);
2435   trap->error_code = Success;
2436
2437   display_x11->error_traps =
2438     g_slist_prepend (display_x11->error_traps, trap);
2439 }
2440
2441 static gint
2442 gdk_x11_display_error_trap_pop_internal (GdkDisplay *display,
2443                                          gboolean    need_code)
2444 {
2445   GdkX11Display *display_x11;
2446   GdkErrorTrap *trap;
2447   GSList *tmp_list;
2448   int result;
2449
2450   display_x11 = GDK_X11_DISPLAY (display);
2451
2452   g_return_val_if_fail (display_x11->error_traps != NULL, Success);
2453
2454   /* Find the first trap that hasn't been popped already */
2455   trap = NULL; /* quiet gcc */
2456   for (tmp_list = display_x11->error_traps;
2457        tmp_list != NULL;
2458        tmp_list = tmp_list->next)
2459     {
2460       trap = tmp_list->data;
2461
2462       if (trap->end_sequence == 0)
2463         break;
2464     }
2465
2466   g_return_val_if_fail (trap != NULL, Success);
2467   g_assert (trap->end_sequence == 0);
2468
2469   /* May need to sync to fill in trap->error_code if we care about
2470    * getting an error code.
2471    */
2472   if (need_code)
2473     {
2474       gulong processed_sequence;
2475       gulong next_sequence;
2476
2477       next_sequence = XNextRequest (display_x11->xdisplay);
2478       processed_sequence = XLastKnownRequestProcessed (display_x11->xdisplay);
2479
2480       /* If our last request was already processed, there is no point
2481        * in syncing. i.e. if last request was a round trip (or even if
2482        * we got an event with the serial of a non-round-trip)
2483        */
2484       if ((next_sequence - 1) != processed_sequence)
2485         {
2486           XSync (display_x11->xdisplay, False);
2487         }
2488
2489       result = trap->error_code;
2490     }
2491   else
2492     {
2493       result = Success;
2494     }
2495
2496   /* record end of trap, giving us a range of
2497    * error sequences we'll ignore.
2498    */
2499   trap->end_sequence = XNextRequest (display_x11->xdisplay);
2500
2501   /* remove the Xlib callback */
2502   _gdk_x11_error_handler_pop ();
2503
2504   /* we may already be outdated */
2505   delete_outdated_error_traps (display_x11);
2506
2507   return result;
2508 }
2509
2510 /**
2511  * gdk_x11_display_error_trap_pop:
2512  * @display: the display
2513  *
2514  * Pops the error trap pushed by gdk_x11_display_error_trap_push().
2515  * Will XSync() if necessary and will always block until
2516  * the error is known to have occurred or not occurred,
2517  * so the error code can be returned.
2518  *
2519  * If you don't need to use the return value,
2520  * gdk_x11_display_error_trap_pop_ignored() would be more efficient.
2521  *
2522  * See gdk_error_trap_pop() for the all-displays-at-once
2523  * equivalent.
2524  *
2525  * Since: 3.0
2526  *
2527  * Return value: X error code or 0 on success
2528  */
2529 gint
2530 gdk_x11_display_error_trap_pop (GdkDisplay *display)
2531 {
2532   g_return_val_if_fail (GDK_IS_X11_DISPLAY (display), Success);
2533
2534   return gdk_x11_display_error_trap_pop_internal (display, TRUE);
2535 }
2536
2537 /**
2538  * gdk_x11_display_error_trap_pop_ignored:
2539  * @display: the display
2540  *
2541  * Pops the error trap pushed by gdk_x11_display_error_trap_push().
2542  * Does not block to see if an error occurred; merely records the
2543  * range of requests to ignore errors for, and ignores those errors
2544  * if they arrive asynchronously.
2545  *
2546  * See gdk_error_trap_pop_ignored() for the all-displays-at-once
2547  * equivalent.
2548  *
2549  * Since: 3.0
2550  */
2551 void
2552 gdk_x11_display_error_trap_pop_ignored (GdkDisplay *display)
2553 {
2554   g_return_if_fail (GDK_IS_X11_DISPLAY (display));
2555
2556   gdk_x11_display_error_trap_pop_internal (display, FALSE);
2557 }
2558
2559 /**
2560  * gdk_x11_set_sm_client_id:
2561  * @sm_client_id: the client id assigned by the session manager when the
2562  *    connection was opened, or %NULL to remove the property.
2563  *
2564  * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
2565  * the window manager can save the application's state using the X11R6 ICCCM
2566  * session management protocol.
2567  *
2568  * See the X Session Management Library documentation for more information on
2569  * session management and the Inter-Client Communication Conventions Manual
2570  *
2571  * Since: 2.24
2572  */
2573 void
2574 gdk_x11_set_sm_client_id (const gchar *sm_client_id)
2575 {
2576  GSList *displays, *l;
2577
2578   g_free (gdk_sm_client_id);
2579   gdk_sm_client_id = g_strdup (sm_client_id);
2580
2581   displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
2582   for (l = displays; l; l = l->next)
2583     set_sm_client_id (l->data, sm_client_id);
2584
2585   g_slist_free (displays);
2586 }
2587
2588 static void
2589 gdk_x11_display_event_data_copy (GdkDisplay    *display,
2590                                 const GdkEvent *src,
2591                                 GdkEvent       *dst)
2592 {
2593 }
2594
2595 static void
2596 gdk_x11_display_event_data_free (GdkDisplay *display,
2597                                  GdkEvent *event)
2598 {
2599 }
2600
2601 static gint
2602 pop_error_trap (GdkDisplay *display,
2603                 gboolean    ignored)
2604 {
2605   if (ignored)
2606     {
2607       gdk_x11_display_error_trap_pop_ignored (display);
2608       return Success;
2609     }
2610   else
2611     {
2612       return gdk_x11_display_error_trap_pop (display);
2613     }
2614 }
2615
2616 static GdkKeymap *
2617 gdk_x11_display_get_keymap (GdkDisplay *display)
2618 {
2619   GdkX11Display *display_x11;
2620   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2621   display_x11 = GDK_X11_DISPLAY (display);
2622
2623   if (!display_x11->keymap)
2624     display_x11->keymap = g_object_new (GDK_TYPE_X11_KEYMAP, NULL);
2625
2626   display_x11->keymap->display = display;
2627
2628   return display_x11->keymap;
2629 }
2630
2631 static void
2632 gdk_x11_display_class_init (GdkX11DisplayClass * class)
2633 {
2634   GObjectClass *object_class = G_OBJECT_CLASS (class);
2635   GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (class);
2636
2637   object_class->dispose = gdk_x11_display_dispose;
2638   object_class->finalize = gdk_x11_display_finalize;
2639
2640   display_class->window_type = GDK_TYPE_X11_WINDOW;
2641
2642   display_class->get_name = gdk_x11_display_get_name;
2643   display_class->get_n_screens = gdk_x11_display_get_n_screens;
2644   display_class->get_screen = gdk_x11_display_get_screen;
2645   display_class->get_default_screen = gdk_x11_display_get_default_screen;
2646   display_class->beep = gdk_x11_display_beep;
2647   display_class->sync = gdk_x11_display_sync;
2648   display_class->flush = gdk_x11_display_flush;
2649   display_class->has_pending = gdk_x11_display_has_pending;
2650   display_class->queue_events = _gdk_x11_display_queue_events;
2651   display_class->get_default_group = gdk_x11_display_get_default_group;
2652   display_class->supports_selection_notification = gdk_x11_display_supports_selection_notification;
2653   display_class->request_selection_notification = gdk_x11_display_request_selection_notification;
2654   display_class->supports_clipboard_persistence = gdk_x11_display_supports_clipboard_persistence;
2655   display_class->store_clipboard = gdk_x11_display_store_clipboard;
2656   display_class->supports_shapes = gdk_x11_display_supports_shapes;
2657   display_class->supports_input_shapes = gdk_x11_display_supports_input_shapes;
2658   display_class->supports_composite = gdk_x11_display_supports_composite;
2659   display_class->list_devices = gdk_x11_display_list_devices;
2660   display_class->get_app_launch_context = _gdk_x11_display_get_app_launch_context;
2661   display_class->get_cursor_for_type = _gdk_x11_display_get_cursor_for_type;
2662   display_class->get_cursor_for_name = _gdk_x11_display_get_cursor_for_name;
2663   display_class->get_cursor_for_pixbuf = _gdk_x11_display_get_cursor_for_pixbuf;
2664   display_class->get_default_cursor_size = _gdk_x11_display_get_default_cursor_size;
2665   display_class->get_maximal_cursor_size = _gdk_x11_display_get_maximal_cursor_size;
2666   display_class->supports_cursor_alpha = _gdk_x11_display_supports_cursor_alpha;
2667   display_class->supports_cursor_color = _gdk_x11_display_supports_cursor_color;
2668
2669   display_class->before_process_all_updates = _gdk_x11_display_before_process_all_updates;
2670   display_class->after_process_all_updates = _gdk_x11_display_after_process_all_updates;
2671   display_class->get_next_serial = gdk_x11_display_get_next_serial;
2672   display_class->notify_startup_complete = gdk_x11_display_notify_startup_complete;
2673   display_class->event_data_copy = gdk_x11_display_event_data_copy;
2674   display_class->event_data_free = gdk_x11_display_event_data_free;
2675   display_class->create_window_impl = _gdk_x11_display_create_window_impl;
2676   display_class->get_keymap = gdk_x11_display_get_keymap;
2677   display_class->push_error_trap = gdk_x11_display_error_trap_push;
2678   display_class->pop_error_trap = pop_error_trap;
2679   display_class->get_selection_owner = _gdk_x11_display_get_selection_owner;
2680   display_class->set_selection_owner = _gdk_x11_display_set_selection_owner;
2681   display_class->send_selection_notify = _gdk_x11_display_send_selection_notify;
2682   display_class->get_selection_property = _gdk_x11_display_get_selection_property;
2683   display_class->convert_selection = _gdk_x11_display_convert_selection;
2684   display_class->text_property_to_utf8_list = _gdk_x11_display_text_property_to_utf8_list;
2685   display_class->utf8_to_string_target = _gdk_x11_display_utf8_to_string_target;
2686 }