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