]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkevents-x11.c
Don't crash on broken ClientMessage events. (#157056, Owen Taylor)
[~andy/gtk] / gdk / x11 / gdkevents-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <config.h>
28
29 #include "gdkalias.h"
30 #include "gdk.h"
31 #include "gdkprivate-x11.h"
32 #include "gdkinternals.h"
33 #include "gdkx.h"
34 #include "gdkscreen-x11.h"
35 #include "gdkdisplay-x11.h"
36 #include "gdkasync.h"
37
38 #include "gdkkeysyms.h"
39
40 #include "xsettings-client.h"
41
42 #include <string.h>
43
44 #include "gdkinputprivate.h"
45
46 #ifdef HAVE_XKB
47 #include <X11/XKBlib.h>
48 #endif
49
50 #ifdef HAVE_XSYNC
51 #include <X11/extensions/sync.h>
52 #endif
53
54 #ifdef HAVE_XFIXES
55 #include <X11/extensions/Xfixes.h>
56 #endif
57
58 #include <X11/Xatom.h>
59
60 typedef struct _GdkIOClosure GdkIOClosure;
61 typedef struct _GdkDisplaySource GdkDisplaySource;
62 typedef struct _GdkEventTypeX11 GdkEventTypeX11;
63
64 struct _GdkIOClosure
65 {
66   GdkInputFunction function;
67   GdkInputCondition condition;
68   GdkDestroyNotify notify;
69   gpointer data;
70 };
71
72 struct _GdkDisplaySource
73 {
74   GSource source;
75   
76   GdkDisplay *display;
77   GPollFD event_poll_fd;
78 };
79
80 struct _GdkEventTypeX11
81 {
82   gint base;
83   gint n_events;
84 };
85
86 /* 
87  * Private function declarations
88  */
89
90 static gint      gdk_event_apply_filters (XEvent   *xevent,
91                                           GdkEvent *event,
92                                           GList    *filters);
93 static gboolean  gdk_event_translate     (GdkDisplay *display,
94                                           GdkEvent   *event, 
95                                           XEvent     *xevent,
96                                           gboolean    return_exposes);
97
98 static gboolean gdk_event_prepare  (GSource     *source,
99                                     gint        *timeout);
100 static gboolean gdk_event_check    (GSource     *source);
101 static gboolean gdk_event_dispatch (GSource     *source,
102                                     GSourceFunc  callback,
103                                     gpointer     user_data);
104
105 static GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
106                                                 GdkEvent  *event,
107                                                 gpointer   data);
108
109 static GSource *gdk_display_source_new (GdkDisplay *display);
110 static gboolean gdk_check_xpending     (GdkDisplay *display);
111
112 static void gdk_xsettings_watch_cb  (Window            window,
113                                      Bool              is_start,
114                                      long              mask,
115                                      void             *cb_data);
116 static void gdk_xsettings_notify_cb (const char       *name,
117                                      XSettingsAction   action,
118                                      XSettingsSetting *setting,
119                                      void             *data);
120
121 /* Private variable declarations
122  */
123
124 static GList *display_sources;
125
126 static GSourceFuncs event_funcs = {
127   gdk_event_prepare,
128   gdk_event_check,
129   gdk_event_dispatch,
130   NULL
131 };
132
133 static GSource *
134 gdk_display_source_new (GdkDisplay *display)
135 {
136   GSource *source = g_source_new (&event_funcs, sizeof (GdkDisplaySource));
137   GdkDisplaySource *display_source = (GdkDisplaySource *)source;
138   
139   display_source->display = display;
140   
141   return source;
142 }
143
144 static gboolean
145 gdk_check_xpending (GdkDisplay *display)
146 {
147   return XPending (GDK_DISPLAY_XDISPLAY (display));
148 }
149
150 /*********************************************
151  * Functions for maintaining the event queue *
152  *********************************************/
153
154 static void
155 refcounted_grab_server (Display *xdisplay)
156 {
157   GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
158
159   gdk_x11_display_grab (display);
160 }
161
162 static void
163 refcounted_ungrab_server (Display *xdisplay)
164 {
165   GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
166   
167   gdk_x11_display_ungrab (display);
168 }
169
170 void
171 _gdk_x11_events_init_screen (GdkScreen *screen)
172 {
173   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
174
175   /* Keep a flag to avoid extra notifies that we don't need
176    */
177   screen_x11->xsettings_in_init = TRUE;
178   screen_x11->xsettings_client = xsettings_client_new (screen_x11->xdisplay,
179                                                        screen_x11->screen_num,
180                                                        gdk_xsettings_notify_cb,
181                                                        gdk_xsettings_watch_cb,
182                                                        screen);
183   xsettings_client_set_grab_func (screen_x11->xsettings_client,
184                                   refcounted_grab_server);
185   xsettings_client_set_ungrab_func (screen_x11->xsettings_client,
186                                     refcounted_ungrab_server);
187   screen_x11->xsettings_in_init = FALSE;
188 }
189
190 void
191 _gdk_x11_events_uninit_screen (GdkScreen *screen)
192 {
193   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
194
195   xsettings_client_destroy (screen_x11->xsettings_client);
196   screen_x11->xsettings_client = NULL;
197 }
198
199 void 
200 _gdk_events_init (GdkDisplay *display)
201 {
202   GSource *source;
203   GdkDisplaySource *display_source;
204   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
205   
206   int connection_number = ConnectionNumber (display_x11->xdisplay);
207   GDK_NOTE (MISC, g_message ("connection number: %d", connection_number));
208
209
210   source = display_x11->event_source = gdk_display_source_new (display);
211   display_source = (GdkDisplaySource*) source;
212   g_source_set_priority (source, GDK_PRIORITY_EVENTS);
213   
214   display_source->event_poll_fd.fd = connection_number;
215   display_source->event_poll_fd.events = G_IO_IN;
216   
217   g_source_add_poll (source, &display_source->event_poll_fd);
218   g_source_set_can_recurse (source, TRUE);
219   g_source_attach (source, NULL);
220
221   display_sources = g_list_prepend (display_sources,display_source);
222
223   gdk_display_add_client_message_filter (display,
224                                          gdk_atom_intern ("WM_PROTOCOLS", FALSE), 
225                                          gdk_wm_protocols_filter,   
226                                          NULL);
227 }
228
229
230 /**
231  * gdk_events_pending:
232  * 
233  * Checks if any events are ready to be processed for any display.
234  * 
235  * Return value:  %TRUE if any events are pending.
236  **/
237 gboolean
238 gdk_events_pending (void)
239 {
240   GList *tmp_list;
241
242   for (tmp_list = display_sources; tmp_list; tmp_list = tmp_list->next)
243     {
244       GdkDisplaySource *tmp_source = tmp_list->data;
245       GdkDisplay *display = tmp_source->display;
246       
247       if (_gdk_event_queue_find_first (display))
248         return TRUE;
249     }
250
251   for (tmp_list = display_sources; tmp_list; tmp_list = tmp_list->next)
252     {
253       GdkDisplaySource *tmp_source = tmp_list->data;
254       GdkDisplay *display = tmp_source->display;
255       
256       if (gdk_check_xpending (display))
257         return TRUE;
258     }
259   
260   return FALSE;
261 }
262
263 static Bool
264 graphics_expose_predicate (Display  *display,
265                            XEvent   *xevent,
266                            XPointer  arg)
267 {
268   if (xevent->xany.window == GDK_DRAWABLE_XID ((GdkDrawable *)arg) &&
269       (xevent->xany.type == GraphicsExpose ||
270        xevent->xany.type == NoExpose))
271     return True;
272   else
273     return False;
274 }
275
276 /**
277  * gdk_event_get_graphics_expose:
278  * @window: the #GdkWindow to wait for the events for.
279  * 
280  * Waits for a GraphicsExpose or NoExpose event from the X server.
281  * This is used in the #GtkText and #GtkCList widgets in GTK+ to make sure any
282  * GraphicsExpose events are handled before the widget is scrolled.
283  *
284  * Return value:  a #GdkEventExpose if a GraphicsExpose was received, or %NULL if a
285  * NoExpose event was received.
286  **/
287 GdkEvent*
288 gdk_event_get_graphics_expose (GdkWindow *window)
289 {
290   XEvent xevent;
291   GdkEvent *event;
292   
293   g_return_val_if_fail (window != NULL, NULL);
294   
295   XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent, 
296             graphics_expose_predicate, (XPointer) window);
297   
298   if (xevent.xany.type == GraphicsExpose)
299     {
300       event = gdk_event_new (GDK_NOTHING);
301       
302       if (gdk_event_translate (GDK_WINDOW_DISPLAY (window), event,
303                                &xevent, TRUE))
304         return event;
305       else
306         gdk_event_free (event);
307     }
308   
309   return NULL;  
310 }
311
312 static gint
313 gdk_event_apply_filters (XEvent *xevent,
314                          GdkEvent *event,
315                          GList *filters)
316 {
317   GList *tmp_list;
318   GdkFilterReturn result;
319   
320   tmp_list = filters;
321   
322   while (tmp_list)
323     {
324       GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
325       
326       tmp_list = tmp_list->next;
327       result = filter->function (xevent, event, filter->data);
328       if (result !=  GDK_FILTER_CONTINUE)
329         return result;
330     }
331   
332   return GDK_FILTER_CONTINUE;
333 }
334
335 /**
336  * gdk_display_add_client_message_filter:
337  * @display: a #GdkDisplay for which this message filter applies
338  * @message_type: the type of ClientMessage events to receive.
339  *   This will be checked against the @message_type field 
340  *   of the XClientMessage event struct.
341  * @func: the function to call to process the event.
342  * @data: user data to pass to @func.
343  *
344  * Adds a filter to be called when X ClientMessage events are received.
345  *
346  * Since: 2.2
347  **/ 
348 void 
349 gdk_display_add_client_message_filter (GdkDisplay   *display,
350                                        GdkAtom       message_type,
351                                        GdkFilterFunc func,
352                                        gpointer      data)
353 {
354   GdkClientFilter *filter;
355   g_return_if_fail (GDK_IS_DISPLAY (display));
356   filter = g_new (GdkClientFilter, 1);
357
358   filter->type = message_type;
359   filter->function = func;
360   filter->data = data;
361   
362   GDK_DISPLAY_X11(display)->client_filters = 
363     g_list_append (GDK_DISPLAY_X11 (display)->client_filters,
364                    filter);
365 }
366
367 /**
368  * gdk_add_client_message_filter:
369  * @message_type: the type of ClientMessage events to receive. This will be
370  *     checked against the <structfield>message_type</structfield> field of the
371  *     XClientMessage event struct.
372  * @func: the function to call to process the event.
373  * @data: user data to pass to @func. 
374  * 
375  * Adds a filter to the default display to be called when X ClientMessage events
376  * are received. See gdk_display_add_client_message_filter().
377  **/
378 void 
379 gdk_add_client_message_filter (GdkAtom       message_type,
380                                GdkFilterFunc func,
381                                gpointer      data)
382 {
383   gdk_display_add_client_message_filter (gdk_display_get_default (),
384                                          message_type, func, data);
385 }
386
387 static void
388 do_net_wm_state_changes (GdkWindow *window)
389 {
390   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
391   GdkWindowState old_state;
392   
393   if (GDK_WINDOW_DESTROYED (window) ||
394       gdk_window_get_window_type (window) != GDK_WINDOW_TOPLEVEL)
395     return;
396   
397   old_state = gdk_window_get_state (window);
398
399   /* For found_sticky to remain TRUE, we have to also be on desktop
400    * 0xFFFFFFFF
401    */
402   if (old_state & GDK_WINDOW_STATE_STICKY)
403     {
404       if (!(toplevel->have_sticky && toplevel->on_all_desktops))
405         gdk_synthesize_window_state (window,
406                                      GDK_WINDOW_STATE_STICKY,
407                                      0);
408     }
409   else
410     {
411       if (toplevel->have_sticky && toplevel->on_all_desktops)
412         gdk_synthesize_window_state (window,
413                                      0,
414                                      GDK_WINDOW_STATE_STICKY);
415     }
416
417   if (old_state & GDK_WINDOW_STATE_FULLSCREEN)
418     {
419       if (!toplevel->have_fullscreen)
420         gdk_synthesize_window_state (window,
421                                      GDK_WINDOW_STATE_FULLSCREEN,
422                                      0);
423     }
424   else
425     {
426       if (toplevel->have_fullscreen)
427         gdk_synthesize_window_state (window,
428                                      0,
429                                      GDK_WINDOW_STATE_FULLSCREEN);
430     }
431   
432   /* Our "maximized" means both vertical and horizontal; if only one,
433    * we don't expose that via GDK
434    */
435   if (old_state & GDK_WINDOW_STATE_MAXIMIZED)
436     {
437       if (!(toplevel->have_maxvert && toplevel->have_maxhorz))
438         gdk_synthesize_window_state (window,
439                                      GDK_WINDOW_STATE_MAXIMIZED,
440                                      0);
441     }
442   else
443     {
444       if (toplevel->have_maxvert && toplevel->have_maxhorz)
445         gdk_synthesize_window_state (window,
446                                      0,
447                                      GDK_WINDOW_STATE_MAXIMIZED);
448     }
449 }
450
451 static void
452 gdk_check_wm_desktop_changed (GdkWindow *window)
453 {
454   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
455   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
456
457   Atom type;
458   gint format;
459   gulong nitems;
460   gulong bytes_after;
461
462   if (toplevel->have_sticky)
463     {
464       gulong *desktop;
465       
466       type = None;
467       gdk_error_trap_push ();
468       XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), 
469                           GDK_WINDOW_XID (window),
470                           gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
471                           0, G_MAXLONG, False, XA_CARDINAL, &type, 
472                           &format, &nitems,
473                           &bytes_after, (guchar **)&desktop);
474       gdk_error_trap_pop ();
475
476       if (type != None)
477         {
478           toplevel->on_all_desktops = (*desktop == 0xFFFFFFFF);
479           XFree (desktop);
480         }
481       else
482         toplevel->on_all_desktops = FALSE;
483       
484       do_net_wm_state_changes (window);
485     }
486 }
487
488 static void
489 gdk_check_wm_state_changed (GdkWindow *window)
490 {
491   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
492   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
493   
494   Atom type;
495   gint format;
496   gulong nitems;
497   gulong bytes_after;
498   Atom *atoms = NULL;
499   gulong i;
500
501   gboolean had_sticky = toplevel->have_sticky;
502
503   toplevel->have_sticky = FALSE;
504   toplevel->have_maxvert = FALSE;
505   toplevel->have_maxhorz = FALSE;
506   toplevel->have_fullscreen = FALSE;
507
508   type = None;
509   gdk_error_trap_push ();
510   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
511                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
512                       0, G_MAXLONG, False, XA_ATOM, &type, &format, &nitems,
513                       &bytes_after, (guchar **)&atoms);
514   gdk_error_trap_pop ();
515
516   if (type != None)
517     {
518       Atom sticky_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_STICKY");
519       Atom maxvert_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT");
520       Atom maxhorz_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ");
521       Atom fullscreen_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FULLSCREEN");
522
523       i = 0;
524       while (i < nitems)
525         {
526           if (atoms[i] == sticky_atom)
527             toplevel->have_sticky = TRUE;
528           else if (atoms[i] == maxvert_atom)
529             toplevel->have_maxvert = TRUE;
530           else if (atoms[i] == maxhorz_atom)
531             toplevel->have_maxhorz = TRUE;
532           else if (atoms[i] == fullscreen_atom)
533             toplevel->have_fullscreen = TRUE;
534           
535           ++i;
536         }
537
538       XFree (atoms);
539     }
540
541   /* When have_sticky is turned on, we have to check the DESKTOP property
542    * as well.
543    */
544   if (toplevel->have_sticky && !had_sticky)
545     gdk_check_wm_desktop_changed (window);
546   else
547     do_net_wm_state_changes (window);
548 }
549
550 #define HAS_FOCUS(toplevel)                           \
551   ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
552
553 static void
554 generate_focus_event (GdkWindow *window,
555                       gboolean   in)
556 {
557   GdkEvent event;
558   
559   event.type = GDK_FOCUS_CHANGE;
560   event.focus_change.window = window;
561   event.focus_change.send_event = FALSE;
562   event.focus_change.in = in;
563   
564   gdk_event_put (&event);
565 }
566
567 static void
568 set_screen_from_root (GdkDisplay *display,
569                       GdkEvent   *event,
570                       Window      xrootwin)
571 {
572   GdkScreen *screen;
573
574   screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
575   g_assert (screen);
576
577   gdk_event_set_screen (event, screen);
578 }
579
580 static void
581 translate_key_event (GdkDisplay *display,
582                      GdkEvent   *event,
583                      XEvent     *xevent)
584 {
585   GdkKeymap *keymap = gdk_keymap_get_for_display (display);
586   gunichar c = 0;
587   guchar buf[7];
588
589   event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
590   event->key.time = xevent->xkey.time;
591
592   event->key.state = (GdkModifierType) xevent->xkey.state;
593   event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
594   event->key.hardware_keycode = xevent->xkey.keycode;
595
596   event->key.keyval = GDK_VoidSymbol;
597
598   gdk_keymap_translate_keyboard_state (keymap,
599                                        event->key.hardware_keycode,
600                                        event->key.state,
601                                        event->key.group,
602                                        &event->key.keyval,
603                                        NULL, NULL, NULL);
604
605   /* Fill in event->string crudely, since various programs
606    * depend on it.
607    */
608   event->key.string = NULL;
609   
610   if (event->key.keyval != GDK_VoidSymbol)
611     c = gdk_keyval_to_unicode (event->key.keyval);
612
613   if (c)
614     {
615       gsize bytes_written;
616       gint len;
617
618       /* Apply the control key - Taken from Xlib
619        */
620       if (event->key.state & GDK_CONTROL_MASK)
621         {
622           if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
623           else if (c == '2')
624             {
625               event->key.string = g_memdup ("\0\0", 2);
626               event->key.length = 1;
627               buf[0] = '\0';
628               goto out;
629             }
630           else if (c >= '3' && c <= '7') c -= ('3' - '\033');
631           else if (c == '8') c = '\177';
632           else if (c == '/') c = '_' & 0x1F;
633         }
634       
635       len = g_unichar_to_utf8 (c, buf);
636       buf[len] = '\0';
637       
638       event->key.string = g_locale_from_utf8 (buf, len,
639                                               NULL, &bytes_written,
640                                               NULL);
641       if (event->key.string)
642         event->key.length = bytes_written;
643     }
644   else if (event->key.keyval == GDK_Escape)
645     {
646       event->key.length = 1;
647       event->key.string = g_strdup ("\033");
648     }
649   else if (event->key.keyval == GDK_Return ||
650           event->key.keyval == GDK_KP_Enter)
651     {
652       event->key.length = 1;
653       event->key.string = g_strdup ("\r");
654     }
655
656   if (!event->key.string)
657     {
658       event->key.length = 0;
659       event->key.string = g_strdup ("");
660     }
661   
662  out:
663 #ifdef G_ENABLE_DEBUG
664   if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
665     {
666       g_message ("%s:\t\twindow: %ld     key: %12s  %d",
667                  event->type == GDK_KEY_PRESS ? "key press  " : "key release",
668                  xevent->xkey.window,
669                  event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
670                  event->key.keyval);
671   
672       if (event->key.length > 0)
673         g_message ("\t\tlength: %4d string: \"%s\"",
674                    event->key.length, buf);
675     }
676 #endif /* G_ENABLE_DEBUG */  
677   return;
678 }
679
680 /**
681  * gdk_x11_register_standard_event_type:
682  * @display: a #GdkDisplay
683  * @event_base: first event type code to register
684  * @n_events: number of event type codes to register
685  * 
686  * Registers interest in receiving extension events with type codes
687  * between @event_base and <literal>event_base + n_events - 1</literal>.
688  * The registered events must have the window field in the same place
689  * as core X events (this is not the case for e.g. XKB extension events).
690  *
691  * If an event type is registered, events of this type will go through
692  * global and window-specific filters (see gdk_window_add_filter()). 
693  * Unregistered events will only go through global filters.
694  * GDK may register the events of some X extensions on its own.
695  * 
696  * This function should only be needed in unusual circumstances, e.g.
697  * when filtering XInput extension events on the root window.
698  *
699  * Since: 2.4
700  **/
701 void
702 gdk_x11_register_standard_event_type (GdkDisplay          *display,
703                                       gint                 event_base,
704                                       gint                 n_events)
705 {
706   GdkEventTypeX11 *event_type;
707   GdkDisplayX11 *display_x11;
708
709   display_x11 = GDK_DISPLAY_X11 (display);
710   event_type = g_new (GdkEventTypeX11, 1);
711
712   event_type->base = event_base;
713   event_type->n_events = n_events;
714
715   display_x11->event_types = g_slist_prepend (display_x11->event_types, event_type);
716 }
717
718 /* Return the window this has to do with, if any, rather
719  * than the frame or root window that was selecting
720  * for substructure
721  */
722 static void
723 get_real_window (GdkDisplay *display,
724                  XEvent     *event,
725                  Window     *event_window,
726                  Window     *filter_window)
727 {
728   /* Core events all have an event->xany.window field, but that's
729    * not true for extension events
730    */
731   if (event->type >= KeyPress &&
732       event->type <= MappingNotify)
733     {
734       *filter_window = event->xany.window;
735       switch (event->type)
736         {      
737         case CreateNotify:
738           *event_window = event->xcreatewindow.window;
739           break;
740         case DestroyNotify:
741           *event_window = event->xdestroywindow.window;
742           break;
743         case UnmapNotify:
744           *event_window = event->xunmap.window;
745           break;
746         case MapNotify:
747           *event_window = event->xmap.window;
748           break;
749         case MapRequest:
750           *event_window = event->xmaprequest.window;
751           break;
752         case ReparentNotify:
753           *event_window = event->xreparent.window;
754           break;
755         case ConfigureNotify:
756           *event_window = event->xconfigure.window;
757           break;
758         case ConfigureRequest:
759           *event_window = event->xconfigurerequest.window;
760           break;
761         case GravityNotify:
762           *event_window = event->xgravity.window;
763           break;
764         case CirculateNotify:
765           *event_window = event->xcirculate.window;
766           break;
767         case CirculateRequest:
768           *event_window = event->xcirculaterequest.window;
769           break;
770         default:
771           *event_window = event->xany.window;
772         }
773     }
774   else
775     {
776       GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
777       GSList *tmp_list;
778
779       for (tmp_list = display_x11->event_types;
780            tmp_list;
781            tmp_list = tmp_list->next)
782         {
783           GdkEventTypeX11 *event_type = tmp_list->data;
784
785           if (event->type >= event_type->base &&
786               event->type < event_type->base + event_type->n_events)
787             {
788               *event_window = event->xany.window;
789               *filter_window = event->xany.window;
790               return;
791             }
792         }
793            
794       *event_window = None;
795       *filter_window = None;
796     }
797 }
798
799 #ifdef G_ENABLE_DEBUG
800 static const char notify_modes[][19] = {
801   "NotifyNormal",
802   "NotifyGrab",
803   "NotifyUngrab",
804   "NotifyWhileGrabbed"
805 };
806
807 static const char notify_details[][23] = {
808   "NotifyAncestor",
809   "NotifyVirtual",
810   "NotifyInferior",
811   "NotifyNonlinear",
812   "NotifyNonlinearVirtual",
813   "NotifyPointer",
814   "NotifyPointerRoot",
815   "NotifyDetailNone"
816 };
817 #endif
818
819 static void
820 set_user_time (GdkWindow *window,
821                GdkEvent  *event)
822 {
823   g_return_if_fail (event != NULL);
824
825   window = gdk_window_get_toplevel (event->client.window);
826   g_return_if_fail (GDK_IS_WINDOW (window));
827
828   /* If an event doesn't have a valid timestamp, we shouldn't use it
829    * to update the latest user interaction time.
830    */
831   if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
832     gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
833                                   gdk_event_get_time (event));
834 }
835
836 static gboolean
837 gdk_event_translate (GdkDisplay *display,
838                      GdkEvent   *event,
839                      XEvent     *xevent,
840                      gboolean    return_exposes)
841 {
842   
843   GdkWindow *window;
844   GdkWindowObject *window_private;
845   GdkWindow *filter_window;
846   GdkWindowImplX11 *window_impl = NULL;
847   gboolean return_val;
848   gint xoffset, yoffset;
849   GdkScreen *screen = NULL;
850   GdkScreenX11 *screen_x11 = NULL;
851   GdkToplevelX11 *toplevel = NULL;
852   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
853   Window xwindow, filter_xwindow;
854   
855   return_val = FALSE;
856
857   /* init these, since the done: block uses them */
858   window = NULL;
859   window_private = NULL;
860   event->any.window = NULL;
861
862   if (_gdk_default_filters)
863     {
864       /* Apply global filters */
865       GdkFilterReturn result;
866       result = gdk_event_apply_filters (xevent, event,
867                                         _gdk_default_filters);
868       
869       if (result != GDK_FILTER_CONTINUE)
870         {
871           return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
872           goto done;
873         }
874     }  
875
876   /* Find the GdkWindow that this event relates to.
877    * Basically this means substructure events
878    * are reported same as structure events
879    */
880   get_real_window (display, xevent, &xwindow, &filter_xwindow);
881   
882   window = gdk_window_lookup_for_display (display, xwindow);
883   /* We may receive events such as NoExpose/GraphicsExpose
884    * and ShmCompletion for pixmaps
885    */
886   if (window && !GDK_IS_WINDOW (window))
887     window = NULL;
888   window_private = (GdkWindowObject *) window;
889
890   /* We always run the filters for the window where the event
891    * is delivered, not the window that it relates to
892    */
893   if (filter_xwindow == xwindow)
894     filter_window = window;
895   else
896     {
897       filter_window = gdk_window_lookup_for_display (display, filter_xwindow);
898       if (filter_window && !GDK_IS_WINDOW (filter_window))
899         filter_window = NULL;
900     }
901
902   if (window)
903     {
904       screen = GDK_WINDOW_SCREEN (window);
905       screen_x11 = GDK_SCREEN_X11 (screen);
906       toplevel = _gdk_x11_window_get_toplevel (window);
907     }
908     
909   if (window != NULL)
910     {
911       window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
912       
913       /* Move key events on focus window to the real toplevel, and
914        * filter out all other events on focus window
915        */          
916       if (toplevel && xwindow == toplevel->focus_window)
917         {
918           switch (xevent->type)
919             {
920             case KeyPress:
921             case KeyRelease:
922               xwindow = GDK_WINDOW_XID (window);
923               xevent->xany.window = xwindow;
924               break;
925             default:
926               return FALSE;
927             }
928         }
929
930       g_object_ref (window);
931     }
932
933   event->any.window = window;
934   event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
935   
936   if (window_private && GDK_WINDOW_DESTROYED (window))
937     {
938       if (xevent->type != DestroyNotify)
939         {
940           return_val = FALSE;
941           goto done;
942         }
943     }
944   else if (filter_window)
945     {
946       /* Apply per-window filters */
947       GdkWindowObject *filter_private = (GdkWindowObject *) filter_window;
948       GdkFilterReturn result;
949
950       if (filter_private->filters)
951         {
952           g_object_ref (filter_window);
953           
954           result = gdk_event_apply_filters (xevent, event,
955                                             filter_private->filters);
956           
957           g_object_unref (filter_window);
958       
959           if (result != GDK_FILTER_CONTINUE)
960             {
961               return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
962               goto done;
963             }
964         }
965     }
966       
967   if (screen_x11 && screen_x11->wmspec_check_window != None &&
968       xwindow == screen_x11->wmspec_check_window)
969     {
970       if (xevent->type == DestroyNotify)
971         {
972           screen_x11->wmspec_check_window = None;
973           g_free (screen_x11->window_manager_name);
974           screen_x11->window_manager_name = g_strdup ("unknown");
975
976           /* careful, reentrancy */
977           _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
978         }
979       
980       /* Eat events on this window unless someone had wrapped
981        * it as a foreign window
982        */
983       if (window == NULL)
984         {
985           return_val = FALSE;
986           goto done;
987         }
988     }
989
990   if (window &&
991       (xevent->xany.type == MotionNotify ||
992        xevent->xany.type == ButtonRelease))
993     {
994       if (_gdk_moveresize_handle_event (xevent))
995         {
996           return_val = FALSE;
997           goto done;
998         }
999     }
1000   
1001   /* We do a "manual" conversion of the XEvent to a
1002    *  GdkEvent. The structures are mostly the same so
1003    *  the conversion is fairly straightforward. We also
1004    *  optionally print debugging info regarding events
1005    *  received.
1006    */
1007
1008   return_val = TRUE;
1009
1010   if (window)
1011     {
1012       _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
1013     }
1014   else
1015     {
1016       xoffset = 0;
1017       yoffset = 0;
1018     }
1019
1020   switch (xevent->type)
1021     {
1022     case KeyPress:
1023       if (window_private == NULL)
1024         {
1025           return_val = FALSE;
1026           break;
1027         }
1028       translate_key_event (display, event, xevent);
1029       set_user_time (window, event);
1030       break;
1031
1032     case KeyRelease:
1033       if (window_private == NULL)
1034         {
1035           return_val = FALSE;
1036           break;
1037         }
1038       
1039       /* Emulate detectable auto-repeat by checking to see
1040        * if the next event is a key press with the same
1041        * keycode and timestamp, and if so, ignoring the event.
1042        */
1043
1044       if (!display_x11->have_xkb_autorepeat && XPending (xevent->xkey.display))
1045         {
1046           XEvent next_event;
1047
1048           XPeekEvent (xevent->xkey.display, &next_event);
1049
1050           if (next_event.type == KeyPress &&
1051               next_event.xkey.keycode == xevent->xkey.keycode &&
1052               next_event.xkey.time == xevent->xkey.time)
1053             {
1054               return_val = FALSE;
1055               break;
1056             }
1057         }
1058
1059       translate_key_event (display, event, xevent);
1060       break;
1061       
1062     case ButtonPress:
1063       GDK_NOTE (EVENTS, 
1064                 g_message ("button press:\t\twindow: %ld  x,y: %d %d  button: %d",
1065                            xevent->xbutton.window,
1066                            xevent->xbutton.x, xevent->xbutton.y,
1067                            xevent->xbutton.button));
1068       
1069       if (window_private == NULL || 
1070           ((window_private->extension_events != 0) &&
1071            display_x11->input_ignore_core))
1072         {
1073           return_val = FALSE;
1074           break;
1075         }
1076       
1077       /* If we get a ButtonPress event where the button is 4 or 5,
1078          it's a Scroll event */
1079       switch (xevent->xbutton.button)
1080         {
1081         case 4: /* up */
1082         case 5: /* down */
1083         case 6: /* left */
1084         case 7: /* right */
1085           event->scroll.type = GDK_SCROLL;
1086
1087           if (xevent->xbutton.button == 4)
1088             event->scroll.direction = GDK_SCROLL_UP;
1089           else if (xevent->xbutton.button == 5)
1090             event->scroll.direction = GDK_SCROLL_DOWN;
1091           else if (xevent->xbutton.button == 6)
1092             event->scroll.direction = GDK_SCROLL_LEFT;
1093           else
1094             event->scroll.direction = GDK_SCROLL_RIGHT;
1095
1096           event->scroll.window = window;
1097           event->scroll.time = xevent->xbutton.time;
1098           event->scroll.x = xevent->xbutton.x + xoffset;
1099           event->scroll.y = xevent->xbutton.y + yoffset;
1100           event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
1101           event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
1102           event->scroll.state = (GdkModifierType) xevent->xbutton.state;
1103           event->scroll.device = display->core_pointer;
1104
1105           set_screen_from_root (display, event, xevent->xbutton.root);
1106           
1107           break;
1108           
1109         default:
1110           event->button.type = GDK_BUTTON_PRESS;
1111           event->button.window = window;
1112           event->button.time = xevent->xbutton.time;
1113           event->button.x = xevent->xbutton.x + xoffset;
1114           event->button.y = xevent->xbutton.y + yoffset;
1115           event->button.x_root = (gfloat)xevent->xbutton.x_root;
1116           event->button.y_root = (gfloat)xevent->xbutton.y_root;
1117           event->button.axes = NULL;
1118           event->button.state = (GdkModifierType) xevent->xbutton.state;
1119           event->button.button = xevent->xbutton.button;
1120           event->button.device = display->core_pointer;
1121           
1122           set_screen_from_root (display, event, xevent->xbutton.root);
1123
1124           _gdk_event_button_generate (display, event);
1125           break;
1126         }
1127
1128       set_user_time (window, event);
1129       break;
1130       
1131     case ButtonRelease:
1132       GDK_NOTE (EVENTS, 
1133                 g_message ("button release:\twindow: %ld  x,y: %d %d  button: %d",
1134                            xevent->xbutton.window,
1135                            xevent->xbutton.x, xevent->xbutton.y,
1136                            xevent->xbutton.button));
1137       
1138       if (window_private == NULL ||
1139           ((window_private->extension_events != 0) &&
1140            display_x11->input_ignore_core))
1141         {
1142           return_val = FALSE;
1143           break;
1144         }
1145       
1146       /* We treat button presses as scroll wheel events, so ignore the release */
1147       if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5 ||
1148           xevent->xbutton.button == 6 || xevent->xbutton.button ==7)
1149         {
1150           return_val = FALSE;
1151           break;
1152         }
1153
1154       event->button.type = GDK_BUTTON_RELEASE;
1155       event->button.window = window;
1156       event->button.time = xevent->xbutton.time;
1157       event->button.x = xevent->xbutton.x + xoffset;
1158       event->button.y = xevent->xbutton.y + yoffset;
1159       event->button.x_root = (gfloat)xevent->xbutton.x_root;
1160       event->button.y_root = (gfloat)xevent->xbutton.y_root;
1161       event->button.axes = NULL;
1162       event->button.state = (GdkModifierType) xevent->xbutton.state;
1163       event->button.button = xevent->xbutton.button;
1164       event->button.device = display->core_pointer;
1165
1166       set_screen_from_root (display, event, xevent->xbutton.root);
1167       
1168       break;
1169       
1170     case MotionNotify:
1171       GDK_NOTE (EVENTS,
1172                 g_message ("motion notify:\t\twindow: %ld  x,y: %d %d  hint: %s", 
1173                            xevent->xmotion.window,
1174                            xevent->xmotion.x, xevent->xmotion.y,
1175                            (xevent->xmotion.is_hint) ? "true" : "false"));
1176       
1177       if (window_private == NULL ||
1178           ((window_private->extension_events != 0) &&
1179            display_x11->input_ignore_core))
1180         {
1181           return_val = FALSE;
1182           break;
1183         }
1184       
1185       event->motion.type = GDK_MOTION_NOTIFY;
1186       event->motion.window = window;
1187       event->motion.time = xevent->xmotion.time;
1188       event->motion.x = xevent->xmotion.x + xoffset;
1189       event->motion.y = xevent->xmotion.y + yoffset;
1190       event->motion.x_root = (gfloat)xevent->xmotion.x_root;
1191       event->motion.y_root = (gfloat)xevent->xmotion.y_root;
1192       event->motion.axes = NULL;
1193       event->motion.state = (GdkModifierType) xevent->xmotion.state;
1194       event->motion.is_hint = xevent->xmotion.is_hint;
1195       event->motion.device = display->core_pointer;
1196       
1197       set_screen_from_root (display, event, xevent->xmotion.root);
1198       
1199       break;
1200       
1201     case EnterNotify:
1202       GDK_NOTE (EVENTS,
1203                 g_message ("enter notify:\t\twindow: %ld  detail: %d subwin: %ld",
1204                            xevent->xcrossing.window,
1205                            xevent->xcrossing.detail,
1206                            xevent->xcrossing.subwindow));
1207  
1208       if (window_private == NULL)
1209         {
1210           return_val = FALSE;
1211           break;
1212         }
1213       
1214       /* Handle focusing (in the case where no window manager is running */
1215       if (toplevel &&
1216           xevent->xcrossing.detail != NotifyInferior &&
1217           xevent->xcrossing.focus && !toplevel->has_focus_window)
1218         {
1219           gboolean had_focus = HAS_FOCUS (toplevel);
1220
1221           toplevel->has_pointer_focus = TRUE;
1222
1223           if (HAS_FOCUS (toplevel) != had_focus)
1224             generate_focus_event (window, TRUE);
1225         }
1226
1227       /* Tell XInput stuff about it if appropriate */
1228       if (window_private &&
1229           !GDK_WINDOW_DESTROYED (window) &&
1230           window_private->extension_events != 0)
1231         _gdk_input_enter_event (&xevent->xcrossing, window);
1232       
1233       event->crossing.type = GDK_ENTER_NOTIFY;
1234       event->crossing.window = window;
1235       
1236       /* If the subwindow field of the XEvent is non-NULL, then
1237        *  lookup the corresponding GdkWindow.
1238        */
1239       if (xevent->xcrossing.subwindow != None)
1240         event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
1241       else
1242         event->crossing.subwindow = NULL;
1243       
1244       event->crossing.time = xevent->xcrossing.time;
1245       event->crossing.x = xevent->xcrossing.x + xoffset;
1246       event->crossing.y = xevent->xcrossing.y + yoffset;
1247       event->crossing.x_root = xevent->xcrossing.x_root;
1248       event->crossing.y_root = xevent->xcrossing.y_root;
1249       
1250       set_screen_from_root (display, event, xevent->xcrossing.root);
1251       
1252       /* Translate the crossing mode into Gdk terms.
1253        */
1254       switch (xevent->xcrossing.mode)
1255         {
1256         case NotifyNormal:
1257           event->crossing.mode = GDK_CROSSING_NORMAL;
1258           break;
1259         case NotifyGrab:
1260           event->crossing.mode = GDK_CROSSING_GRAB;
1261           break;
1262         case NotifyUngrab:
1263           event->crossing.mode = GDK_CROSSING_UNGRAB;
1264           break;
1265         };
1266       
1267       /* Translate the crossing detail into Gdk terms.
1268        */
1269       switch (xevent->xcrossing.detail)
1270         {
1271         case NotifyInferior:
1272           event->crossing.detail = GDK_NOTIFY_INFERIOR;
1273           break;
1274         case NotifyAncestor:
1275           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
1276           break;
1277         case NotifyVirtual:
1278           event->crossing.detail = GDK_NOTIFY_VIRTUAL;
1279           break;
1280         case NotifyNonlinear:
1281           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
1282           break;
1283         case NotifyNonlinearVirtual:
1284           event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
1285           break;
1286         default:
1287           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
1288           break;
1289         }
1290       
1291       event->crossing.focus = xevent->xcrossing.focus;
1292       event->crossing.state = xevent->xcrossing.state;
1293   
1294       break;
1295       
1296     case LeaveNotify:
1297       GDK_NOTE (EVENTS, 
1298                 g_message ("leave notify:\t\twindow: %ld  detail: %d subwin: %ld",
1299                            xevent->xcrossing.window,
1300                            xevent->xcrossing.detail, xevent->xcrossing.subwindow));
1301
1302       if (window_private == NULL)
1303         {
1304           return_val = FALSE;
1305           break;
1306         }
1307       
1308       /* Handle focusing (in the case where no window manager is running */
1309       if (toplevel &&
1310           xevent->xcrossing.detail != NotifyInferior &&
1311           xevent->xcrossing.focus && !toplevel->has_focus_window)
1312         {
1313           gboolean had_focus = HAS_FOCUS (toplevel);
1314           
1315           toplevel->has_pointer_focus = FALSE;
1316           
1317           if (HAS_FOCUS (toplevel) != had_focus)
1318             generate_focus_event (window, FALSE);
1319         }
1320
1321       event->crossing.type = GDK_LEAVE_NOTIFY;
1322       event->crossing.window = window;
1323       
1324       /* If the subwindow field of the XEvent is non-NULL, then
1325        *  lookup the corresponding GdkWindow.
1326        */
1327       if (xevent->xcrossing.subwindow != None)
1328         event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
1329       else
1330         event->crossing.subwindow = NULL;
1331       
1332       event->crossing.time = xevent->xcrossing.time;
1333       event->crossing.x = xevent->xcrossing.x + xoffset;
1334       event->crossing.y = xevent->xcrossing.y + yoffset;
1335       event->crossing.x_root = xevent->xcrossing.x_root;
1336       event->crossing.y_root = xevent->xcrossing.y_root;
1337       
1338       set_screen_from_root (display, event, xevent->xcrossing.root);
1339       
1340       /* Translate the crossing mode into Gdk terms.
1341        */
1342       switch (xevent->xcrossing.mode)
1343         {
1344         case NotifyNormal:
1345           event->crossing.mode = GDK_CROSSING_NORMAL;
1346           break;
1347         case NotifyGrab:
1348           event->crossing.mode = GDK_CROSSING_GRAB;
1349           break;
1350         case NotifyUngrab:
1351           event->crossing.mode = GDK_CROSSING_UNGRAB;
1352           break;
1353         };
1354       
1355       /* Translate the crossing detail into Gdk terms.
1356        */
1357       switch (xevent->xcrossing.detail)
1358         {
1359         case NotifyInferior:
1360           event->crossing.detail = GDK_NOTIFY_INFERIOR;
1361           break;
1362         case NotifyAncestor:
1363           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
1364           break;
1365         case NotifyVirtual:
1366           event->crossing.detail = GDK_NOTIFY_VIRTUAL;
1367           break;
1368         case NotifyNonlinear:
1369           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
1370           break;
1371         case NotifyNonlinearVirtual:
1372           event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
1373           break;
1374         default:
1375           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
1376           break;
1377         }
1378       
1379       event->crossing.focus = xevent->xcrossing.focus;
1380       event->crossing.state = xevent->xcrossing.state;
1381       
1382       break;
1383       
1384       /* We only care about focus events that indicate that _this_
1385        * window (not a ancestor or child) got or lost the focus
1386        */
1387     case FocusIn:
1388       GDK_NOTE (EVENTS,
1389                 g_message ("focus in:\t\twindow: %ld, detail: %s, mode: %s",
1390                            xevent->xfocus.window,
1391                            notify_details[xevent->xfocus.detail],
1392                            notify_modes[xevent->xfocus.mode]));
1393       
1394       if (toplevel)
1395         {
1396           gboolean had_focus = HAS_FOCUS (toplevel);
1397           
1398           switch (xevent->xfocus.detail)
1399             {
1400             case NotifyAncestor:
1401             case NotifyNonlinear:
1402             case NotifyVirtual:
1403             case NotifyNonlinearVirtual:
1404               toplevel->has_focus_window = TRUE;
1405               /* We pretend that the focus moves to the grab
1406                * window, so we pay attention to NotifyGrab
1407                * NotifyUngrab, and ignore NotifyWhileGrabbed
1408                */
1409               if (xevent->xfocus.mode != NotifyWhileGrabbed)
1410                 toplevel->has_focus = TRUE;
1411               break;
1412             case NotifyPointer:
1413               /* The X server sends NotifyPointer/NotifyGrab,
1414                * but the pointer focus is ignored while a
1415                * grab is in effect
1416                */
1417               if (xevent->xfocus.mode != NotifyGrab)
1418                 toplevel->has_pointer_focus = TRUE;
1419               break;
1420             case NotifyInferior:
1421             case NotifyPointerRoot:
1422             case NotifyDetailNone:
1423               break;
1424             }
1425
1426           if (HAS_FOCUS (toplevel) != had_focus)
1427             generate_focus_event (window, TRUE);
1428         }
1429       break;
1430     case FocusOut:
1431       GDK_NOTE (EVENTS,
1432                 g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
1433                            xevent->xfocus.window,
1434                            notify_details[xevent->xfocus.detail],
1435                            notify_modes[xevent->xfocus.mode]));
1436       
1437       if (toplevel)
1438         {
1439           gboolean had_focus = HAS_FOCUS (toplevel);
1440             
1441           switch (xevent->xfocus.detail)
1442             {
1443             case NotifyAncestor:
1444             case NotifyNonlinear:
1445             case NotifyVirtual:
1446             case NotifyNonlinearVirtual:
1447               toplevel->has_focus_window = FALSE;
1448               if (xevent->xfocus.mode != NotifyWhileGrabbed)
1449                 toplevel->has_focus = FALSE;
1450               break;
1451             case NotifyPointer:
1452               if (xevent->xfocus.mode != NotifyUngrab)
1453                 toplevel->has_pointer_focus = FALSE;
1454             break;
1455             case NotifyInferior:
1456             case NotifyPointerRoot:
1457             case NotifyDetailNone:
1458               break;
1459             }
1460
1461           if (HAS_FOCUS (toplevel) != had_focus)
1462             generate_focus_event (window, FALSE);
1463         }
1464       break;
1465
1466 #if 0      
1467           /* gdk_keyboard_grab() causes following events. These events confuse
1468            * the XIM focus, so ignore them.
1469            */
1470           if (xevent->xfocus.mode == NotifyGrab ||
1471               xevent->xfocus.mode == NotifyUngrab)
1472             break;
1473 #endif
1474
1475     case KeymapNotify:
1476       GDK_NOTE (EVENTS,
1477                 g_message ("keymap notify"));
1478
1479       /* Not currently handled */
1480       return_val = FALSE;
1481       break;
1482       
1483     case Expose:
1484       GDK_NOTE (EVENTS,
1485                 g_message ("expose:\t\twindow: %ld  %d  x,y: %d %d  w,h: %d %d%s",
1486                            xevent->xexpose.window, xevent->xexpose.count,
1487                            xevent->xexpose.x, xevent->xexpose.y,
1488                            xevent->xexpose.width, xevent->xexpose.height,
1489                            event->any.send_event ? " (send)" : ""));
1490       
1491       if (window_private == NULL)
1492         {
1493           return_val = FALSE;
1494           break;
1495         }
1496       
1497       {
1498         GdkRectangle expose_rect;
1499
1500         expose_rect.x = xevent->xexpose.x + xoffset;
1501         expose_rect.y = xevent->xexpose.y + yoffset;
1502         expose_rect.width = xevent->xexpose.width;
1503         expose_rect.height = xevent->xexpose.height;
1504
1505         if (return_exposes)
1506           {
1507             event->expose.type = GDK_EXPOSE;
1508             event->expose.area = expose_rect;
1509             event->expose.region = gdk_region_rectangle (&expose_rect);
1510             event->expose.window = window;
1511             event->expose.count = xevent->xexpose.count;
1512
1513             return_val = TRUE;
1514           }
1515         else
1516           {
1517             _gdk_window_process_expose (window, xevent->xexpose.serial, &expose_rect);
1518             return_val = FALSE;
1519           }
1520         
1521         return_val = FALSE;
1522       }
1523         
1524       break;
1525       
1526     case GraphicsExpose:
1527       {
1528         GdkRectangle expose_rect;
1529
1530         GDK_NOTE (EVENTS,
1531                   g_message ("graphics expose:\tdrawable: %ld",
1532                              xevent->xgraphicsexpose.drawable));
1533  
1534         if (window_private == NULL)
1535           {
1536             return_val = FALSE;
1537             break;
1538           }
1539         
1540         expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
1541         expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
1542         expose_rect.width = xevent->xgraphicsexpose.width;
1543         expose_rect.height = xevent->xgraphicsexpose.height;
1544             
1545         if (return_exposes)
1546           {
1547             event->expose.type = GDK_EXPOSE;
1548             event->expose.area = expose_rect;
1549             event->expose.region = gdk_region_rectangle (&expose_rect);
1550             event->expose.window = window;
1551             event->expose.count = xevent->xgraphicsexpose.count;
1552
1553             return_val = TRUE;
1554           }
1555         else
1556           {
1557             _gdk_window_process_expose (window, xevent->xgraphicsexpose.serial, &expose_rect);
1558             
1559             return_val = FALSE;
1560           }
1561         
1562       }
1563       break;
1564       
1565     case NoExpose:
1566       GDK_NOTE (EVENTS,
1567                 g_message ("no expose:\t\tdrawable: %ld",
1568                            xevent->xnoexpose.drawable));
1569       
1570       event->no_expose.type = GDK_NO_EXPOSE;
1571       event->no_expose.window = window;
1572       
1573       break;
1574       
1575     case VisibilityNotify:
1576 #ifdef G_ENABLE_DEBUG
1577       if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
1578         switch (xevent->xvisibility.state)
1579           {
1580           case VisibilityFullyObscured:
1581             g_message ("visibility notify:\twindow: %ld  none",
1582                        xevent->xvisibility.window);
1583             break;
1584           case VisibilityPartiallyObscured:
1585             g_message ("visibility notify:\twindow: %ld  partial",
1586                        xevent->xvisibility.window);
1587             break;
1588           case VisibilityUnobscured:
1589             g_message ("visibility notify:\twindow: %ld  full",
1590                        xevent->xvisibility.window);
1591             break;
1592           }
1593 #endif /* G_ENABLE_DEBUG */
1594       
1595       if (window_private == NULL)
1596         {
1597           return_val = FALSE;
1598           break;
1599         }
1600       
1601       event->visibility.type = GDK_VISIBILITY_NOTIFY;
1602       event->visibility.window = window;
1603       
1604       switch (xevent->xvisibility.state)
1605         {
1606         case VisibilityFullyObscured:
1607           event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
1608           break;
1609           
1610         case VisibilityPartiallyObscured:
1611           event->visibility.state = GDK_VISIBILITY_PARTIAL;
1612           break;
1613           
1614         case VisibilityUnobscured:
1615           event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
1616           break;
1617         }
1618       
1619       break;
1620       
1621     case CreateNotify:
1622       GDK_NOTE (EVENTS,
1623                 g_message ("create notify:\twindow: %ld  x,y: %d %d     w,h: %d %d  b-w: %d  parent: %ld         ovr: %d",
1624                            xevent->xcreatewindow.window,
1625                            xevent->xcreatewindow.x,
1626                            xevent->xcreatewindow.y,
1627                            xevent->xcreatewindow.width,
1628                            xevent->xcreatewindow.height,
1629                            xevent->xcreatewindow.border_width,
1630                            xevent->xcreatewindow.parent,
1631                            xevent->xcreatewindow.override_redirect));
1632       /* not really handled */
1633       break;
1634       
1635     case DestroyNotify:
1636       GDK_NOTE (EVENTS,
1637                 g_message ("destroy notify:\twindow: %ld",
1638                            xevent->xdestroywindow.window));
1639
1640       /* Ignore DestroyNotify from SubstructureNotifyMask */
1641       if (xevent->xdestroywindow.window == xevent->xdestroywindow.event)
1642         {
1643           event->any.type = GDK_DESTROY;
1644           event->any.window = window;
1645           
1646           return_val = window_private && !GDK_WINDOW_DESTROYED (window);
1647           
1648           if (window && GDK_WINDOW_XID (window) != screen_x11->xroot_window)
1649             gdk_window_destroy_notify (window);
1650         }
1651       else
1652         return_val = FALSE;
1653       
1654       break;
1655       
1656     case UnmapNotify:
1657       GDK_NOTE (EVENTS,
1658                 g_message ("unmap notify:\t\twindow: %ld",
1659                            xevent->xmap.window));
1660       
1661       event->any.type = GDK_UNMAP;
1662       event->any.window = window;      
1663
1664       /* If we are shown (not withdrawn) and get an unmap, it means we
1665        * were iconified in the X sense. If we are withdrawn, and get
1666        * an unmap, it means we hid the window ourselves, so we
1667        * will have already flipped the iconified bit off.
1668        */
1669       if (window)
1670         {
1671           if (GDK_WINDOW_IS_MAPPED (window))
1672             gdk_synthesize_window_state (window,
1673                                          0,
1674                                          GDK_WINDOW_STATE_ICONIFIED);
1675
1676           _gdk_xgrab_check_unmap (window, xevent->xany.serial);
1677         }
1678       
1679       break;
1680       
1681     case MapNotify:
1682       GDK_NOTE (EVENTS,
1683                 g_message ("map notify:\t\twindow: %ld",
1684                            xevent->xmap.window));
1685       
1686       event->any.type = GDK_MAP;
1687       event->any.window = window;
1688
1689       /* Unset iconified if it was set */
1690       if (window && (((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_ICONIFIED))
1691         gdk_synthesize_window_state (window,
1692                                      GDK_WINDOW_STATE_ICONIFIED,
1693                                      0);
1694       
1695       break;
1696       
1697     case ReparentNotify:
1698       GDK_NOTE (EVENTS,
1699                 g_message ("reparent notify:\twindow: %ld  x,y: %d %d  parent: %ld      ovr: %d",
1700                            xevent->xreparent.window,
1701                            xevent->xreparent.x,
1702                            xevent->xreparent.y,
1703                            xevent->xreparent.parent,
1704                            xevent->xreparent.override_redirect));
1705
1706       /* Not currently handled */
1707       return_val = FALSE;
1708       break;
1709       
1710     case ConfigureNotify:
1711       GDK_NOTE (EVENTS,
1712                 g_message ("configure notify:\twindow: %ld  x,y: %d %d  w,h: %d %d  b-w: %d  above: %ld  ovr: %d%s",
1713                            xevent->xconfigure.window,
1714                            xevent->xconfigure.x,
1715                            xevent->xconfigure.y,
1716                            xevent->xconfigure.width,
1717                            xevent->xconfigure.height,
1718                            xevent->xconfigure.border_width,
1719                            xevent->xconfigure.above,
1720                            xevent->xconfigure.override_redirect,
1721                            !window
1722                            ? " (discarding)"
1723                            : GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD
1724                            ? " (discarding child)"
1725                            : xevent->xconfigure.event != xevent->xconfigure.window
1726                            ? " (discarding substructure)"
1727                            : ""));
1728       if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
1729         _gdk_x11_screen_size_changed (screen, xevent);
1730
1731       if (window &&
1732           xevent->xconfigure.event == xevent->xconfigure.window &&
1733           !GDK_WINDOW_DESTROYED (window) &&
1734           (window_private->extension_events != 0))
1735         _gdk_input_configure_event (&xevent->xconfigure, window);
1736       
1737 #ifdef HAVE_XSYNC
1738       if (toplevel && display_x11->use_sync && !XSyncValueIsZero (toplevel->pending_counter_value))
1739         {
1740           toplevel->current_counter_value = toplevel->pending_counter_value;
1741           XSyncIntToValue (&toplevel->pending_counter_value, 0);
1742         }
1743 #endif
1744
1745     if (!window ||
1746           xevent->xconfigure.event != xevent->xconfigure.window ||
1747           GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
1748           GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
1749         return_val = FALSE;
1750       else
1751         {
1752           event->configure.type = GDK_CONFIGURE;
1753           event->configure.window = window;
1754           event->configure.width = xevent->xconfigure.width;
1755           event->configure.height = xevent->xconfigure.height;
1756           
1757           if (!xevent->xconfigure.send_event &&
1758               !xevent->xconfigure.override_redirect &&
1759               !GDK_WINDOW_DESTROYED (window))
1760             {
1761               gint tx = 0;
1762               gint ty = 0;
1763               Window child_window = 0;
1764
1765               gdk_error_trap_push ();
1766               if (XTranslateCoordinates (GDK_DRAWABLE_XDISPLAY (window),
1767                                          GDK_DRAWABLE_XID (window),
1768                                          screen_x11->xroot_window,
1769                                          0, 0,
1770                                          &tx, &ty,
1771                                          &child_window))
1772                 {
1773                   event->configure.x = tx;
1774                   event->configure.y = ty;
1775                 }
1776               gdk_error_trap_pop ();
1777             }
1778           else
1779             {
1780               event->configure.x = xevent->xconfigure.x;
1781               event->configure.y = xevent->xconfigure.y;
1782             }
1783           window_private->x = event->configure.x;
1784           window_private->y = event->configure.y;
1785           window_impl->width = xevent->xconfigure.width;
1786           window_impl->height = xevent->xconfigure.height;
1787           if (window_private->resize_count >= 1)
1788             {
1789               window_private->resize_count -= 1;
1790
1791               if (window_private->resize_count == 0)
1792                 _gdk_moveresize_configure_done (display, window);
1793             }
1794         }
1795       break;
1796       
1797     case PropertyNotify:
1798       GDK_NOTE (EVENTS,
1799                 g_message ("property notify:\twindow: %ld, atom(%ld): %s%s%s",
1800                            xevent->xproperty.window,
1801                            xevent->xproperty.atom,
1802                            "\"",
1803                            gdk_x11_get_xatom_name_for_display (display, xevent->xproperty.atom),
1804                            "\""));
1805
1806       if (window_private == NULL)
1807         {
1808           return_val = FALSE;
1809           break;
1810         }
1811
1812       /* We compare with the serial of the last time we mapped the
1813        * window to avoid refetching properties that we set ourselves
1814        */
1815       if (toplevel &&
1816           xevent->xproperty.serial >= toplevel->map_serial)
1817         {
1818           if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"))
1819             gdk_check_wm_state_changed (window);
1820           
1821           if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"))
1822             gdk_check_wm_desktop_changed (window);
1823         }
1824       
1825       if (window_private->event_mask & GDK_PROPERTY_CHANGE_MASK) 
1826         {
1827           event->property.type = GDK_PROPERTY_NOTIFY;
1828           event->property.window = window;
1829           event->property.atom = gdk_x11_xatom_to_atom_for_display (display, xevent->xproperty.atom);
1830           event->property.time = xevent->xproperty.time;
1831           event->property.state = xevent->xproperty.state;
1832         }
1833       else
1834         return_val = FALSE;
1835
1836       break;
1837       
1838     case SelectionClear:
1839       GDK_NOTE (EVENTS,
1840                 g_message ("selection clear:\twindow: %ld",
1841                            xevent->xproperty.window));
1842
1843       if (_gdk_selection_filter_clear_event (&xevent->xselectionclear))
1844         {
1845           event->selection.type = GDK_SELECTION_CLEAR;
1846           event->selection.window = window;
1847           event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionclear.selection);
1848           event->selection.time = xevent->xselectionclear.time;
1849         }
1850       else
1851         return_val = FALSE;
1852           
1853       break;
1854       
1855     case SelectionRequest:
1856       GDK_NOTE (EVENTS,
1857                 g_message ("selection request:\twindow: %ld",
1858                            xevent->xproperty.window));
1859       
1860       event->selection.type = GDK_SELECTION_REQUEST;
1861       event->selection.window = window;
1862       event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.selection);
1863       event->selection.target = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.target);
1864       event->selection.property = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.property);
1865       event->selection.requestor = xevent->xselectionrequest.requestor;
1866       event->selection.time = xevent->xselectionrequest.time;
1867       
1868       break;
1869       
1870     case SelectionNotify:
1871       GDK_NOTE (EVENTS,
1872                 g_message ("selection notify:\twindow: %ld",
1873                            xevent->xproperty.window));
1874       
1875       
1876       event->selection.type = GDK_SELECTION_NOTIFY;
1877       event->selection.window = window;
1878       event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.selection);
1879       event->selection.target = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.target);
1880       event->selection.property = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.property);
1881       event->selection.time = xevent->xselection.time;
1882       
1883       break;
1884       
1885     case ColormapNotify:
1886       GDK_NOTE (EVENTS,
1887                 g_message ("colormap notify:\twindow: %ld",
1888                            xevent->xcolormap.window));
1889       
1890       /* Not currently handled */
1891       return_val = FALSE;
1892       break;
1893       
1894     case ClientMessage:
1895       {
1896         GList *tmp_list;
1897         GdkFilterReturn result = GDK_FILTER_CONTINUE;
1898         GdkAtom message_type = gdk_x11_xatom_to_atom_for_display (display, xevent->xclient.message_type);
1899
1900         GDK_NOTE (EVENTS,
1901                   g_message ("client message:\twindow: %ld",
1902                              xevent->xclient.window));
1903         
1904         tmp_list = display_x11->client_filters;
1905         while (tmp_list)
1906           {
1907             GdkClientFilter *filter = tmp_list->data;
1908             tmp_list = tmp_list->next;
1909             
1910             if (filter->type == message_type)
1911               {
1912                 result = (*filter->function) (xevent, event, filter->data);
1913                 if (result != GDK_FILTER_CONTINUE)
1914                   break;
1915               }
1916           }
1917
1918         switch (result)
1919           {
1920           case GDK_FILTER_REMOVE:
1921             return_val = FALSE;
1922             break;
1923           case GDK_FILTER_TRANSLATE:
1924             return_val = TRUE;
1925             break;
1926           case GDK_FILTER_CONTINUE:
1927             /* Send unknown ClientMessage's on to Gtk for it to use */
1928             if (window_private == NULL)
1929               {
1930                 return_val = FALSE;
1931               }
1932             else
1933               {
1934                 event->client.type = GDK_CLIENT_EVENT;
1935                 event->client.window = window;
1936                 event->client.message_type = message_type;
1937                 event->client.data_format = xevent->xclient.format;
1938                 memcpy(&event->client.data, &xevent->xclient.data,
1939                        sizeof(event->client.data));
1940               }
1941             break;
1942           }
1943       }
1944       
1945       break;
1946       
1947     case MappingNotify:
1948       GDK_NOTE (EVENTS,
1949                 g_message ("mapping notify"));
1950       
1951       /* Let XLib know that there is a new keyboard mapping.
1952        */
1953       XRefreshKeyboardMapping (&xevent->xmapping);
1954       _gdk_keymap_keys_changed (display);
1955       return_val = FALSE;
1956       break;
1957
1958     default:
1959 #ifdef HAVE_XKB
1960       if (xevent->type == display_x11->xkb_event_type)
1961         {
1962           XkbEvent *xkb_event = (XkbEvent *)xevent;
1963
1964           switch (xkb_event->any.xkb_type)
1965             {
1966             case XkbNewKeyboardNotify:
1967             case XkbMapNotify:
1968               _gdk_keymap_keys_changed (display);
1969
1970               return_val = FALSE;
1971               break;
1972               
1973             case XkbStateNotify:
1974               _gdk_keymap_state_changed (display);
1975               break;
1976             }
1977         }
1978       else
1979 #endif
1980 #ifdef HAVE_XFIXES
1981       if (xevent->type - display_x11->xfixes_event_base == XFixesSelectionNotify)
1982         {
1983           XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)xevent;
1984           event->owner_change.type = GDK_OWNER_CHANGE;
1985           event->owner_change.window = window;
1986           event->owner_change.owner = selection_notify->owner;
1987           event->owner_change.reason = selection_notify->subtype;
1988           event->owner_change.selection = 
1989             gdk_x11_xatom_to_atom_for_display (display, 
1990                                                selection_notify->selection);
1991           event->owner_change.time = selection_notify->timestamp;
1992           event->owner_change.selection_time = selection_notify->selection_timestamp;
1993
1994           return_val = TRUE;
1995         }
1996       else
1997 #endif
1998         {
1999           /* something else - (e.g., a Xinput event) */
2000           
2001           if (window_private &&
2002               !GDK_WINDOW_DESTROYED (window_private) &&
2003               (window_private->extension_events != 0))
2004             return_val = _gdk_input_other_event(event, xevent, window);
2005           else
2006             return_val = FALSE;
2007           
2008           break;
2009         }
2010     }
2011
2012  done:
2013   if (return_val)
2014     {
2015       if (event->any.window)
2016         g_object_ref (event->any.window);
2017       if (((event->any.type == GDK_ENTER_NOTIFY) ||
2018            (event->any.type == GDK_LEAVE_NOTIFY)) &&
2019           (event->crossing.subwindow != NULL))
2020         g_object_ref (event->crossing.subwindow);
2021     }
2022   else
2023     {
2024       /* Mark this event as having no resources to be freed */
2025       event->any.window = NULL;
2026       event->any.type = GDK_NOTHING;
2027     }
2028   
2029   if (window)
2030     g_object_unref (window);
2031   
2032   return return_val;
2033 }
2034
2035 static GdkFilterReturn
2036 gdk_wm_protocols_filter (GdkXEvent *xev,
2037                          GdkEvent  *event,
2038                          gpointer data)
2039 {
2040   XEvent *xevent = (XEvent *)xev;
2041   GdkWindow *win = event->any.window;
2042   GdkDisplay *display;
2043   Atom atom;
2044
2045   if (!win)
2046       return GDK_FILTER_REMOVE;    
2047
2048   display = GDK_WINDOW_DISPLAY (win);
2049   atom = (Atom)xevent->xclient.data.l[0];
2050
2051   if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
2052     {
2053   /* The delete window request specifies a window
2054    *  to delete. We don't actually destroy the
2055    *  window because "it is only a request". (The
2056    *  window might contain vital data that the
2057    *  program does not want destroyed). Instead
2058    *  the event is passed along to the program,
2059    *  which should then destroy the window.
2060    */
2061       GDK_NOTE (EVENTS,
2062                 g_message ("delete window:\t\twindow: %ld",
2063                            xevent->xclient.window));
2064       
2065       event->any.type = GDK_DELETE;
2066
2067       return GDK_FILTER_TRANSLATE;
2068     }
2069   else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"))
2070     {
2071       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window);
2072       GdkWindowObject *private = (GdkWindowObject *)win;
2073
2074       /* There is no way of knowing reliably whether we are viewable;
2075        * _gdk_x11_set_input_focus_safe() traps errors asynchronously.
2076        */
2077       if (toplevel && private->accept_focus)
2078         _gdk_x11_set_input_focus_safe (display, toplevel->focus_window,
2079                                        RevertToParent,
2080                                        xevent->xclient.data.l[1]);
2081
2082       return GDK_FILTER_REMOVE;
2083     }
2084   else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING") &&
2085            !_gdk_x11_display_is_root_window (display,
2086                                              xevent->xclient.window))
2087     {
2088       XEvent xev = *xevent;
2089       
2090       xev.xclient.window = GDK_WINDOW_XROOTWIN (win);
2091       XSendEvent (GDK_WINDOW_XDISPLAY (win), 
2092                   xev.xclient.window,
2093                   False, 
2094                   SubstructureRedirectMask | SubstructureNotifyMask, &xev);
2095
2096       return GDK_FILTER_REMOVE;
2097     }
2098   else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST") &&
2099            GDK_DISPLAY_X11 (display)->use_sync)
2100     {
2101       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window);
2102       if (toplevel)
2103         {
2104 #ifdef HAVE_XSYNC
2105           XSyncIntsToValue (&toplevel->pending_counter_value, 
2106                             xevent->xclient.data.l[2], 
2107                             xevent->xclient.data.l[3]);
2108 #endif
2109         }
2110       return GDK_FILTER_REMOVE;
2111     }
2112   
2113   return GDK_FILTER_CONTINUE;
2114 }
2115
2116 void
2117 _gdk_events_queue (GdkDisplay *display)
2118 {
2119   GList *node;
2120   GdkEvent *event;
2121   XEvent xevent;
2122   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
2123
2124   while (!_gdk_event_queue_find_first(display) && XPending (xdisplay))
2125     {
2126       XNextEvent (xdisplay, &xevent);
2127
2128       switch (xevent.type)
2129         {
2130         case KeyPress:
2131         case KeyRelease:
2132           break;
2133         default:
2134           if (XFilterEvent (&xevent, None))
2135             continue;
2136         }
2137       
2138       event = gdk_event_new (GDK_NOTHING);
2139       
2140       event->any.window = NULL;
2141       event->any.send_event = xevent.xany.send_event ? TRUE : FALSE;
2142
2143       ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
2144
2145       node = _gdk_event_queue_append (display, event);
2146
2147       if (gdk_event_translate (display, event, &xevent, FALSE))
2148         {
2149           ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
2150         }
2151       else
2152         {
2153           _gdk_event_queue_remove_link (display, node);
2154           g_list_free_1 (node);
2155           gdk_event_free (event);
2156         }
2157     }
2158 }
2159
2160 static gboolean  
2161 gdk_event_prepare (GSource  *source,
2162                    gint     *timeout)
2163 {
2164   GdkDisplay *display = ((GdkDisplaySource*)source)->display;
2165   gboolean retval;
2166   
2167   GDK_THREADS_ENTER ();
2168
2169   *timeout = -1;
2170   retval = (_gdk_event_queue_find_first (display) != NULL || 
2171             gdk_check_xpending (display));
2172   
2173   GDK_THREADS_LEAVE ();
2174
2175   return retval;
2176 }
2177
2178 static gboolean  
2179 gdk_event_check (GSource *source) 
2180 {
2181   GdkDisplaySource *display_source = (GdkDisplaySource*)source;
2182   gboolean retval;
2183
2184   GDK_THREADS_ENTER ();
2185
2186   if (display_source->event_poll_fd.revents & G_IO_IN)
2187     retval = (_gdk_event_queue_find_first (display_source->display) != NULL || 
2188               gdk_check_xpending (display_source->display));
2189   else
2190     retval = FALSE;
2191
2192   GDK_THREADS_LEAVE ();
2193
2194   return retval;
2195 }
2196
2197 static gboolean  
2198 gdk_event_dispatch (GSource    *source,
2199                     GSourceFunc callback,
2200                     gpointer    user_data)
2201 {
2202   GdkDisplay *display = ((GdkDisplaySource*)source)->display;
2203   GdkEvent *event;
2204  
2205   GDK_THREADS_ENTER ();
2206
2207   _gdk_events_queue (display);
2208   event = _gdk_event_unqueue (display);
2209
2210   if (event)
2211     {
2212       if (_gdk_event_func)
2213         (*_gdk_event_func) (event, _gdk_event_data);
2214       
2215       gdk_event_free (event);
2216     }
2217   
2218   GDK_THREADS_LEAVE ();
2219
2220   return TRUE;
2221 }
2222
2223 /**
2224  * gdk_event_send_client_message_for_display:
2225  * @display: the #GdkDisplay for the window where the message is to be sent.
2226  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
2227  * @winid: the window to send the client message to.
2228  *
2229  * On X11, sends an X ClientMessage event to a given window. On
2230  * Windows, sends a message registered with the name
2231  * GDK_WIN32_CLIENT_MESSAGE.
2232  *
2233  * This could be used for communicating between different
2234  * applications, though the amount of data is limited to 20 bytes on
2235  * X11, and to just four bytes on Windows.
2236  *
2237  * Returns: non-zero on success.
2238  *
2239  * Since: 2.2
2240  */
2241 gboolean
2242 gdk_event_send_client_message_for_display (GdkDisplay     *display,
2243                                            GdkEvent       *event,
2244                                            GdkNativeWindow winid)
2245 {
2246   XEvent sev;
2247   
2248   g_return_val_if_fail(event != NULL, FALSE);
2249
2250   /* Set up our event to send, with the exception of its target window */
2251   sev.xclient.type = ClientMessage;
2252   sev.xclient.display = GDK_DISPLAY_XDISPLAY (display);
2253   sev.xclient.format = event->client.data_format;
2254   sev.xclient.window = winid;
2255   memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data));
2256   sev.xclient.message_type = gdk_x11_atom_to_xatom_for_display (display, event->client.message_type);
2257   
2258   return _gdk_send_xevent (display, winid, False, NoEventMask, &sev);
2259 }
2260
2261
2262
2263 /* Sends a ClientMessage to all toplevel client windows */
2264 static gboolean
2265 gdk_event_send_client_message_to_all_recurse (GdkDisplay *display,
2266                                               XEvent     *xev, 
2267                                               guint32     xid,
2268                                               guint       level)
2269 {
2270   Atom type = None;
2271   int format;
2272   unsigned long nitems, after;
2273   unsigned char *data;
2274   Window *ret_children, ret_root, ret_parent;
2275   unsigned int ret_nchildren;
2276   gboolean send = FALSE;
2277   gboolean found = FALSE;
2278   gboolean result = FALSE;
2279   int i;
2280   
2281   gdk_error_trap_push ();
2282   
2283   if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xid, 
2284                           gdk_x11_get_xatom_by_name_for_display (display, "WM_STATE"),
2285                           0, 0, False, AnyPropertyType,
2286                           &type, &format, &nitems, &after, &data) != Success)
2287     goto out;
2288   
2289   if (type)
2290     {
2291       send = TRUE;
2292       XFree (data);
2293     }
2294   else
2295     {
2296       /* OK, we're all set, now let's find some windows to send this to */
2297       if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xid,
2298                       &ret_root, &ret_parent,
2299                       &ret_children, &ret_nchildren))   
2300         goto out;
2301
2302       for(i = 0; i < ret_nchildren; i++)
2303         if (gdk_event_send_client_message_to_all_recurse (display, xev, ret_children[i], level + 1))
2304           found = TRUE;
2305
2306       XFree (ret_children);
2307     }
2308
2309   if (send || (!found && (level == 1)))
2310     {
2311       xev->xclient.window = xid;
2312       _gdk_send_xevent (display, xid, False, NoEventMask, xev);
2313     }
2314
2315   result = send || found;
2316
2317  out:
2318   gdk_error_trap_pop ();
2319
2320   return result;
2321 }
2322
2323 /**
2324  * gdk_screen_broadcast_client_message:
2325  * @screen: the #GdkScreen where the event will be broadcasted.
2326  * @event: the #GdkEvent.
2327  *
2328  * On X11, sends an X ClientMessage event to all toplevel windows on
2329  * @screen. 
2330  *
2331  * Toplevel windows are determined by checking for the WM_STATE property, 
2332  * as described in the Inter-Client Communication Conventions Manual (ICCCM).
2333  * If no windows are found with the WM_STATE property set, the message is 
2334  * sent to all children of the root window.
2335  *
2336  * On Windows, broadcasts a message registered with the name
2337  * GDK_WIN32_CLIENT_MESSAGE to all top-level windows. The amount of
2338  * data is limited to one long, i.e. four bytes.
2339  *
2340  * Since: 2.2
2341  */
2342
2343 void
2344 gdk_screen_broadcast_client_message (GdkScreen *screen, 
2345                                      GdkEvent  *event)
2346 {
2347   XEvent sev;
2348   GdkWindow *root_window;
2349
2350   g_return_if_fail (event != NULL);
2351   
2352   root_window = gdk_screen_get_root_window (screen);
2353   
2354   /* Set up our event to send, with the exception of its target window */
2355   sev.xclient.type = ClientMessage;
2356   sev.xclient.display = GDK_WINDOW_XDISPLAY (root_window);
2357   sev.xclient.format = event->client.data_format;
2358   memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data));
2359   sev.xclient.message_type = 
2360     gdk_x11_atom_to_xatom_for_display (GDK_WINDOW_DISPLAY (root_window),
2361                                        event->client.message_type);
2362
2363   gdk_event_send_client_message_to_all_recurse (gdk_screen_get_display (screen),
2364                                                 &sev, 
2365                                                 GDK_WINDOW_XID (root_window), 
2366                                                 0);
2367 }
2368
2369 /*
2370  *--------------------------------------------------------------
2371  * gdk_flush
2372  *
2373  *   Flushes the Xlib output buffer and then waits
2374  *   until all requests have been received and processed
2375  *   by the X server. The only real use for this function
2376  *   is in dealing with XShm.
2377  *
2378  * Arguments:
2379  *
2380  * Results:
2381  *
2382  * Side effects:
2383  *
2384  *--------------------------------------------------------------
2385  */
2386
2387 void
2388 gdk_flush (void)
2389 {
2390   GSList *tmp_list = _gdk_displays;
2391   
2392   while (tmp_list)
2393     {
2394       XSync (GDK_DISPLAY_XDISPLAY (tmp_list->data), False);
2395       tmp_list = tmp_list->next;
2396     }
2397 }
2398
2399 static Bool
2400 timestamp_predicate (Display *display,
2401                      XEvent  *xevent,
2402                      XPointer arg)
2403 {
2404   Window xwindow = GPOINTER_TO_UINT (arg);
2405   GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
2406
2407   if (xevent->type == PropertyNotify &&
2408       xevent->xproperty.window == xwindow &&
2409       xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
2410                                                                        "GDK_TIMESTAMP_PROP"))
2411     return True;
2412
2413   return False;
2414 }
2415
2416 /**
2417  * gdk_x11_get_server_time:
2418  * @window: a #GdkWindow, used for communication with the server.
2419  *          The window must have GDK_PROPERTY_CHANGE_MASK in its
2420  *          events mask or a hang will result.
2421  * 
2422  * Routine to get the current X server time stamp. 
2423  * 
2424  * Return value: the time stamp.
2425  **/
2426 guint32
2427 gdk_x11_get_server_time (GdkWindow *window)
2428 {
2429   Display *xdisplay;
2430   Window   xwindow;
2431   guchar c = 'a';
2432   XEvent xevent;
2433   Atom timestamp_prop_atom;
2434
2435   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
2436   g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
2437
2438   xdisplay = GDK_WINDOW_XDISPLAY (window);
2439   xwindow = GDK_WINDOW_XWINDOW (window);
2440   timestamp_prop_atom = 
2441     gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
2442                                            "GDK_TIMESTAMP_PROP");
2443   
2444   XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
2445                    timestamp_prop_atom,
2446                    8, PropModeReplace, &c, 1);
2447
2448   XIfEvent (xdisplay, &xevent,
2449             timestamp_predicate, GUINT_TO_POINTER(xwindow));
2450
2451   return xevent.xproperty.time;
2452 }
2453
2454 static void
2455 fetch_net_wm_check_window (GdkScreen *screen)
2456 {
2457   GdkScreenX11 *screen_x11;
2458   GdkDisplay *display;
2459   Atom type;
2460   gint format;
2461   gulong n_items;
2462   gulong bytes_after;
2463   Window *xwindow;
2464   
2465   /* This function is very slow on every call if you are not running a
2466    * spec-supporting WM. For now not optimized, because it isn't in
2467    * any critical code paths, but if you used it somewhere that had to
2468    * be fast you want to avoid "GTK is slow with old WMs" complaints.
2469    * Probably at that point the function should be changed to query
2470    * _NET_SUPPORTING_WM_CHECK only once every 10 seconds or something.
2471    */
2472   
2473   screen_x11 = GDK_SCREEN_X11 (screen);
2474   display = screen_x11->display;
2475   
2476   if (screen_x11->wmspec_check_window != None)
2477     return; /* already have it */
2478   
2479   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
2480                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTING_WM_CHECK"),
2481                       0, G_MAXLONG, False, XA_WINDOW, &type, &format, 
2482                       &n_items, &bytes_after, (guchar **) & xwindow);
2483   
2484   if (type != XA_WINDOW)
2485     return;
2486
2487   gdk_error_trap_push ();
2488   
2489   /* Find out if this WM goes away, so we can reset everything. */
2490   XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask);
2491   gdk_display_sync (display);
2492
2493   if (gdk_error_trap_pop () == Success)
2494     {
2495       screen_x11->wmspec_check_window = *xwindow;
2496       XFree (xwindow);
2497       
2498       screen_x11->need_refetch_net_supported = TRUE;
2499       screen_x11->need_refetch_wm_name = TRUE;
2500       
2501       /* Careful, reentrancy */
2502       _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
2503     }
2504 }
2505
2506 /**
2507  * gdk_x11_screen_get_window_manager_name:
2508  * @screen: a #GdkScreen 
2509  * 
2510  * Returns the name of the window manager for @screen. 
2511  * 
2512  * Return value: the name of the window manager screen @screen, or 
2513  * "unknown" if the window manager is unknown. The string is owned by GDK
2514  * and should not be freed.
2515  *
2516  * Since: 2.2
2517  **/
2518 const char*
2519 gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
2520 {
2521   GdkScreenX11 *screen_x11;
2522
2523   screen_x11 = GDK_SCREEN_X11 (screen);
2524   
2525   fetch_net_wm_check_window (screen);
2526
2527   if (screen_x11->need_refetch_wm_name)
2528     {
2529       /* Get the name of the window manager */
2530       screen_x11->need_refetch_wm_name = FALSE;
2531
2532       g_free (screen_x11->window_manager_name);
2533       screen_x11->window_manager_name = g_strdup ("unknown");
2534       
2535       if (screen_x11->wmspec_check_window != None)
2536         {
2537           Atom type;
2538           gint format;
2539           gulong n_items;
2540           gulong bytes_after;
2541           guchar *name;
2542           
2543           name = NULL;
2544
2545           gdk_error_trap_push ();
2546           
2547           XGetWindowProperty (GDK_DISPLAY_XDISPLAY (screen_x11->display),
2548                               screen_x11->wmspec_check_window,
2549                               gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
2550                                                                      "_NET_WM_NAME"),
2551                               0, G_MAXLONG, False,
2552                               gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
2553                                                                      "UTF8_STRING"),
2554                               &type, &format, 
2555                               &n_items, &bytes_after,
2556                               (guchar **)&name);
2557           
2558           gdk_display_sync (screen_x11->display);
2559           
2560           gdk_error_trap_pop ();
2561           
2562           if (name != NULL)
2563             {
2564               g_free (screen_x11->window_manager_name);
2565               screen_x11->window_manager_name = g_strdup (name);
2566               XFree (name);
2567             }
2568         }
2569     }
2570   
2571   return GDK_SCREEN_X11 (screen)->window_manager_name;
2572 }
2573
2574 typedef struct _NetWmSupportedAtoms NetWmSupportedAtoms;
2575
2576 struct _NetWmSupportedAtoms
2577 {
2578   Atom *atoms;
2579   gulong n_atoms;
2580 };
2581
2582 /**
2583  * gdk_x11_screen_supports_net_wm_hint:
2584  * @screen: the relevant #GdkScreen.
2585  * @property: a property atom.
2586  * 
2587  * This function is specific to the X11 backend of GDK, and indicates
2588  * whether the window manager supports a certain hint from the
2589  * Extended Window Manager Hints Specification. You can find this
2590  * specification on 
2591  * <ulink url="http://www.freedesktop.org">http://www.freedesktop.org</ulink>.
2592  *
2593  * When using this function, keep in mind that the window manager
2594  * can change over time; so you shouldn't use this function in
2595  * a way that impacts persistent application state. A common bug
2596  * is that your application can start up before the window manager
2597  * does when the user logs in, and before the window manager starts
2598  * gdk_x11_screen_supports_net_wm_hint() will return %FALSE for every property.
2599  * You can monitor the window_manager_changed signal on #GdkScreen to detect
2600  * a window manager change.
2601  * 
2602  * Return value: %TRUE if the window manager supports @property
2603  *
2604  * Since: 2.2
2605  **/
2606 gboolean
2607 gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
2608                                      GdkAtom    property)
2609 {
2610   gulong i;
2611   GdkScreenX11 *screen_x11;
2612   NetWmSupportedAtoms *supported_atoms;
2613   GdkDisplay *display;
2614
2615   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
2616   
2617   screen_x11 = GDK_SCREEN_X11 (screen);
2618   display = screen_x11->display;
2619
2620   supported_atoms = g_object_get_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms");
2621   if (!supported_atoms)
2622     {
2623       supported_atoms = g_new0 (NetWmSupportedAtoms, 1);
2624       g_object_set_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms", supported_atoms);
2625     }
2626
2627   fetch_net_wm_check_window (screen);
2628
2629   if (screen_x11->wmspec_check_window == None)
2630     return FALSE;
2631   
2632   if (screen_x11->need_refetch_net_supported)
2633     {
2634       /* WM has changed since we last got the supported list,
2635        * refetch it.
2636        */
2637       Atom type;
2638       gint format;
2639       gulong bytes_after;
2640
2641       screen_x11->need_refetch_net_supported = FALSE;
2642       
2643       if (supported_atoms->atoms)
2644         XFree (supported_atoms->atoms);
2645       
2646       supported_atoms->atoms = NULL;
2647       supported_atoms->n_atoms = 0;
2648       
2649       XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
2650                           gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTED"),
2651                           0, G_MAXLONG, False, XA_ATOM, &type, &format, 
2652                           &supported_atoms->n_atoms, &bytes_after,
2653                           (guchar **)&supported_atoms->atoms);
2654       
2655       if (type != XA_ATOM)
2656         return FALSE;
2657     }
2658   
2659   if (supported_atoms->atoms == NULL)
2660     return FALSE;
2661   
2662   i = 0;
2663   while (i < supported_atoms->n_atoms)
2664     {
2665       if (supported_atoms->atoms[i] == gdk_x11_atom_to_xatom_for_display (display, property))
2666         return TRUE;
2667       
2668       ++i;
2669     }
2670   
2671   return FALSE;
2672 }
2673
2674 /**
2675  * gdk_net_wm_supports:
2676  * @property: a property atom.
2677  * 
2678  * This function is specific to the X11 backend of GDK, and indicates
2679  * whether the window manager for the default screen supports a certain
2680  * hint from the Extended Window Manager Hints Specification. See
2681  * gdk_x11_screen_supports_net_wm_hint() for complete details.
2682  * 
2683  * Return value: %TRUE if the window manager supports @property
2684  **/
2685 gboolean
2686 gdk_net_wm_supports (GdkAtom property)
2687 {
2688   return gdk_x11_screen_supports_net_wm_hint (gdk_screen_get_default (), property);
2689 }
2690
2691 static struct
2692 {
2693   const char *xsettings_name;
2694   const char *gdk_name;
2695 } settings_map[] = {
2696   { "Net/DoubleClickTime", "gtk-double-click-time" },
2697   { "Net/DoubleClickDistance", "gtk-double-click-distance" },
2698   { "Net/DndDragThreshold", "gtk-dnd-drag-threshold" },
2699   { "Net/CursorBlink", "gtk-cursor-blink" },
2700   { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
2701   { "Net/ThemeName", "gtk-theme-name" },
2702   { "Net/IconThemeName", "gtk-icon-theme-name" },
2703   { "Gtk/CanChangeAccels", "gtk-can-change-accels" },
2704   { "Gtk/ColorPalette", "gtk-color-palette" },
2705   { "Gtk/FontName", "gtk-font-name" },
2706   { "Gtk/IconSizes", "gtk-icon-sizes" },
2707   { "Gtk/KeyThemeName", "gtk-key-theme-name" },
2708   { "Gtk/ToolbarStyle", "gtk-toolbar-style" },
2709   { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
2710   { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
2711   { "Gtk/IMStatusStyle", "gtk-im-status-style" },
2712   { "Gtk/Modules", "gtk-modules" },
2713   { "Gtk/FileChooserBackend", "gtk-file-chooser-backend" },
2714   { "Gtk/ButtonImages", "gtk-button-images" },
2715   { "Gtk/MenuImages", "gtk-menu-images" },
2716   { "Gtk/MenuBarAccel", "gtk-menu-bar-accel" },
2717   { "Xft/Antialias", "gtk-xft-antialias" },
2718   { "Xft/Hinting", "gtk-xft-hinting" },
2719   { "Xft/HintStyle", "gtk-xft-hintstyle" },
2720   { "Xft/RGBA", "gtk-xft-rgba" },
2721   { "Xft/DPI", "gtk-xft-dpi" },
2722 };
2723
2724 static void
2725 gdk_xsettings_notify_cb (const char       *name,
2726                          XSettingsAction   action,
2727                          XSettingsSetting *setting,
2728                          void             *data)
2729 {
2730   GdkEvent new_event;
2731   GdkScreen *screen = data;
2732   GdkScreenX11 *screen_x11 = data;
2733   int i;
2734
2735   if (screen_x11->xsettings_in_init)
2736     return;
2737   
2738   new_event.type = GDK_SETTING;
2739   new_event.setting.window = gdk_screen_get_root_window (screen);
2740   new_event.setting.send_event = FALSE;
2741   new_event.setting.name = NULL;
2742
2743   for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
2744     if (strcmp (settings_map[i].xsettings_name, name) == 0)
2745       {
2746         new_event.setting.name = (char *)settings_map[i].gdk_name;
2747         break;
2748       }
2749   
2750   if (!new_event.setting.name)
2751     return;
2752   
2753   switch (action)
2754     {
2755     case XSETTINGS_ACTION_NEW:
2756       new_event.setting.action = GDK_SETTING_ACTION_NEW;
2757       break;
2758     case XSETTINGS_ACTION_CHANGED:
2759       new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
2760       break;
2761     case XSETTINGS_ACTION_DELETED:
2762       new_event.setting.action = GDK_SETTING_ACTION_DELETED;
2763       break;
2764     }
2765
2766   gdk_event_put (&new_event);
2767 }
2768
2769 static gboolean
2770 check_transform (const gchar *xsettings_name,
2771                  GType        src_type,
2772                  GType        dest_type)
2773 {
2774   if (!g_value_type_transformable (src_type, dest_type))
2775     {
2776       g_warning ("Cannot tranform xsetting %s of type %s to type %s\n",
2777                  xsettings_name,
2778                  g_type_name (src_type),
2779                  g_type_name (dest_type));
2780       return FALSE;
2781     }
2782   else
2783     return TRUE;
2784 }
2785
2786 /**
2787  * gdk_screen_get_setting:
2788  * @screen: the #GdkScreen where the setting is located
2789  * @name: the name of the setting
2790  * @value: location to store the value of the setting
2791  *
2792  * Retrieves a desktop-wide setting such as double-click time
2793  * for the #GdkScreen @screen. 
2794  *
2795  * FIXME needs a list of valid settings here, or a link to 
2796  * more information.
2797  * 
2798  * Returns: %TRUE if the setting existed and a value was stored
2799  *   in @value, %FALSE otherwise.
2800  *
2801  * Since: 2.2
2802  **/
2803 gboolean
2804 gdk_screen_get_setting (GdkScreen   *screen,
2805                         const gchar *name,
2806                         GValue      *value)
2807 {
2808
2809   const char *xsettings_name = NULL;
2810   XSettingsResult result;
2811   XSettingsSetting *setting;
2812   GdkScreenX11 *screen_x11;
2813   gboolean success = FALSE;
2814   gint i;
2815   GValue tmp_val = { 0, };
2816   
2817   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
2818   
2819   screen_x11 = GDK_SCREEN_X11 (screen);
2820
2821   for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
2822     if (strcmp (settings_map[i].gdk_name, name) == 0)
2823       {
2824         xsettings_name = settings_map[i].xsettings_name;
2825         break;
2826       }
2827
2828   if (!xsettings_name)
2829     return FALSE;
2830
2831   result = xsettings_client_get_setting (screen_x11->xsettings_client, 
2832                                          xsettings_name, &setting);
2833   if (result != XSETTINGS_SUCCESS)
2834     return FALSE;
2835
2836   switch (setting->type)
2837     {
2838     case XSETTINGS_TYPE_INT:
2839       if (check_transform (xsettings_name, G_TYPE_INT, G_VALUE_TYPE (value)))
2840         {
2841           g_value_init (&tmp_val, G_TYPE_INT);
2842           g_value_set_int (&tmp_val, setting->data.v_int);
2843           g_value_transform (&tmp_val, value);
2844
2845           success = TRUE;
2846         }
2847       break;
2848     case XSETTINGS_TYPE_STRING:
2849       if (check_transform (xsettings_name, G_TYPE_STRING, G_VALUE_TYPE (value)))
2850         {
2851           g_value_init (&tmp_val, G_TYPE_STRING);
2852           g_value_set_string (&tmp_val, setting->data.v_string);
2853           g_value_transform (&tmp_val, value);
2854
2855           success = TRUE;
2856         }
2857       break;
2858     case XSETTINGS_TYPE_COLOR:
2859       if (!check_transform (xsettings_name, GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
2860         {
2861           GdkColor color;
2862           
2863           g_value_init (&tmp_val, GDK_TYPE_COLOR);
2864
2865           color.pixel = 0;
2866           color.red = setting->data.v_color.red;
2867           color.green = setting->data.v_color.green;
2868           color.blue = setting->data.v_color.blue;
2869           
2870           g_value_set_boxed (&tmp_val, &color);
2871           
2872           g_value_transform (&tmp_val, value);
2873           
2874           success = TRUE;
2875         }
2876       break;
2877     }
2878   
2879   g_value_unset (&tmp_val);
2880
2881   xsettings_setting_free (setting);
2882
2883   return success;
2884 }
2885
2886 static GdkFilterReturn 
2887 gdk_xsettings_client_event_filter (GdkXEvent *xevent,
2888                                    GdkEvent  *event,
2889                                    gpointer   data)
2890 {
2891   GdkScreenX11 *screen = data;
2892   
2893   if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent))
2894     return GDK_FILTER_REMOVE;
2895   else
2896     return GDK_FILTER_CONTINUE;
2897 }
2898
2899 static void 
2900 gdk_xsettings_watch_cb (Window   window,
2901                         Bool     is_start,
2902                         long     mask,
2903                         void    *cb_data)
2904 {
2905   GdkWindow *gdkwin;
2906   GdkScreen *screen = cb_data;
2907
2908   gdkwin = gdk_window_lookup_for_display (gdk_screen_get_display (screen), window);
2909
2910   if (is_start)
2911     {
2912       if (!gdkwin)
2913         gdkwin = gdk_window_foreign_new_for_display (gdk_screen_get_display (screen), window);
2914       else
2915         g_object_ref (gdkwin);
2916       
2917       gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
2918     }
2919   else
2920     {
2921       g_assert (gdkwin);
2922       gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
2923       g_object_unref (gdkwin);
2924     }
2925 }