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