]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkevents-x11.c
Throughout: assorted docs
[~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 "gdk.h"
28 #include "gdkprivate-x11.h"
29 #include "gdkinternals.h"
30 #include "gdkx.h"
31
32 #include "gdkkeysyms.h"
33
34 #include "xsettings-client.h"
35
36 #if HAVE_CONFIG_H
37 #  include <config.h>
38 #  if STDC_HEADERS
39 #    include <string.h>
40 #  endif
41 #endif
42
43 #include "gdkinputprivate.h"
44
45 #ifdef HAVE_XKB
46 #include <X11/XKBlib.h>
47 #endif
48
49 #include <X11/Xatom.h>
50
51 typedef struct _GdkIOClosure GdkIOClosure;
52 typedef struct _GdkEventPrivate GdkEventPrivate;
53
54 #define DOUBLE_CLICK_TIME      250
55 #define TRIPLE_CLICK_TIME      500
56 #define DOUBLE_CLICK_DIST      5
57 #define TRIPLE_CLICK_DIST      5
58
59 typedef enum
60 {
61   /* Following flag is set for events on the event queue during
62    * translation and cleared afterwards.
63    */
64   GDK_EVENT_PENDING = 1 << 0
65 } GdkEventFlags;
66
67 struct _GdkIOClosure
68 {
69   GdkInputFunction function;
70   GdkInputCondition condition;
71   GdkDestroyNotify notify;
72   gpointer data;
73 };
74
75 struct _GdkEventPrivate
76 {
77   GdkEvent event;
78   guint    flags;
79 };
80
81 /* 
82  * Private function declarations
83  */
84
85 static gint      gdk_event_apply_filters (XEvent   *xevent,
86                                           GdkEvent *event,
87                                           GList    *filters);
88 static gint      gdk_event_translate     (GdkEvent *event, 
89                                           XEvent   *xevent,
90                                           gboolean  return_exposes);
91 #if 0
92 static Bool      gdk_event_get_type     (Display   *display, 
93                                          XEvent    *xevent, 
94                                          XPointer   arg);
95 #endif
96
97 static gboolean gdk_event_prepare  (GSource     *source,
98                                     gint        *timeout);
99 static gboolean gdk_event_check    (GSource     *source);
100 static gboolean gdk_event_dispatch (GSource     *source,
101                                     GSourceFunc  callback,
102                                     gpointer     user_data);
103
104 static GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
105                                                 GdkEvent  *event,
106                                                 gpointer   data);
107
108 static void gdk_xsettings_watch_cb  (Window            window,
109                                      Bool              is_start,
110                                      long              mask,
111                                      void             *cb_data);
112 static void gdk_xsettings_notify_cb (const char       *name,
113                                      XSettingsAction   action,
114                                      XSettingsSetting *setting,
115                                      void             *data);
116
117 /* Private variable declarations
118  */
119
120 static int connection_number = 0;           /* The file descriptor number of our
121                                              *  connection to the X server. This
122                                              *  is used so that we may determine
123                                              *  when events are pending by using
124                                              *  the "select" system call.
125                                              */
126 static GList *client_filters;               /* Filters for client messages */
127
128 static GSourceFuncs event_funcs = {
129   gdk_event_prepare,
130   gdk_event_check,
131   gdk_event_dispatch,
132   NULL
133 };
134
135 static GPollFD event_poll_fd;
136
137 static Window wmspec_check_window = None;
138
139 static XSettingsClient *xsettings_client;
140
141 /*********************************************
142  * Functions for maintaining the event queue *
143  *********************************************/
144
145 void 
146 _gdk_events_init (void)
147 {
148   GSource *source;
149   
150   connection_number = ConnectionNumber (gdk_display);
151   GDK_NOTE (MISC,
152             g_message ("connection number: %d", connection_number));
153
154
155   source = g_source_new (&event_funcs, sizeof (GSource));
156   g_source_set_priority (source, GDK_PRIORITY_EVENTS);
157   
158   event_poll_fd.fd = connection_number;
159   event_poll_fd.events = G_IO_IN;
160   
161   g_source_add_poll (source, &event_poll_fd);
162   g_source_set_can_recurse (source, TRUE);
163   g_source_attach (source, NULL);
164
165   _gdk_wm_window_protocols[0] = gdk_atom_intern ("WM_DELETE_WINDOW", FALSE);
166   _gdk_wm_window_protocols[1] = gdk_atom_intern ("WM_TAKE_FOCUS", FALSE);
167   _gdk_wm_window_protocols[2] = gdk_atom_intern ("_NET_WM_PING", FALSE);
168   
169   gdk_add_client_message_filter (gdk_atom_intern ("WM_PROTOCOLS", FALSE),
170                                  gdk_wm_protocols_filter, NULL);
171
172   xsettings_client = xsettings_client_new (gdk_display, DefaultScreen (gdk_display),
173                                            gdk_xsettings_notify_cb,
174                                            gdk_xsettings_watch_cb,
175                                            NULL);
176 }
177
178 /*
179  *--------------------------------------------------------------
180  * gdk_events_pending
181  *
182  *   Returns if events are pending on the queue.
183  *
184  * Arguments:
185  *
186  * Results:
187  *   Returns TRUE if events are pending
188  *
189  * Side effects:
190  *
191  *--------------------------------------------------------------
192  */
193
194 gboolean
195 gdk_events_pending (void)
196 {
197   return (_gdk_event_queue_find_first() || XPending (gdk_display));
198 }
199
200 /*
201  *--------------------------------------------------------------
202  * gdk_event_get_graphics_expose
203  *
204  *   Waits for a GraphicsExpose or NoExpose event
205  *
206  * Arguments:
207  *
208  * Results: 
209  *   For GraphicsExpose events, returns a pointer to the event
210  *   converted into a GdkEvent Otherwise, returns NULL.
211  *
212  * Side effects:
213  *
214  *-------------------------------------------------------------- */
215
216 static Bool
217 graphics_expose_predicate (Display  *display,
218                            XEvent   *xevent,
219                            XPointer  arg)
220 {
221   if (xevent->xany.window == GDK_DRAWABLE_XID ((GdkDrawable *)arg) &&
222       (xevent->xany.type == GraphicsExpose ||
223        xevent->xany.type == NoExpose))
224     return True;
225   else
226     return False;
227 }
228
229 GdkEvent*
230 gdk_event_get_graphics_expose (GdkWindow *window)
231 {
232   XEvent xevent;
233   GdkEvent *event;
234   
235   g_return_val_if_fail (window != NULL, NULL);
236   
237   XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer) window);
238   
239   if (xevent.xany.type == GraphicsExpose)
240     {
241       event = _gdk_event_new ();
242       
243       if (gdk_event_translate (event, &xevent, TRUE))
244         return event;
245       else
246         gdk_event_free (event);
247     }
248   
249   return NULL;  
250 }
251
252 static gint
253 gdk_event_apply_filters (XEvent *xevent,
254                          GdkEvent *event,
255                          GList *filters)
256 {
257   GList *tmp_list;
258   GdkFilterReturn result;
259   
260   tmp_list = filters;
261   
262   while (tmp_list)
263     {
264       GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
265       
266       tmp_list = tmp_list->next;
267       result = filter->function (xevent, event, filter->data);
268       if (result !=  GDK_FILTER_CONTINUE)
269         return result;
270     }
271   
272   return GDK_FILTER_CONTINUE;
273 }
274
275 void 
276 gdk_add_client_message_filter (GdkAtom       message_type,
277                                GdkFilterFunc func,
278                                gpointer      data)
279 {
280   GdkClientFilter *filter = g_new (GdkClientFilter, 1);
281
282   filter->type = message_type;
283   filter->function = func;
284   filter->data = data;
285   
286   client_filters = g_list_prepend (client_filters, filter);
287 }
288
289 static GdkAtom wm_state_atom = 0;
290 static GdkAtom wm_desktop_atom = 0;
291
292 static void
293 gdk_check_wm_state_changed (GdkWindow *window)
294 {  
295   Atom type;
296   gint format;
297   gulong nitems;
298   gulong bytes_after;
299   GdkAtom *atoms = NULL;
300   gulong i;
301   GdkAtom sticky_atom;
302   GdkAtom maxvert_atom;
303   GdkAtom maxhorz_atom;
304   gboolean found_sticky, found_maxvert, found_maxhorz;
305   GdkWindowState old_state;
306   
307   if (GDK_WINDOW_DESTROYED (window))
308     return;
309   
310   if (wm_state_atom == 0)
311     wm_state_atom = gdk_atom_intern ("_NET_WM_STATE", FALSE);
312
313   if (wm_desktop_atom == 0)
314     wm_desktop_atom = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE);
315   
316   XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
317                       wm_state_atom, 0, G_MAXLONG,
318                       False, XA_ATOM, &type, &format, &nitems,
319                       &bytes_after, (guchar **)&atoms);
320
321   if (type != None)
322     {
323
324       sticky_atom = gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE);
325       maxvert_atom = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE);
326       maxhorz_atom = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE);    
327
328       found_sticky = FALSE;
329       found_maxvert = FALSE;
330       found_maxhorz = FALSE;
331   
332       i = 0;
333       while (i < nitems)
334         {
335           if (atoms[i] == sticky_atom)
336             found_sticky = TRUE;
337           else if (atoms[i] == maxvert_atom)
338             found_maxvert = TRUE;
339           else if (atoms[i] == maxhorz_atom)
340             found_maxhorz = TRUE;
341
342           ++i;
343         }
344
345       XFree (atoms);
346     }
347   else
348     {
349       found_sticky = FALSE;
350       found_maxvert = FALSE;
351       found_maxhorz = FALSE;
352     }
353
354   /* For found_sticky to remain TRUE, we have to also be on desktop
355    * 0xFFFFFFFF
356    */
357
358   if (found_sticky)
359     {
360       gulong *desktop;
361       
362       XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
363                           wm_desktop_atom, 0, G_MAXLONG,
364                           False, XA_CARDINAL, &type, &format, &nitems,
365                           &bytes_after, (guchar **)&desktop);
366
367       if (type != None)
368         {
369           if (*desktop != 0xFFFFFFFF)
370             found_sticky = FALSE;
371           XFree (desktop);
372         }
373     }
374           
375   old_state = gdk_window_get_state (window);
376
377   if (old_state & GDK_WINDOW_STATE_STICKY)
378     {
379       if (!found_sticky)
380         gdk_synthesize_window_state (window,
381                                      GDK_WINDOW_STATE_STICKY,
382                                      0);
383     }
384   else
385     {
386       if (found_sticky)
387         gdk_synthesize_window_state (window,
388                                      0,
389                                      GDK_WINDOW_STATE_STICKY);
390     }
391
392   /* Our "maximized" means both vertical and horizontal; if only one,
393    * we don't expose that via GDK
394    */
395   if (old_state & GDK_WINDOW_STATE_MAXIMIZED)
396     {
397       if (!(found_maxvert && found_maxhorz))
398         gdk_synthesize_window_state (window,
399                                      GDK_WINDOW_STATE_MAXIMIZED,
400                                      0);
401     }
402   else
403     {
404       if (found_maxvert && found_maxhorz)
405         gdk_synthesize_window_state (window,
406                                      0,
407                                      GDK_WINDOW_STATE_MAXIMIZED);
408     }
409 }
410
411 #define HAS_FOCUS(window_impl)                           \
412   ((window_impl)->has_focus || (window_impl)->has_pointer_focus)
413
414 static void
415 generate_focus_event (GdkWindow *window,
416                       gboolean   in)
417 {
418   GdkEvent event;
419   
420   event.type = GDK_FOCUS_CHANGE;
421   event.focus_change.window = window;
422   event.focus_change.send_event = FALSE;
423   event.focus_change.in = in;
424   
425   gdk_event_put (&event);
426 }
427
428 static gint
429 gdk_event_translate (GdkEvent *event,
430                      XEvent   *xevent,
431                      gboolean  return_exposes)
432 {
433   
434   GdkWindow *window;
435   GdkWindowObject *window_private;
436   GdkWindowImplX11 *window_impl = NULL;
437   static XComposeStatus compose;
438   KeySym keysym;
439   int charcount;
440   char buf[16];
441   gint return_val;
442   gint xoffset, yoffset;
443   
444   return_val = FALSE;
445
446   /* init these, since the done: block uses them */
447   window = NULL;
448   window_private = NULL;
449   event->any.window = NULL;
450   
451   if (_gdk_default_filters)
452     {
453       /* Apply global filters */
454       GdkFilterReturn result;
455       result = gdk_event_apply_filters (xevent, event,
456                                         _gdk_default_filters);
457       
458       if (result != GDK_FILTER_CONTINUE)
459         {
460           return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
461           goto done;
462         }
463     }  
464
465    /* We handle events with window=None
466     *  specially - they are generated by XFree86's XInput under
467     *  some circumstances. This handling for obvious reasons
468     * goes before we bother to lookup the event window.
469     */
470   
471   if (xevent->xany.window == None)
472     {
473       return_val = _gdk_input_window_none_event (event, xevent);
474       
475       if (return_val >= 0)      /* was handled */
476         return return_val;
477       else
478         return_val = FALSE;
479     }
480
481   /* Find the GdkWindow that this event occurred in. */
482   
483   window = gdk_window_lookup (xevent->xany.window);
484   window_private = (GdkWindowObject *) window;
485   
486   if (window != NULL)
487     {
488       /* Window may be a pixmap, so check its type.
489        * (This check is probably too expensive unless
490        *  GLib short-circuits an exact type match,
491        *  which has been proposed)
492        */
493       if (GDK_IS_WINDOW (window))
494         {
495           window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
496           
497           if (xevent->xany.window != GDK_WINDOW_XID (window))
498             {
499               g_assert (xevent->xany.window == window_impl->focus_window);
500               
501               switch (xevent->type)
502                 {
503                 case KeyPress:
504                 case KeyRelease:
505                   xevent->xany.window = GDK_WINDOW_XID (window);
506                   break;
507                 default:
508                   return False;
509                 }
510             }
511         }
512
513       g_object_ref (G_OBJECT (window));
514     }
515
516   event->any.window = window;
517   event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
518   
519   if (window_private && GDK_WINDOW_DESTROYED (window))
520     {
521       if (xevent->type != DestroyNotify)
522         {
523           return_val = FALSE;
524           goto done;
525         }
526     }
527   else if (window_private)
528     {
529       /* Apply per-window filters */
530       GdkFilterReturn result;
531       result = gdk_event_apply_filters (xevent, event,
532                                         window_private->filters);
533       
534       if (result != GDK_FILTER_CONTINUE)
535         {
536           return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
537           goto done;
538         }
539     }
540       
541   if (wmspec_check_window != None &&
542       xevent->xany.window == wmspec_check_window)
543     {
544       if (xevent->type == DestroyNotify)
545         wmspec_check_window = None;
546       
547       /* Eat events on this window unless someone had wrapped
548        * it as a foreign window
549        */
550       if (window == NULL)
551         {
552           return_val = FALSE;
553           goto done;
554         }
555     }
556
557   if (window &&
558       _gdk_moveresize_window &&
559       (xevent->xany.type == MotionNotify ||
560        xevent->xany.type == ButtonRelease))
561     {
562       _gdk_moveresize_handle_event (xevent);
563       
564       return_val = FALSE;
565       goto done;
566     }
567   
568   /* We do a "manual" conversion of the XEvent to a
569    *  GdkEvent. The structures are mostly the same so
570    *  the conversion is fairly straightforward. We also
571    *  optionally print debugging info regarding events
572    *  received.
573    */
574
575   return_val = TRUE;
576
577   if (window)
578     {
579       _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
580     }
581   else
582     {
583       xoffset = 0;
584       yoffset = 0;
585     }
586   
587   switch (xevent->type)
588     {
589     case KeyPress:
590       if (window_private == NULL)
591         {
592           return_val = FALSE;
593           break;
594         }
595       
596       /* Lookup the string corresponding to the given keysym.
597        */
598
599       charcount = XLookupString (&xevent->xkey, buf, 16,
600                                  &keysym, &compose);
601       event->key.keyval = keysym;
602       event->key.hardware_keycode = xevent->xkey.keycode;
603       
604       if (charcount > 0 && buf[charcount-1] == '\0')
605         charcount --;
606       else
607         buf[charcount] = '\0';
608       
609 #ifdef G_ENABLE_DEBUG
610       if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
611         {
612           g_message ("key press:\twindow: %ld  key: %12s  %d",
613                      xevent->xkey.window,
614                      event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
615                      event->key.keyval);
616           if (charcount > 0)
617             g_message ("\t\tlength: %4d string: \"%s\"",
618                        charcount, buf);
619         }
620 #endif /* G_ENABLE_DEBUG */
621
622       /* bits 13 and 14 in the "state" field are the keyboard group */
623 #define KEYBOARD_GROUP_SHIFT 13
624 #define KEYBOARD_GROUP_MASK ((1 << 13) | (1 << 14))
625       
626       event->key.type = GDK_KEY_PRESS;
627       event->key.window = window;
628       event->key.time = xevent->xkey.time;
629       event->key.state = (GdkModifierType) xevent->xkey.state;
630       event->key.string = g_strdup (buf);
631       event->key.length = charcount;
632
633       event->key.group = (xevent->xkey.state & KEYBOARD_GROUP_MASK) >> KEYBOARD_GROUP_SHIFT;
634       
635       break;
636       
637     case KeyRelease:
638       if (window_private == NULL)
639         {
640           return_val = FALSE;
641           break;
642         }
643       
644       /* Lookup the string corresponding to the given keysym.
645        */
646
647       /* Emulate detectable auto-repeat by checking to see
648        * if the next event is a key press with the same
649        * keycode and timestamp, and if so, ignoring the event.
650        */
651
652       if (!_gdk_have_xkb_autorepeat && XPending (gdk_display))
653         {
654           XEvent next_event;
655
656           XPeekEvent (gdk_display, &next_event);
657
658           if (next_event.type == KeyPress &&
659               next_event.xkey.keycode == xevent->xkey.keycode &&
660               next_event.xkey.time == xevent->xkey.time)
661             break;
662         }
663       
664       keysym = GDK_VoidSymbol;
665       charcount = XLookupString (&xevent->xkey, buf, 16,
666                                  &keysym, &compose);
667       event->key.keyval = keysym;      
668       
669       GDK_NOTE (EVENTS, 
670                 g_message ("key release:\t\twindow: %ld  key: %12s  %d",
671                            xevent->xkey.window,
672                            XKeysymToString (event->key.keyval),
673                            event->key.keyval));
674       
675       event->key.type = GDK_KEY_RELEASE;
676       event->key.window = window;
677       event->key.time = xevent->xkey.time;
678       event->key.state = (GdkModifierType) xevent->xkey.state;
679       event->key.length = 0;
680       event->key.string = NULL;
681       
682       break;
683       
684     case ButtonPress:
685       GDK_NOTE (EVENTS, 
686                 g_message ("button press:\t\twindow: %ld  x,y: %d %d  button: %d",
687                            xevent->xbutton.window,
688                            xevent->xbutton.x, xevent->xbutton.y,
689                            xevent->xbutton.button));
690       
691       if (window_private == NULL || 
692           ((window_private->extension_events != 0) &&
693            _gdk_input_ignore_core))
694         {
695           return_val = FALSE;
696           break;
697         }
698       
699       /* If we get a ButtonPress event where the button is 4 or 5,
700          it's a Scroll event */
701       switch (xevent->xbutton.button)
702         {
703         case 4: /* up */
704         case 5: /* down */
705         case 6: /* left */
706         case 7: /* right */
707           event->scroll.type = GDK_SCROLL;
708
709           if (xevent->xbutton.button == 4)
710             event->scroll.direction = GDK_SCROLL_UP;
711           else if (xevent->xbutton.button == 5)
712             event->scroll.direction = GDK_SCROLL_DOWN;
713           else if (xevent->xbutton.button == 6)
714             event->scroll.direction = GDK_SCROLL_LEFT;
715           else
716             event->scroll.direction = GDK_SCROLL_RIGHT;
717
718           event->scroll.window = window;
719           event->scroll.time = xevent->xbutton.x;
720           event->scroll.x = xevent->xbutton.x + xoffset;
721           event->scroll.y = xevent->xbutton.y + yoffset;
722           event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
723           event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
724           event->scroll.state = (GdkModifierType) xevent->xbutton.state;
725           event->scroll.device = _gdk_core_pointer;
726           break;
727           
728         default:
729           event->button.type = GDK_BUTTON_PRESS;
730           event->button.window = window;
731           event->button.time = xevent->xbutton.time;
732           event->button.x = xevent->xbutton.x + xoffset;
733           event->button.y = xevent->xbutton.y + yoffset;
734           event->button.x_root = (gfloat)xevent->xbutton.x_root;
735           event->button.y_root = (gfloat)xevent->xbutton.y_root;
736           event->button.axes = NULL;
737           event->button.state = (GdkModifierType) xevent->xbutton.state;
738           event->button.button = xevent->xbutton.button;
739           event->button.device = _gdk_core_pointer;
740           
741           _gdk_event_button_generate (event);
742           break;
743         }
744
745       break;
746       
747     case ButtonRelease:
748       GDK_NOTE (EVENTS, 
749                 g_message ("button release:\twindow: %ld  x,y: %d %d  button: %d",
750                            xevent->xbutton.window,
751                            xevent->xbutton.x, xevent->xbutton.y,
752                            xevent->xbutton.button));
753       
754       if (window_private == NULL ||
755           ((window_private->extension_events != 0) &&
756            _gdk_input_ignore_core))
757         {
758           return_val = FALSE;
759           break;
760         }
761       
762       /* We treat button presses as scroll wheel events, so ignore the release */
763       if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5 ||
764           xevent->xbutton.button == 6 || xevent->xbutton.button ==7)
765         {
766           return_val = FALSE;
767           break;
768         }
769
770       event->button.type = GDK_BUTTON_RELEASE;
771       event->button.window = window;
772       event->button.time = xevent->xbutton.time;
773       event->button.x = xevent->xbutton.x + xoffset;
774       event->button.y = xevent->xbutton.y + yoffset;
775       event->button.x_root = (gfloat)xevent->xbutton.x_root;
776       event->button.y_root = (gfloat)xevent->xbutton.y_root;
777       event->button.axes = NULL;
778       event->button.state = (GdkModifierType) xevent->xbutton.state;
779       event->button.button = xevent->xbutton.button;
780       event->button.device = _gdk_core_pointer;
781       
782       break;
783       
784     case MotionNotify:
785       GDK_NOTE (EVENTS,
786                 g_message ("motion notify:\t\twindow: %ld  x,y: %d %d  hint: %s", 
787                            xevent->xmotion.window,
788                            xevent->xmotion.x, xevent->xmotion.y,
789                            (xevent->xmotion.is_hint) ? "true" : "false"));
790       
791       if (window_private == NULL ||
792           ((window_private->extension_events != 0) &&
793            _gdk_input_ignore_core))
794         {
795           return_val = FALSE;
796           break;
797         }
798       
799       event->motion.type = GDK_MOTION_NOTIFY;
800       event->motion.window = window;
801       event->motion.time = xevent->xmotion.time;
802       event->motion.x = xevent->xmotion.x + xoffset;
803       event->motion.y = xevent->xmotion.y + yoffset;
804       event->motion.x_root = (gfloat)xevent->xmotion.x_root;
805       event->motion.y_root = (gfloat)xevent->xmotion.y_root;
806       event->motion.axes = NULL;
807       event->motion.state = (GdkModifierType) xevent->xmotion.state;
808       event->motion.is_hint = xevent->xmotion.is_hint;
809       event->motion.device = _gdk_core_pointer;
810       
811       break;
812       
813     case EnterNotify:
814       GDK_NOTE (EVENTS,
815                 g_message ("enter notify:\t\twindow: %ld  detail: %d subwin: %ld",
816                            xevent->xcrossing.window,
817                            xevent->xcrossing.detail,
818                            xevent->xcrossing.subwindow));
819  
820       if (window_private == NULL)
821         {
822           return_val = FALSE;
823           break;
824         }
825       
826       /* Handle focusing (in the case where no window manager is running */
827       if (window &&
828           GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
829           xevent->xcrossing.detail != NotifyInferior &&
830           xevent->xcrossing.focus && !window_impl->has_focus)
831         {
832           gboolean had_focus = HAS_FOCUS (window_impl);
833           
834           window_impl->has_pointer_focus = TRUE;
835
836           if (HAS_FOCUS (window_impl) != had_focus)
837             generate_focus_event (window, TRUE);
838         }
839
840       /* Tell XInput stuff about it if appropriate */
841       if (window_private &&
842           !GDK_WINDOW_DESTROYED (window) &&
843           window_private->extension_events != 0)
844         _gdk_input_enter_event (&xevent->xcrossing, window);
845       
846       event->crossing.type = GDK_ENTER_NOTIFY;
847       event->crossing.window = window;
848       
849       /* If the subwindow field of the XEvent is non-NULL, then
850        *  lookup the corresponding GdkWindow.
851        */
852       if (xevent->xcrossing.subwindow != None)
853         event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
854       else
855         event->crossing.subwindow = NULL;
856       
857       event->crossing.time = xevent->xcrossing.time;
858       event->crossing.x = xevent->xcrossing.x + xoffset;
859       event->crossing.y = xevent->xcrossing.y + yoffset;
860       event->crossing.x_root = xevent->xcrossing.x_root;
861       event->crossing.y_root = xevent->xcrossing.y_root;
862       
863       /* Translate the crossing mode into Gdk terms.
864        */
865       switch (xevent->xcrossing.mode)
866         {
867         case NotifyNormal:
868           event->crossing.mode = GDK_CROSSING_NORMAL;
869           break;
870         case NotifyGrab:
871           event->crossing.mode = GDK_CROSSING_GRAB;
872           break;
873         case NotifyUngrab:
874           event->crossing.mode = GDK_CROSSING_UNGRAB;
875           break;
876         };
877       
878       /* Translate the crossing detail into Gdk terms.
879        */
880       switch (xevent->xcrossing.detail)
881         {
882         case NotifyInferior:
883           event->crossing.detail = GDK_NOTIFY_INFERIOR;
884           break;
885         case NotifyAncestor:
886           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
887           break;
888         case NotifyVirtual:
889           event->crossing.detail = GDK_NOTIFY_VIRTUAL;
890           break;
891         case NotifyNonlinear:
892           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
893           break;
894         case NotifyNonlinearVirtual:
895           event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
896           break;
897         default:
898           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
899           break;
900         }
901       
902       event->crossing.focus = xevent->xcrossing.focus;
903       event->crossing.state = xevent->xcrossing.state;
904   
905       break;
906       
907     case LeaveNotify:
908       GDK_NOTE (EVENTS, 
909                 g_message ("leave notify:\t\twindow: %ld  detail: %d subwin: %ld",
910                            xevent->xcrossing.window,
911                            xevent->xcrossing.detail, xevent->xcrossing.subwindow));
912
913       if (window_private == NULL)
914         {
915           return_val = FALSE;
916           break;
917         }
918       
919       /* Handle focusing (in the case where no window manager is running */
920       if (window &&
921           GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
922           xevent->xcrossing.detail != NotifyInferior &&
923           xevent->xcrossing.focus && !window_impl->has_focus)
924         {
925           gboolean had_focus = HAS_FOCUS (window_impl);
926           
927           window_impl->has_pointer_focus = FALSE;
928
929           if (HAS_FOCUS (window_impl) != had_focus)
930             generate_focus_event (window, FALSE);
931         }
932
933       event->crossing.type = GDK_LEAVE_NOTIFY;
934       event->crossing.window = window;
935       
936       /* If the subwindow field of the XEvent is non-NULL, then
937        *  lookup the corresponding GdkWindow.
938        */
939       if (xevent->xcrossing.subwindow != None)
940         event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
941       else
942         event->crossing.subwindow = NULL;
943       
944       event->crossing.time = xevent->xcrossing.time;
945       event->crossing.x = xevent->xcrossing.x + xoffset;
946       event->crossing.y = xevent->xcrossing.y + yoffset;
947       event->crossing.x_root = xevent->xcrossing.x_root;
948       event->crossing.y_root = xevent->xcrossing.y_root;
949       
950       /* Translate the crossing mode into Gdk terms.
951        */
952       switch (xevent->xcrossing.mode)
953         {
954         case NotifyNormal:
955           event->crossing.mode = GDK_CROSSING_NORMAL;
956           break;
957         case NotifyGrab:
958           event->crossing.mode = GDK_CROSSING_GRAB;
959           break;
960         case NotifyUngrab:
961           event->crossing.mode = GDK_CROSSING_UNGRAB;
962           break;
963         };
964       
965       /* Translate the crossing detail into Gdk terms.
966        */
967       switch (xevent->xcrossing.detail)
968         {
969         case NotifyInferior:
970           event->crossing.detail = GDK_NOTIFY_INFERIOR;
971           break;
972         case NotifyAncestor:
973           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
974           break;
975         case NotifyVirtual:
976           event->crossing.detail = GDK_NOTIFY_VIRTUAL;
977           break;
978         case NotifyNonlinear:
979           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
980           break;
981         case NotifyNonlinearVirtual:
982           event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
983           break;
984         default:
985           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
986           break;
987         }
988       
989       event->crossing.focus = xevent->xcrossing.focus;
990       event->crossing.state = xevent->xcrossing.state;
991       
992       break;
993       
994       /* We only care about focus events that indicate that _this_
995        * window (not a ancestor or child) got or lost the focus
996        */
997     case FocusIn:
998       GDK_NOTE (EVENTS,
999                 g_message ("focus in:\t\twindow: %ld", xevent->xfocus.window));
1000       
1001       if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
1002         {
1003           gboolean had_focus = HAS_FOCUS (window_impl);
1004           
1005           switch (xevent->xfocus.detail)
1006             {
1007             case NotifyAncestor:
1008             case NotifyNonlinear:
1009             case NotifyVirtual:
1010             case NotifyNonlinearVirtual:
1011               window_impl->has_focus = TRUE;
1012               break;
1013             case NotifyPointer:
1014               window_impl->has_pointer_focus = TRUE;
1015               break;
1016             case NotifyInferior:
1017             case NotifyPointerRoot:
1018             case NotifyDetailNone:
1019               break;
1020             }
1021
1022           if (HAS_FOCUS (window_impl) != had_focus)
1023             generate_focus_event (window, TRUE);
1024         }
1025       break;
1026     case FocusOut:
1027       GDK_NOTE (EVENTS,
1028                 g_message ("focus out:\t\twindow: %ld", xevent->xfocus.window));
1029
1030       if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
1031         {
1032           gboolean had_focus = HAS_FOCUS (window_impl);
1033             
1034           switch (xevent->xfocus.detail)
1035             {
1036             case NotifyAncestor:
1037             case NotifyNonlinear:
1038             case NotifyVirtual:
1039             case NotifyNonlinearVirtual:
1040               window_impl->has_focus = FALSE;
1041               break;
1042             case NotifyPointer:
1043               window_impl->has_pointer_focus = FALSE;
1044             break;
1045             case NotifyInferior:
1046             case NotifyPointerRoot:
1047             case NotifyDetailNone:
1048               break;
1049             }
1050
1051           if (HAS_FOCUS (window_impl) != had_focus)
1052             generate_focus_event (window, FALSE);
1053         }
1054       break;
1055
1056 #if 0      
1057           /* gdk_keyboard_grab() causes following events. These events confuse
1058            * the XIM focus, so ignore them.
1059            */
1060           if (xevent->xfocus.mode == NotifyGrab ||
1061               xevent->xfocus.mode == NotifyUngrab)
1062             break;
1063 #endif
1064
1065     case KeymapNotify:
1066       GDK_NOTE (EVENTS,
1067                 g_message ("keymap notify"));
1068
1069       /* Not currently handled */
1070       return_val = FALSE;
1071       break;
1072       
1073     case Expose:
1074       GDK_NOTE (EVENTS,
1075                 g_message ("expose:\t\twindow: %ld  %d  x,y: %d %d  w,h: %d %d%s",
1076                            xevent->xexpose.window, xevent->xexpose.count,
1077                            xevent->xexpose.x, xevent->xexpose.y,
1078                            xevent->xexpose.width, xevent->xexpose.height,
1079                            event->any.send_event ? " (send)" : ""));
1080       
1081       if (window_private == NULL)
1082         {
1083           return_val = FALSE;
1084           break;
1085         }
1086       
1087       {
1088         GdkRectangle expose_rect;
1089
1090         expose_rect.x = xevent->xexpose.x + xoffset;
1091         expose_rect.y = xevent->xexpose.y + yoffset;
1092         expose_rect.width = xevent->xexpose.width;
1093         expose_rect.height = xevent->xexpose.height;
1094
1095         if (return_exposes)
1096           {
1097             event->expose.type = GDK_EXPOSE;
1098             event->expose.area = expose_rect;
1099             event->expose.region = gdk_region_rectangle (&expose_rect);
1100             event->expose.window = window;
1101             event->expose.count = xevent->xexpose.count;
1102
1103             return_val = TRUE;
1104           }
1105         else
1106           {
1107             _gdk_window_process_expose (window, xevent->xexpose.serial, &expose_rect);
1108
1109             return_val = FALSE;
1110           }
1111         
1112         return_val = FALSE;
1113       }
1114         
1115       break;
1116       
1117     case GraphicsExpose:
1118       {
1119         GdkRectangle expose_rect;
1120
1121         GDK_NOTE (EVENTS,
1122                   g_message ("graphics expose:\tdrawable: %ld",
1123                              xevent->xgraphicsexpose.drawable));
1124  
1125         if (window_private == NULL)
1126           {
1127             return_val = FALSE;
1128             break;
1129           }
1130         
1131         expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
1132         expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
1133         expose_rect.width = xevent->xgraphicsexpose.width;
1134         expose_rect.height = xevent->xgraphicsexpose.height;
1135             
1136         if (return_exposes)
1137           {
1138             event->expose.type = GDK_EXPOSE;
1139             event->expose.area = expose_rect;
1140             event->expose.region = gdk_region_rectangle (&expose_rect);
1141             event->expose.window = window;
1142             event->expose.count = xevent->xgraphicsexpose.count;
1143
1144             return_val = TRUE;
1145           }
1146         else
1147           {
1148             _gdk_window_process_expose (window, xevent->xgraphicsexpose.serial, &expose_rect);
1149             
1150             return_val = FALSE;
1151           }
1152         
1153       }
1154       break;
1155       
1156     case NoExpose:
1157       GDK_NOTE (EVENTS,
1158                 g_message ("no expose:\t\tdrawable: %ld",
1159                            xevent->xnoexpose.drawable));
1160       
1161       event->no_expose.type = GDK_NO_EXPOSE;
1162       event->no_expose.window = window;
1163       
1164       break;
1165       
1166     case VisibilityNotify:
1167 #ifdef G_ENABLE_DEBUG
1168       if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
1169         switch (xevent->xvisibility.state)
1170           {
1171           case VisibilityFullyObscured:
1172             g_message ("visibility notify:\twindow: %ld  none",
1173                        xevent->xvisibility.window);
1174             break;
1175           case VisibilityPartiallyObscured:
1176             g_message ("visibility notify:\twindow: %ld  partial",
1177                        xevent->xvisibility.window);
1178             break;
1179           case VisibilityUnobscured:
1180             g_message ("visibility notify:\twindow: %ld  full",
1181                        xevent->xvisibility.window);
1182             break;
1183           }
1184 #endif /* G_ENABLE_DEBUG */
1185       
1186       if (window_private == NULL)
1187         {
1188           return_val = FALSE;
1189           break;
1190         }
1191       
1192       event->visibility.type = GDK_VISIBILITY_NOTIFY;
1193       event->visibility.window = window;
1194       
1195       switch (xevent->xvisibility.state)
1196         {
1197         case VisibilityFullyObscured:
1198           event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
1199           break;
1200           
1201         case VisibilityPartiallyObscured:
1202           event->visibility.state = GDK_VISIBILITY_PARTIAL;
1203           break;
1204           
1205         case VisibilityUnobscured:
1206           event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
1207           break;
1208         }
1209       
1210       break;
1211       
1212     case CreateNotify:
1213       GDK_NOTE (EVENTS,
1214                 g_message ("create notify:\twindow: %ld  x,y: %d %d     w,h: %d %d  b-w: %d  parent: %ld         ovr: %d",
1215                            xevent->xcreatewindow.window,
1216                            xevent->xcreatewindow.x,
1217                            xevent->xcreatewindow.y,
1218                            xevent->xcreatewindow.width,
1219                            xevent->xcreatewindow.height,
1220                            xevent->xcreatewindow.border_width,
1221                            xevent->xcreatewindow.parent,
1222                            xevent->xcreatewindow.override_redirect));
1223       /* not really handled */
1224       break;
1225       
1226     case DestroyNotify:
1227       GDK_NOTE (EVENTS,
1228                 g_message ("destroy notify:\twindow: %ld",
1229                            xevent->xdestroywindow.window));
1230
1231       /* Ignore DestroyNotify from SubstructureNotifyMask */
1232       if (xevent->xdestroywindow.window == xevent->xdestroywindow.event)
1233         {
1234           event->any.type = GDK_DESTROY;
1235           event->any.window = window;
1236           
1237           return_val = window_private && !GDK_WINDOW_DESTROYED (window);
1238           
1239           if (window && GDK_WINDOW_XID (window) != GDK_ROOT_WINDOW())
1240             gdk_window_destroy_notify (window);
1241         }
1242       else
1243         return_val = FALSE;
1244       break;
1245       
1246     case UnmapNotify:
1247       GDK_NOTE (EVENTS,
1248                 g_message ("unmap notify:\t\twindow: %ld",
1249                            xevent->xmap.window));
1250       
1251       event->any.type = GDK_UNMAP;
1252       event->any.window = window;      
1253
1254       /* If we are shown (not withdrawn) and get an unmap, it means we
1255        * were iconified in the X sense. If we are withdrawn, and get
1256        * an unmap, it means we hid the window ourselves, so we
1257        * will have already flipped the iconified bit off.
1258        */
1259       if (window && GDK_WINDOW_IS_MAPPED (window))
1260         gdk_synthesize_window_state (window,
1261                                      0,
1262                                      GDK_WINDOW_STATE_ICONIFIED);
1263       
1264       if (_gdk_xgrab_window == window_private)
1265         _gdk_xgrab_window = NULL;
1266       
1267       break;
1268       
1269     case MapNotify:
1270       GDK_NOTE (EVENTS,
1271                 g_message ("map notify:\t\twindow: %ld",
1272                            xevent->xmap.window));
1273       
1274       event->any.type = GDK_MAP;
1275       event->any.window = window;
1276
1277       /* Unset iconified if it was set */
1278       if (window && (((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_ICONIFIED))
1279         gdk_synthesize_window_state (window,
1280                                      GDK_WINDOW_STATE_ICONIFIED,
1281                                      0);
1282       
1283       break;
1284       
1285     case ReparentNotify:
1286       GDK_NOTE (EVENTS,
1287                 g_message ("reparent notify:\twindow: %ld  x,y: %d %d  parent: %ld      ovr: %d",
1288                            xevent->xreparent.window,
1289                            xevent->xreparent.x,
1290                            xevent->xreparent.y,
1291                            xevent->xreparent.parent,
1292                            xevent->xreparent.override_redirect));
1293
1294       /* Not currently handled */
1295       return_val = FALSE;
1296       break;
1297       
1298     case ConfigureNotify:
1299       GDK_NOTE (EVENTS,
1300                 g_message ("configure notify:\twindow: %ld  x,y: %d %d  w,h: %d %d  b-w: %d  above: %ld  ovr: %d%s",
1301                            xevent->xconfigure.window,
1302                            xevent->xconfigure.x,
1303                            xevent->xconfigure.y,
1304                            xevent->xconfigure.width,
1305                            xevent->xconfigure.height,
1306                            xevent->xconfigure.border_width,
1307                            xevent->xconfigure.above,
1308                            xevent->xconfigure.override_redirect,
1309                            !window
1310                            ? " (discarding)"
1311                            : GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD
1312                            ? " (discarding child)"
1313                            : ""));
1314       if (window &&
1315           !GDK_WINDOW_DESTROYED (window) &&
1316           (window_private->extension_events != 0))
1317         _gdk_input_configure_event (&xevent->xconfigure, window);
1318
1319       if (!window ||
1320           GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
1321           GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
1322         return_val = FALSE;
1323       else
1324         {
1325           event->configure.type = GDK_CONFIGURE;
1326           event->configure.window = window;
1327           event->configure.width = xevent->xconfigure.width;
1328           event->configure.height = xevent->xconfigure.height;
1329           
1330           if (!xevent->xconfigure.send_event && 
1331               !GDK_WINDOW_DESTROYED (window))
1332             {
1333               gint tx = 0;
1334               gint ty = 0;
1335               Window child_window = 0;
1336
1337               gdk_error_trap_push ();
1338               if (XTranslateCoordinates (GDK_DRAWABLE_XDISPLAY (window),
1339                                          GDK_DRAWABLE_XID (window),
1340                                          _gdk_root_window,
1341                                          0, 0,
1342                                          &tx, &ty,
1343                                          &child_window))
1344                 {
1345                   if (!gdk_error_trap_pop ())
1346                     {
1347                       event->configure.x = tx;
1348                       event->configure.y = ty;
1349                     }
1350                 }
1351               else
1352                 gdk_error_trap_pop ();
1353             }
1354           else
1355             {
1356               event->configure.x = xevent->xconfigure.x;
1357               event->configure.y = xevent->xconfigure.y;
1358             }
1359           window_private->x = event->configure.x;
1360           window_private->y = event->configure.y;
1361           GDK_WINDOW_IMPL_X11 (window_private->impl)->width = xevent->xconfigure.width;
1362           GDK_WINDOW_IMPL_X11 (window_private->impl)->height = xevent->xconfigure.height;
1363           if (window_private->resize_count >= 1)
1364             {
1365               window_private->resize_count -= 1;
1366
1367               if (window_private->resize_count == 0 &&
1368                   window == _gdk_moveresize_window)
1369                 _gdk_moveresize_configure_done ();
1370             }
1371         }
1372       break;
1373       
1374     case PropertyNotify:
1375       GDK_NOTE (EVENTS,
1376                 gchar *atom = gdk_atom_name (xevent->xproperty.atom);
1377                 g_message ("property notify:\twindow: %ld, atom(%ld): %s%s%s",
1378                            xevent->xproperty.window,
1379                            xevent->xproperty.atom,
1380                            atom ? "\"" : "",
1381                            atom ? atom : "unknown",
1382                            atom ? "\"" : "");
1383                 g_free (atom);
1384                 );
1385
1386       if (window_private == NULL)
1387         {
1388           return_val = FALSE;
1389           break;
1390         }
1391       
1392       event->property.type = GDK_PROPERTY_NOTIFY;
1393       event->property.window = window;
1394       event->property.atom = xevent->xproperty.atom;
1395       event->property.time = xevent->xproperty.time;
1396       event->property.state = xevent->xproperty.state;
1397
1398       if (wm_state_atom == 0)
1399         wm_state_atom = gdk_atom_intern ("_NET_WM_STATE", FALSE);
1400
1401       if (wm_desktop_atom == 0)
1402         wm_desktop_atom = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE);
1403       
1404       if (event->property.atom == wm_state_atom ||
1405           event->property.atom == wm_desktop_atom)
1406         {
1407           /* If window state changed, then synthesize those events. */
1408           gdk_check_wm_state_changed (event->property.window);
1409         }
1410       
1411       break;
1412       
1413     case SelectionClear:
1414       GDK_NOTE (EVENTS,
1415                 g_message ("selection clear:\twindow: %ld",
1416                            xevent->xproperty.window));
1417
1418       if (_gdk_selection_filter_clear_event (&xevent->xselectionclear))
1419         {
1420           event->selection.type = GDK_SELECTION_CLEAR;
1421           event->selection.window = window;
1422           event->selection.selection = xevent->xselectionclear.selection;
1423           event->selection.time = xevent->xselectionclear.time;
1424         }
1425       else
1426         return_val = FALSE;
1427           
1428       break;
1429       
1430     case SelectionRequest:
1431       GDK_NOTE (EVENTS,
1432                 g_message ("selection request:\twindow: %ld",
1433                            xevent->xproperty.window));
1434       
1435       event->selection.type = GDK_SELECTION_REQUEST;
1436       event->selection.window = window;
1437       event->selection.selection = xevent->xselectionrequest.selection;
1438       event->selection.target = xevent->xselectionrequest.target;
1439       event->selection.property = xevent->xselectionrequest.property;
1440       event->selection.requestor = xevent->xselectionrequest.requestor;
1441       event->selection.time = xevent->xselectionrequest.time;
1442       
1443       break;
1444       
1445     case SelectionNotify:
1446       GDK_NOTE (EVENTS,
1447                 g_message ("selection notify:\twindow: %ld",
1448                            xevent->xproperty.window));
1449       
1450       
1451       event->selection.type = GDK_SELECTION_NOTIFY;
1452       event->selection.window = window;
1453       event->selection.selection = xevent->xselection.selection;
1454       event->selection.target = xevent->xselection.target;
1455       event->selection.property = xevent->xselection.property;
1456       event->selection.time = xevent->xselection.time;
1457       
1458       break;
1459       
1460     case ColormapNotify:
1461       GDK_NOTE (EVENTS,
1462                 g_message ("colormap notify:\twindow: %ld",
1463                            xevent->xcolormap.window));
1464       
1465       /* Not currently handled */
1466       return_val = FALSE;
1467       break;
1468       
1469     case ClientMessage:
1470       {
1471         GList *tmp_list;
1472         GdkFilterReturn result = GDK_FILTER_CONTINUE;
1473
1474         GDK_NOTE (EVENTS,
1475                   g_message ("client message:\twindow: %ld",
1476                              xevent->xclient.window));
1477         
1478         tmp_list = client_filters;
1479         while (tmp_list)
1480           {
1481             GdkClientFilter *filter = tmp_list->data;
1482             if (filter->type == xevent->xclient.message_type)
1483               {
1484                 result = (*filter->function) (xevent, event, filter->data);
1485                 break;
1486               }
1487             
1488             tmp_list = tmp_list->next;
1489           }
1490
1491         switch (result)
1492           {
1493           case GDK_FILTER_REMOVE:
1494             return_val = FALSE;
1495             break;
1496           case GDK_FILTER_TRANSLATE:
1497             return_val = TRUE;
1498             break;
1499           case GDK_FILTER_CONTINUE:
1500             /* Send unknown ClientMessage's on to Gtk for it to use */
1501             if (window_private == NULL)
1502               {
1503                 return_val = FALSE;
1504               }
1505             else
1506               {
1507                 event->client.type = GDK_CLIENT_EVENT;
1508                 event->client.window = window;
1509                 event->client.message_type = xevent->xclient.message_type;
1510                 event->client.data_format = xevent->xclient.format;
1511                 memcpy(&event->client.data, &xevent->xclient.data,
1512                        sizeof(event->client.data));
1513               }
1514             break;
1515           }
1516       }
1517       
1518       break;
1519       
1520     case MappingNotify:
1521       GDK_NOTE (EVENTS,
1522                 g_message ("mapping notify"));
1523       
1524       /* Let XLib know that there is a new keyboard mapping.
1525        */
1526       XRefreshKeyboardMapping (&xevent->xmapping);
1527       ++_gdk_keymap_serial;
1528       return_val = FALSE;
1529       break;
1530
1531     default:
1532 #ifdef HAVE_XKB
1533       if (xevent->type == _gdk_xkb_event_type)
1534         {
1535           XkbEvent *xkb_event = (XkbEvent *)xevent;
1536
1537           switch (xkb_event->any.xkb_type)
1538             {
1539             case XkbMapNotify:
1540               ++_gdk_keymap_serial;
1541               return_val = FALSE;
1542               break;
1543               
1544             case XkbStateNotify:
1545               _gdk_keymap_state_changed ();
1546               break;
1547             }
1548         }
1549       else
1550 #endif
1551         {
1552           /* something else - (e.g., a Xinput event) */
1553           
1554           if (window_private &&
1555               !GDK_WINDOW_DESTROYED (window_private) &&
1556               (window_private->extension_events != 0))
1557             return_val = _gdk_input_other_event(event, xevent, window);
1558           else
1559             return_val = FALSE;
1560           
1561           break;
1562         }
1563     }
1564
1565  done:
1566   if (return_val)
1567     {
1568       if (event->any.window)
1569         gdk_window_ref (event->any.window);
1570       if (((event->any.type == GDK_ENTER_NOTIFY) ||
1571            (event->any.type == GDK_LEAVE_NOTIFY)) &&
1572           (event->crossing.subwindow != NULL))
1573         gdk_window_ref (event->crossing.subwindow);
1574     }
1575   else
1576     {
1577       /* Mark this event as having no resources to be freed */
1578       event->any.window = NULL;
1579       event->any.type = GDK_NOTHING;
1580     }
1581   
1582   if (window)
1583     gdk_window_unref (window);
1584   
1585   return return_val;
1586 }
1587
1588 static GdkFilterReturn
1589 gdk_wm_protocols_filter (GdkXEvent *xev,
1590                          GdkEvent  *event,
1591                          gpointer data)
1592 {
1593   XEvent *xevent = (XEvent *)xev;
1594
1595   if ((Atom) xevent->xclient.data.l[0] == gdk_atom_intern ("WM_DELETE_WINDOW", FALSE))
1596     {
1597   /* The delete window request specifies a window
1598    *  to delete. We don't actually destroy the
1599    *  window because "it is only a request". (The
1600    *  window might contain vital data that the
1601    *  program does not want destroyed). Instead
1602    *  the event is passed along to the program,
1603    *  which should then destroy the window.
1604    */
1605       GDK_NOTE (EVENTS,
1606                 g_message ("delete window:\t\twindow: %ld",
1607                            xevent->xclient.window));
1608       
1609       event->any.type = GDK_DELETE;
1610
1611       return GDK_FILTER_TRANSLATE;
1612     }
1613   else if ((Atom) xevent->xclient.data.l[0] == gdk_atom_intern ("WM_TAKE_FOCUS", FALSE))
1614     {
1615       GdkWindow *win = event->any.window;
1616       Window focus_win = GDK_WINDOW_IMPL_X11(((GdkWindowObject *)win)->impl)->focus_window;
1617
1618       /* There is no way of knowing reliably whether we are viewable so we need
1619        * to trap errors so we don't cause a BadMatch.
1620        */
1621       gdk_error_trap_push ();
1622       XSetInputFocus (GDK_WINDOW_XDISPLAY (win),
1623                       focus_win,
1624                       RevertToParent,
1625                       xevent->xclient.data.l[1]);
1626       XSync (GDK_WINDOW_XDISPLAY (win), False);
1627       gdk_error_trap_pop ();
1628     }
1629   else if ((Atom) xevent->xclient.data.l[0] == gdk_atom_intern ("_NET_WM_PING", FALSE))
1630     {
1631       XEvent xev = *xevent;
1632       
1633       xev.xclient.window = _gdk_root_window;
1634       XSendEvent (gdk_display, _gdk_root_window, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
1635     }
1636
1637   return GDK_FILTER_REMOVE;
1638 }
1639
1640 #if 0
1641 static Bool
1642 gdk_event_get_type (Display  *display,
1643                     XEvent   *xevent,
1644                     XPointer  arg)
1645 {
1646   GdkEvent event;
1647   GdkPredicate *pred;
1648   
1649   if (gdk_event_translate (&event, xevent, FALSE))
1650     {
1651       pred = (GdkPredicate*) arg;
1652       return (* pred->func) (&event, pred->data);
1653     }
1654   
1655   return FALSE;
1656 }
1657 #endif
1658
1659 void
1660 _gdk_events_queue (void)
1661 {
1662   GList *node;
1663   GdkEvent *event;
1664   XEvent xevent;
1665
1666   while (!_gdk_event_queue_find_first() && XPending (gdk_display))
1667     {
1668       XNextEvent (gdk_display, &xevent);
1669
1670       switch (xevent.type)
1671         {
1672         case KeyPress:
1673         case KeyRelease:
1674           break;
1675         default:
1676           if (XFilterEvent (&xevent, None))
1677             continue;
1678         }
1679       
1680       event = _gdk_event_new ();
1681       
1682       event->any.type = GDK_NOTHING;
1683       event->any.window = NULL;
1684       event->any.send_event = xevent.xany.send_event ? TRUE : FALSE;
1685
1686       ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
1687
1688       _gdk_event_queue_append (event);
1689       node = _gdk_queued_tail;
1690
1691       if (gdk_event_translate (event, &xevent, FALSE))
1692         {
1693           ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
1694         }
1695       else
1696         {
1697           _gdk_event_queue_remove_link (node);
1698           g_list_free_1 (node);
1699           gdk_event_free (event);
1700         }
1701     }
1702 }
1703
1704 static gboolean  
1705 gdk_event_prepare (GSource  *source,
1706                    gint     *timeout)
1707 {
1708   gboolean retval;
1709   
1710   GDK_THREADS_ENTER ();
1711
1712   *timeout = -1;
1713
1714   retval = (_gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
1715
1716   GDK_THREADS_LEAVE ();
1717
1718   return retval;
1719 }
1720
1721 static gboolean  
1722 gdk_event_check (GSource  *source) 
1723 {
1724   gboolean retval;
1725   
1726   GDK_THREADS_ENTER ();
1727
1728   if (event_poll_fd.revents & G_IO_IN)
1729     retval = (_gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
1730   else
1731     retval = FALSE;
1732
1733   GDK_THREADS_LEAVE ();
1734
1735   return retval;
1736 }
1737
1738 static gboolean  
1739 gdk_event_dispatch (GSource    *source,
1740                     GSourceFunc callback,
1741                     gpointer    user_data)
1742 {
1743   GdkEvent *event;
1744  
1745   GDK_THREADS_ENTER ();
1746
1747   _gdk_events_queue();
1748   event = _gdk_event_unqueue();
1749
1750   if (event)
1751     {
1752       if (_gdk_event_func)
1753         (*_gdk_event_func) (event, _gdk_event_data);
1754       
1755       gdk_event_free (event);
1756     }
1757   
1758   GDK_THREADS_LEAVE ();
1759
1760   return TRUE;
1761 }
1762
1763 /* Sends a ClientMessage to all toplevel client windows */
1764 gboolean
1765 gdk_event_send_client_message (GdkEvent *event, guint32 xid)
1766 {
1767   XEvent sev;
1768   
1769   g_return_val_if_fail(event != NULL, FALSE);
1770   
1771   /* Set up our event to send, with the exception of its target window */
1772   sev.xclient.type = ClientMessage;
1773   sev.xclient.display = gdk_display;
1774   sev.xclient.format = event->client.data_format;
1775   sev.xclient.window = xid;
1776   memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
1777   sev.xclient.message_type = event->client.message_type;
1778   
1779   return gdk_send_xevent (xid, False, NoEventMask, &sev);
1780 }
1781
1782 /* Sends a ClientMessage to all toplevel client windows */
1783 gboolean
1784 gdk_event_send_client_message_to_all_recurse (XEvent  *xev, 
1785                                               guint32  xid,
1786                                               guint    level)
1787 {
1788   static GdkAtom wm_state_atom = GDK_NONE;
1789   Atom type = None;
1790   int format;
1791   unsigned long nitems, after;
1792   unsigned char *data;
1793   Window *ret_children, ret_root, ret_parent;
1794   unsigned int ret_nchildren;
1795   gint old_warnings = _gdk_error_warnings;
1796   gboolean send = FALSE;
1797   gboolean found = FALSE;
1798   int i;
1799
1800   if (!wm_state_atom)
1801     wm_state_atom = gdk_atom_intern ("WM_STATE", FALSE);
1802
1803   _gdk_error_warnings = FALSE;
1804   _gdk_error_code = 0;
1805   XGetWindowProperty (gdk_display, xid, wm_state_atom, 0, 0, False, AnyPropertyType,
1806                       &type, &format, &nitems, &after, &data);
1807
1808   if (_gdk_error_code)
1809     {
1810       _gdk_error_warnings = old_warnings;
1811
1812       return FALSE;
1813     }
1814
1815   if (type)
1816     {
1817       send = TRUE;
1818       XFree (data);
1819     }
1820   else
1821     {
1822       /* OK, we're all set, now let's find some windows to send this to */
1823       if (XQueryTree (gdk_display, xid, &ret_root, &ret_parent,
1824                       &ret_children, &ret_nchildren) != True ||
1825           _gdk_error_code)
1826         {
1827           _gdk_error_warnings = old_warnings;
1828
1829           return FALSE;
1830         }
1831
1832       for(i = 0; i < ret_nchildren; i++)
1833         if (gdk_event_send_client_message_to_all_recurse (xev, ret_children[i], level + 1))
1834           found = TRUE;
1835
1836       XFree (ret_children);
1837     }
1838
1839   if (send || (!found && (level == 1)))
1840     {
1841       xev->xclient.window = xid;
1842       gdk_send_xevent (xid, False, NoEventMask, xev);
1843     }
1844
1845   _gdk_error_warnings = old_warnings;
1846
1847   return (send || found);
1848 }
1849
1850 void
1851 gdk_event_send_clientmessage_toall (GdkEvent *event)
1852 {
1853   XEvent sev;
1854   gint old_warnings = _gdk_error_warnings;
1855
1856   g_return_if_fail(event != NULL);
1857   
1858   /* Set up our event to send, with the exception of its target window */
1859   sev.xclient.type = ClientMessage;
1860   sev.xclient.display = gdk_display;
1861   sev.xclient.format = event->client.data_format;
1862   memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
1863   sev.xclient.message_type = event->client.message_type;
1864
1865   gdk_event_send_client_message_to_all_recurse(&sev, _gdk_root_window, 0);
1866
1867   _gdk_error_warnings = old_warnings;
1868 }
1869
1870 /*
1871  *--------------------------------------------------------------
1872  * gdk_flush
1873  *
1874  *   Flushes the Xlib output buffer and then waits
1875  *   until all requests have been received and processed
1876  *   by the X server. The only real use for this function
1877  *   is in dealing with XShm.
1878  *
1879  * Arguments:
1880  *
1881  * Results:
1882  *
1883  * Side effects:
1884  *
1885  *--------------------------------------------------------------
1886  */
1887
1888 void
1889 gdk_flush (void)
1890 {
1891   XSync (gdk_display, False);
1892 }
1893
1894 static GdkAtom timestamp_prop_atom = 0;
1895
1896 static Bool
1897 timestamp_predicate (Display *display,
1898                      XEvent  *xevent,
1899                      XPointer arg)
1900 {
1901   Window xwindow = GPOINTER_TO_UINT (arg);
1902
1903   if (xevent->type == PropertyNotify &&
1904       xevent->xproperty.window == xwindow &&
1905       xevent->xproperty.atom == timestamp_prop_atom)
1906     return True;
1907
1908   return False;
1909 }
1910
1911 /**
1912  * gdk_x11_get_server_time:
1913  * @window: a #GdkWindow, used for communication with the server.
1914  *          The window must have GDK_PROPERTY_CHANGE_MASK in its
1915  *          events mask or a hang will result.
1916  * 
1917  * Routine to get the current X server time stamp. 
1918  * 
1919  * Return value: the time stamp.
1920  **/
1921 guint32
1922 gdk_x11_get_server_time (GdkWindow *window)
1923 {
1924   Display *xdisplay;
1925   Window   xwindow;
1926   guchar c = 'a';
1927   XEvent xevent;
1928
1929   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1930   g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
1931
1932   if (!timestamp_prop_atom)
1933     timestamp_prop_atom = gdk_atom_intern ("GDK_TIMESTAMP_PROP", FALSE);
1934
1935   xdisplay = GDK_WINDOW_XDISPLAY (window);
1936   xwindow = GDK_WINDOW_XWINDOW (window);
1937   
1938   XChangeProperty (xdisplay, xwindow,
1939                    timestamp_prop_atom, timestamp_prop_atom,
1940                    8, PropModeReplace, &c, 1);
1941
1942   XIfEvent (xdisplay, &xevent,
1943             timestamp_predicate, GUINT_TO_POINTER(xwindow));
1944
1945   return xevent.xproperty.time;
1946 }
1947
1948
1949 /**
1950  * gdk_net_wm_supports:
1951  * @property: a property atom
1952  * 
1953  * This function is specific to the X11 backend of GDK, and indicates
1954  * whether the window manager supports a certain hint from the
1955  * Extended Window Manager Hints Specification. You can find this
1956  * specification on http://www.freedesktop.org.
1957  *
1958  * When using this function, keep in mind that the window manager
1959  * can change over time; so you shouldn't use this function in
1960  * a way that impacts persistent application state. A common bug
1961  * is that your application can start up before the window manager
1962  * does when the user logs in, and before the window manager starts
1963  * gdk_net_wm_supports() will return %FALSE for every property.
1964  * 
1965  * Return value: %TRUE if the window manager supports @property
1966  **/
1967 gboolean
1968 gdk_net_wm_supports (GdkAtom property)
1969 {
1970   static GdkAtom wmspec_check_atom = 0;
1971   static GdkAtom wmspec_supported_atom = 0;
1972   static GdkAtom *atoms = NULL;
1973   static gulong n_atoms = 0;
1974   Atom type;
1975   gint format;
1976   gulong nitems;
1977   gulong bytes_after;
1978   Window *xwindow;
1979   gulong i;
1980
1981   if (wmspec_check_window != None)
1982     {
1983       if (atoms == NULL)
1984         return FALSE;
1985
1986       i = 0;
1987       while (i < n_atoms)
1988         {
1989           if (atoms[i] == property)
1990             return TRUE;
1991           
1992           ++i;
1993         }
1994
1995       return FALSE;
1996     }
1997
1998   if (atoms)
1999     XFree (atoms);
2000
2001   atoms = NULL;
2002   n_atoms = 0;
2003   
2004   /* This function is very slow on every call if you are not running a
2005    * spec-supporting WM. For now not optimized, because it isn't in
2006    * any critical code paths, but if you used it somewhere that had to
2007    * be fast you want to avoid "GTK is slow with old WMs" complaints.
2008    * Probably at that point the function should be changed to query
2009    * _NET_SUPPORTING_WM_CHECK only once every 10 seconds or something.
2010    */
2011   
2012   if (wmspec_check_atom == 0)
2013     wmspec_check_atom = gdk_atom_intern ("_NET_SUPPORTING_WM_CHECK", FALSE);
2014       
2015   if (wmspec_supported_atom == 0)
2016     wmspec_supported_atom = gdk_atom_intern ("_NET_SUPPORTED", FALSE);
2017   
2018   XGetWindowProperty (gdk_display, _gdk_root_window,
2019                       wmspec_check_atom, 0, G_MAXLONG,
2020                       False, XA_WINDOW, &type, &format, &nitems,
2021                       &bytes_after, (guchar **)&xwindow);
2022
2023   if (type != XA_WINDOW)
2024     return FALSE;
2025
2026   gdk_error_trap_push ();
2027
2028   /* Find out if this WM goes away, so we can reset everything. */
2029   XSelectInput (gdk_display, *xwindow,
2030                 StructureNotifyMask);
2031   
2032   gdk_flush ();
2033   
2034   if (gdk_error_trap_pop ())
2035     {
2036       XFree (xwindow);
2037       return FALSE;
2038     }
2039
2040   XGetWindowProperty (gdk_display, _gdk_root_window,
2041                       wmspec_supported_atom, 0, G_MAXLONG,
2042                       False, XA_ATOM, &type, &format, &n_atoms,
2043                       &bytes_after, (guchar **)&atoms);
2044   
2045   if (type != XA_ATOM)
2046     return FALSE;
2047   
2048   wmspec_check_window = *xwindow;
2049   XFree (xwindow);
2050   
2051   /* since wmspec_check_window != None this isn't infinite. ;-) */
2052   return gdk_net_wm_supports (property);
2053 }
2054
2055 static struct
2056 {
2057   const char *xsettings_name;
2058   const char *gdk_name;
2059 } settings_map[] = {
2060   { "Net/DoubleClickTime", "gtk-double-click-timeout" },
2061   { "Net/DragThreshold", "gtk-drag-threshold" },
2062   { "Gtk/ColorPalette", "gtk-color-palette" },
2063   { "Gtk/ToolbarStyle", "gtk-toolbar-style" },
2064   { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
2065   { "Net/CursorBlink", "gtk-cursor-blink" },
2066   { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
2067   { "Net/ThemeName", "gtk-theme-name" },
2068   { "Gtk/KeyThemeName", "gtk-key-theme-name" }
2069 };
2070
2071 static void
2072 gdk_xsettings_notify_cb (const char       *name,
2073                          XSettingsAction   action,
2074                          XSettingsSetting *setting,
2075                          void             *data)
2076 {
2077   GdkEvent new_event;
2078   int i;
2079
2080   new_event.type = GDK_SETTING;
2081   new_event.setting.window = NULL;
2082   new_event.setting.send_event = FALSE;
2083   new_event.setting.name = NULL;
2084
2085   for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
2086     if (strcmp (settings_map[i].xsettings_name, name) == 0)
2087       {
2088         new_event.setting.name = g_strdup (settings_map[i].gdk_name);
2089         break;
2090       }
2091
2092   if (!new_event.setting.name)
2093     return;
2094   
2095   switch (action)
2096     {
2097     case XSETTINGS_ACTION_NEW:
2098       new_event.setting.action = GDK_SETTING_ACTION_NEW;
2099       break;
2100     case XSETTINGS_ACTION_CHANGED:
2101       new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
2102       break;
2103     case XSETTINGS_ACTION_DELETED:
2104       new_event.setting.action = GDK_SETTING_ACTION_DELETED;
2105       break;
2106     }
2107
2108   gdk_event_put (&new_event);
2109 }
2110
2111 static gboolean
2112 check_transform (const gchar *xsettings_name,
2113                  GType        src_type,
2114                  GType        dest_type)
2115 {
2116   if (!g_value_type_transformable (src_type, dest_type))
2117     {
2118       g_warning ("Cannot tranform xsetting %s of type %s to type %s\n",
2119                  xsettings_name,
2120                  g_type_name (src_type),
2121                  g_type_name (dest_type));
2122       return FALSE;
2123     }
2124   else
2125     return TRUE;
2126 }
2127
2128 gboolean
2129 gdk_setting_get (const gchar *name,
2130                  GValue      *value)
2131 {
2132   const char *xsettings_name = NULL;
2133   XSettingsResult result;
2134   XSettingsSetting *setting;
2135   gboolean success = FALSE;
2136   gint i;
2137   GValue tmp_val = { 0, };
2138
2139   for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
2140     if (strcmp (settings_map[i].gdk_name, name) == 0)
2141       {
2142         xsettings_name = settings_map[i].xsettings_name;
2143         break;
2144       }
2145
2146   if (!xsettings_name)
2147     return FALSE;
2148
2149   result = xsettings_client_get_setting (xsettings_client, xsettings_name, &setting);
2150   if (result != XSETTINGS_SUCCESS)
2151     return FALSE;
2152
2153   switch (setting->type)
2154     {
2155     case XSETTINGS_TYPE_INT:
2156       if (check_transform (xsettings_name, G_TYPE_INT, G_VALUE_TYPE (value)))
2157         {
2158           g_value_init (&tmp_val, G_TYPE_INT);
2159           g_value_set_int (&tmp_val, setting->data.v_int);
2160           g_value_transform (&tmp_val, value);
2161
2162           success = TRUE;
2163         }
2164       break;
2165     case XSETTINGS_TYPE_STRING:
2166       if (check_transform (xsettings_name, G_TYPE_STRING, G_VALUE_TYPE (value)))
2167         {
2168           g_value_init (&tmp_val, G_TYPE_STRING);
2169           g_value_set_string (&tmp_val, setting->data.v_string);
2170           g_value_transform (&tmp_val, value);
2171
2172           success = TRUE;
2173         }
2174       break;
2175     case XSETTINGS_TYPE_COLOR:
2176       if (!check_transform (xsettings_name, GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
2177         {
2178           GdkColor color;
2179           
2180           g_value_init (&tmp_val, GDK_TYPE_COLOR);
2181
2182           color.pixel = 0;
2183           color.red = setting->data.v_color.red;
2184           color.green = setting->data.v_color.green;
2185           color.blue = setting->data.v_color.blue;
2186           
2187           g_value_set_boxed (&tmp_val, &color);
2188           
2189           g_value_transform (&tmp_val, value);
2190           
2191           success = TRUE;
2192         }
2193       break;
2194     }
2195   
2196   g_value_unset (&tmp_val);
2197
2198   xsettings_setting_free (setting);
2199
2200   return success;
2201 }
2202
2203 static GdkFilterReturn 
2204 gdk_xsettings_client_event_filter (GdkXEvent *xevent,
2205                                    GdkEvent  *event,
2206                                    gpointer   data)
2207 {
2208   if (xsettings_client_process_event (xsettings_client, (XEvent *)xevent))
2209     return GDK_FILTER_REMOVE;
2210   else
2211     return GDK_FILTER_CONTINUE;
2212 }
2213
2214 static void 
2215 gdk_xsettings_watch_cb (Window window,
2216                         Bool   is_start,
2217                         long   mask,
2218                         void  *cb_data)
2219 {
2220   GdkWindow *gdkwin;
2221
2222   gdkwin = gdk_window_lookup (window);
2223   if (is_start)
2224     gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, NULL);
2225   else
2226     gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, NULL);
2227 }