]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkevents-x11.c
Move here, and save/restore the X error handler to allow people using GTK+
[~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_x11_get_xatom_by_name ("WM_DELETE_WINDOW");
166   _gdk_wm_window_protocols[1] = gdk_x11_get_xatom_by_name ("WM_TAKE_FOCUS");
167   _gdk_wm_window_protocols[2] = gdk_x11_get_xatom_by_name ("_NET_WM_PING");
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 Atom wm_state_atom = 0;
290 static Atom 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   Atom *atoms = NULL;
300   gulong i;
301   Atom sticky_atom;
302   Atom maxvert_atom;
303   Atom 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_x11_get_xatom_by_name ("_NET_WM_STATE");
312
313   if (wm_desktop_atom == 0)
314     wm_desktop_atom = gdk_x11_get_xatom_by_name ("_NET_WM_DESKTOP");
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_x11_get_xatom_by_name ("_NET_WM_STATE_STICKY");
325       maxvert_atom = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_MAXIMIZED_VERT");
326       maxhorz_atom = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_MAXIMIZED_HORZ");    
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                 g_message ("property notify:\twindow: %ld, atom(%ld): %s%s%s",
1377                            xevent->xproperty.window,
1378                            xevent->xproperty.atom,
1379                            "\"",
1380                            gdk_x11_get_xatom_name (xevent->xproperty.atom),
1381                            "\""));
1382
1383       if (window_private == NULL)
1384         {
1385           return_val = FALSE;
1386           break;
1387         }
1388       
1389       event->property.type = GDK_PROPERTY_NOTIFY;
1390       event->property.window = window;
1391       event->property.atom = gdk_x11_xatom_to_atom (xevent->xproperty.atom);
1392       event->property.time = xevent->xproperty.time;
1393       event->property.state = xevent->xproperty.state;
1394
1395       if (wm_state_atom == 0)
1396         wm_state_atom = gdk_x11_get_xatom_by_name ("_NET_WM_STATE");
1397
1398       if (wm_desktop_atom == 0)
1399         wm_desktop_atom = gdk_x11_get_xatom_by_name ("_NET_WM_DESKTOP");
1400       
1401       if (xevent->xproperty.atom == wm_state_atom || 
1402           xevent->xproperty.atom == wm_desktop_atom)
1403         {
1404           /* If window state changed, then synthesize those events. */
1405           gdk_check_wm_state_changed (event->property.window);
1406         }
1407       
1408       break;
1409       
1410     case SelectionClear:
1411       GDK_NOTE (EVENTS,
1412                 g_message ("selection clear:\twindow: %ld",
1413                            xevent->xproperty.window));
1414
1415       if (_gdk_selection_filter_clear_event (&xevent->xselectionclear))
1416         {
1417           event->selection.type = GDK_SELECTION_CLEAR;
1418           event->selection.window = window;
1419           event->selection.selection = gdk_x11_xatom_to_atom (xevent->xselectionclear.selection);
1420           event->selection.time = xevent->xselectionclear.time;
1421         }
1422       else
1423         return_val = FALSE;
1424           
1425       break;
1426       
1427     case SelectionRequest:
1428       GDK_NOTE (EVENTS,
1429                 g_message ("selection request:\twindow: %ld",
1430                            xevent->xproperty.window));
1431       
1432       event->selection.type = GDK_SELECTION_REQUEST;
1433       event->selection.window = window;
1434       event->selection.selection = gdk_x11_xatom_to_atom (xevent->xselectionrequest.selection);
1435       event->selection.target = gdk_x11_xatom_to_atom (xevent->xselectionrequest.target);
1436       event->selection.property = gdk_x11_xatom_to_atom (xevent->xselectionrequest.property);
1437       event->selection.requestor = xevent->xselectionrequest.requestor;
1438       event->selection.time = xevent->xselectionrequest.time;
1439       
1440       break;
1441       
1442     case SelectionNotify:
1443       GDK_NOTE (EVENTS,
1444                 g_message ("selection notify:\twindow: %ld",
1445                            xevent->xproperty.window));
1446       
1447       
1448       event->selection.type = GDK_SELECTION_NOTIFY;
1449       event->selection.window = window;
1450       event->selection.selection = gdk_x11_xatom_to_atom (xevent->xselection.selection);
1451       event->selection.target = gdk_x11_xatom_to_atom (xevent->xselection.target);
1452       event->selection.property = gdk_x11_xatom_to_atom (xevent->xselection.property);
1453       event->selection.time = xevent->xselection.time;
1454       
1455       break;
1456       
1457     case ColormapNotify:
1458       GDK_NOTE (EVENTS,
1459                 g_message ("colormap notify:\twindow: %ld",
1460                            xevent->xcolormap.window));
1461       
1462       /* Not currently handled */
1463       return_val = FALSE;
1464       break;
1465       
1466     case ClientMessage:
1467       {
1468         GList *tmp_list;
1469         GdkFilterReturn result = GDK_FILTER_CONTINUE;
1470         GdkAtom message_type = gdk_x11_xatom_to_atom (xevent->xclient.message_type);
1471
1472         GDK_NOTE (EVENTS,
1473                   g_message ("client message:\twindow: %ld",
1474                              xevent->xclient.window));
1475         
1476         tmp_list = client_filters;
1477         while (tmp_list)
1478           {
1479             GdkClientFilter *filter = tmp_list->data;
1480             if (filter->type == message_type)
1481               {
1482                 result = (*filter->function) (xevent, event, filter->data);
1483                 break;
1484               }
1485             
1486             tmp_list = tmp_list->next;
1487           }
1488
1489         switch (result)
1490           {
1491           case GDK_FILTER_REMOVE:
1492             return_val = FALSE;
1493             break;
1494           case GDK_FILTER_TRANSLATE:
1495             return_val = TRUE;
1496             break;
1497           case GDK_FILTER_CONTINUE:
1498             /* Send unknown ClientMessage's on to Gtk for it to use */
1499             if (window_private == NULL)
1500               {
1501                 return_val = FALSE;
1502               }
1503             else
1504               {
1505                 event->client.type = GDK_CLIENT_EVENT;
1506                 event->client.window = window;
1507                 event->client.message_type = message_type;
1508                 event->client.data_format = xevent->xclient.format;
1509                 memcpy(&event->client.data, &xevent->xclient.data,
1510                        sizeof(event->client.data));
1511               }
1512             break;
1513           }
1514       }
1515       
1516       break;
1517       
1518     case MappingNotify:
1519       GDK_NOTE (EVENTS,
1520                 g_message ("mapping notify"));
1521       
1522       /* Let XLib know that there is a new keyboard mapping.
1523        */
1524       XRefreshKeyboardMapping (&xevent->xmapping);
1525       ++_gdk_keymap_serial;
1526       return_val = FALSE;
1527       break;
1528
1529     default:
1530 #ifdef HAVE_XKB
1531       if (xevent->type == _gdk_xkb_event_type)
1532         {
1533           XkbEvent *xkb_event = (XkbEvent *)xevent;
1534
1535           switch (xkb_event->any.xkb_type)
1536             {
1537             case XkbMapNotify:
1538               ++_gdk_keymap_serial;
1539               return_val = FALSE;
1540               break;
1541               
1542             case XkbStateNotify:
1543               _gdk_keymap_state_changed ();
1544               break;
1545             }
1546         }
1547       else
1548 #endif
1549         {
1550           /* something else - (e.g., a Xinput event) */
1551           
1552           if (window_private &&
1553               !GDK_WINDOW_DESTROYED (window_private) &&
1554               (window_private->extension_events != 0))
1555             return_val = _gdk_input_other_event(event, xevent, window);
1556           else
1557             return_val = FALSE;
1558           
1559           break;
1560         }
1561     }
1562
1563  done:
1564   if (return_val)
1565     {
1566       if (event->any.window)
1567         gdk_window_ref (event->any.window);
1568       if (((event->any.type == GDK_ENTER_NOTIFY) ||
1569            (event->any.type == GDK_LEAVE_NOTIFY)) &&
1570           (event->crossing.subwindow != NULL))
1571         gdk_window_ref (event->crossing.subwindow);
1572     }
1573   else
1574     {
1575       /* Mark this event as having no resources to be freed */
1576       event->any.window = NULL;
1577       event->any.type = GDK_NOTHING;
1578     }
1579   
1580   if (window)
1581     gdk_window_unref (window);
1582   
1583   return return_val;
1584 }
1585
1586 static GdkFilterReturn
1587 gdk_wm_protocols_filter (GdkXEvent *xev,
1588                          GdkEvent  *event,
1589                          gpointer data)
1590 {
1591   XEvent *xevent = (XEvent *)xev;
1592
1593   if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name ("WM_DELETE_WINDOW"))
1594     {
1595   /* The delete window request specifies a window
1596    *  to delete. We don't actually destroy the
1597    *  window because "it is only a request". (The
1598    *  window might contain vital data that the
1599    *  program does not want destroyed). Instead
1600    *  the event is passed along to the program,
1601    *  which should then destroy the window.
1602    */
1603       GDK_NOTE (EVENTS,
1604                 g_message ("delete window:\t\twindow: %ld",
1605                            xevent->xclient.window));
1606       
1607       event->any.type = GDK_DELETE;
1608
1609       return GDK_FILTER_TRANSLATE;
1610     }
1611   else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name ("WM_TAKE_FOCUS"))
1612     {
1613       GdkWindow *win = event->any.window;
1614       Window focus_win = GDK_WINDOW_IMPL_X11(((GdkWindowObject *)win)->impl)->focus_window;
1615
1616       /* There is no way of knowing reliably whether we are viewable so we need
1617        * to trap errors so we don't cause a BadMatch.
1618        */
1619       gdk_error_trap_push ();
1620       XSetInputFocus (GDK_WINDOW_XDISPLAY (win),
1621                       focus_win,
1622                       RevertToParent,
1623                       xevent->xclient.data.l[1]);
1624       XSync (GDK_WINDOW_XDISPLAY (win), False);
1625       gdk_error_trap_pop ();
1626     }
1627   else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name ("_NET_WM_PING"))
1628     {
1629       XEvent xev = *xevent;
1630       
1631       xev.xclient.window = _gdk_root_window;
1632       XSendEvent (gdk_display, _gdk_root_window, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
1633     }
1634
1635   return GDK_FILTER_REMOVE;
1636 }
1637
1638 #if 0
1639 static Bool
1640 gdk_event_get_type (Display  *display,
1641                     XEvent   *xevent,
1642                     XPointer  arg)
1643 {
1644   GdkEvent event;
1645   GdkPredicate *pred;
1646   
1647   if (gdk_event_translate (&event, xevent, FALSE))
1648     {
1649       pred = (GdkPredicate*) arg;
1650       return (* pred->func) (&event, pred->data);
1651     }
1652   
1653   return FALSE;
1654 }
1655 #endif
1656
1657 void
1658 _gdk_events_queue (void)
1659 {
1660   GList *node;
1661   GdkEvent *event;
1662   XEvent xevent;
1663
1664   while (!_gdk_event_queue_find_first() && XPending (gdk_display))
1665     {
1666       XNextEvent (gdk_display, &xevent);
1667
1668       switch (xevent.type)
1669         {
1670         case KeyPress:
1671         case KeyRelease:
1672           break;
1673         default:
1674           if (XFilterEvent (&xevent, None))
1675             continue;
1676         }
1677       
1678       event = _gdk_event_new ();
1679       
1680       event->any.type = GDK_NOTHING;
1681       event->any.window = NULL;
1682       event->any.send_event = xevent.xany.send_event ? TRUE : FALSE;
1683
1684       ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
1685
1686       _gdk_event_queue_append (event);
1687       node = _gdk_queued_tail;
1688
1689       if (gdk_event_translate (event, &xevent, FALSE))
1690         {
1691           ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
1692         }
1693       else
1694         {
1695           _gdk_event_queue_remove_link (node);
1696           g_list_free_1 (node);
1697           gdk_event_free (event);
1698         }
1699     }
1700 }
1701
1702 static gboolean  
1703 gdk_event_prepare (GSource  *source,
1704                    gint     *timeout)
1705 {
1706   gboolean retval;
1707   
1708   GDK_THREADS_ENTER ();
1709
1710   *timeout = -1;
1711
1712   retval = (_gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
1713
1714   GDK_THREADS_LEAVE ();
1715
1716   return retval;
1717 }
1718
1719 static gboolean  
1720 gdk_event_check (GSource  *source) 
1721 {
1722   gboolean retval;
1723   
1724   GDK_THREADS_ENTER ();
1725
1726   if (event_poll_fd.revents & G_IO_IN)
1727     retval = (_gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
1728   else
1729     retval = FALSE;
1730
1731   GDK_THREADS_LEAVE ();
1732
1733   return retval;
1734 }
1735
1736 static gboolean  
1737 gdk_event_dispatch (GSource    *source,
1738                     GSourceFunc callback,
1739                     gpointer    user_data)
1740 {
1741   GdkEvent *event;
1742  
1743   GDK_THREADS_ENTER ();
1744
1745   _gdk_events_queue();
1746   event = _gdk_event_unqueue();
1747
1748   if (event)
1749     {
1750       if (_gdk_event_func)
1751         (*_gdk_event_func) (event, _gdk_event_data);
1752       
1753       gdk_event_free (event);
1754     }
1755   
1756   GDK_THREADS_LEAVE ();
1757
1758   return TRUE;
1759 }
1760
1761 /* Sends a ClientMessage to all toplevel client windows */
1762 gboolean
1763 gdk_event_send_client_message (GdkEvent *event, guint32 xid)
1764 {
1765   XEvent sev;
1766   
1767   g_return_val_if_fail(event != NULL, FALSE);
1768   
1769   /* Set up our event to send, with the exception of its target window */
1770   sev.xclient.type = ClientMessage;
1771   sev.xclient.display = gdk_display;
1772   sev.xclient.format = event->client.data_format;
1773   sev.xclient.window = xid;
1774   memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
1775   sev.xclient.message_type = gdk_x11_atom_to_xatom (event->client.message_type);
1776   
1777   return gdk_send_xevent (xid, False, NoEventMask, &sev);
1778 }
1779
1780 /* Sends a ClientMessage to all toplevel client windows */
1781 gboolean
1782 gdk_event_send_client_message_to_all_recurse (XEvent  *xev, 
1783                                               guint32  xid,
1784                                               guint    level)
1785 {
1786   static Atom wm_state_atom = None;
1787   Atom type = None;
1788   int format;
1789   unsigned long nitems, after;
1790   unsigned char *data;
1791   Window *ret_children, ret_root, ret_parent;
1792   unsigned int ret_nchildren;
1793   gboolean send = FALSE;
1794   gboolean found = FALSE;
1795   gboolean result = FALSE;
1796   int i;
1797
1798   if (!wm_state_atom)
1799     wm_state_atom = gdk_x11_get_xatom_by_name ("WM_STATE");
1800
1801   gdk_error_trap_push ();
1802   
1803   if (XGetWindowProperty (gdk_display, xid, wm_state_atom, 0, 0, False, AnyPropertyType,
1804                           &type, &format, &nitems, &after, &data) != Success)
1805     goto out;
1806
1807   if (type)
1808     {
1809       send = TRUE;
1810       XFree (data);
1811     }
1812   else
1813     {
1814       /* OK, we're all set, now let's find some windows to send this to */
1815       if (!XQueryTree (gdk_display, xid, &ret_root, &ret_parent,
1816                        &ret_children, &ret_nchildren))
1817         goto out;
1818
1819       for(i = 0; i < ret_nchildren; i++)
1820         if (gdk_event_send_client_message_to_all_recurse (xev, ret_children[i], level + 1))
1821           found = TRUE;
1822
1823       XFree (ret_children);
1824     }
1825
1826   if (send || (!found && (level == 1)))
1827     {
1828       xev->xclient.window = xid;
1829       gdk_send_xevent (xid, False, NoEventMask, xev);
1830     }
1831
1832   result = send || found;
1833
1834  out:
1835   gdk_error_trap_pop ();
1836
1837   return result;
1838 }
1839
1840 void
1841 gdk_event_send_clientmessage_toall (GdkEvent *event)
1842 {
1843   XEvent sev;
1844
1845   g_return_if_fail(event != NULL);
1846   
1847   /* Set up our event to send, with the exception of its target window */
1848   sev.xclient.type = ClientMessage;
1849   sev.xclient.display = gdk_display;
1850   sev.xclient.format = event->client.data_format;
1851   memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
1852   sev.xclient.message_type = gdk_x11_atom_to_xatom (event->client.message_type);
1853
1854   gdk_event_send_client_message_to_all_recurse(&sev, _gdk_root_window, 0);
1855 }
1856
1857 /*
1858  *--------------------------------------------------------------
1859  * gdk_flush
1860  *
1861  *   Flushes the Xlib output buffer and then waits
1862  *   until all requests have been received and processed
1863  *   by the X server. The only real use for this function
1864  *   is in dealing with XShm.
1865  *
1866  * Arguments:
1867  *
1868  * Results:
1869  *
1870  * Side effects:
1871  *
1872  *--------------------------------------------------------------
1873  */
1874
1875 void
1876 gdk_flush (void)
1877 {
1878   XSync (gdk_display, False);
1879 }
1880
1881 static Atom timestamp_prop_atom = 0;
1882
1883 static Bool
1884 timestamp_predicate (Display *display,
1885                      XEvent  *xevent,
1886                      XPointer arg)
1887 {
1888   Window xwindow = GPOINTER_TO_UINT (arg);
1889
1890   if (xevent->type == PropertyNotify &&
1891       xevent->xproperty.window == xwindow &&
1892       xevent->xproperty.atom == timestamp_prop_atom)
1893     return True;
1894
1895   return False;
1896 }
1897
1898 /**
1899  * gdk_x11_get_server_time:
1900  * @window: a #GdkWindow, used for communication with the server.
1901  *          The window must have GDK_PROPERTY_CHANGE_MASK in its
1902  *          events mask or a hang will result.
1903  * 
1904  * Routine to get the current X server time stamp. 
1905  * 
1906  * Return value: the time stamp.
1907  **/
1908 guint32
1909 gdk_x11_get_server_time (GdkWindow *window)
1910 {
1911   Display *xdisplay;
1912   Window   xwindow;
1913   guchar c = 'a';
1914   XEvent xevent;
1915
1916   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1917   g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
1918
1919   if (!timestamp_prop_atom)
1920     timestamp_prop_atom = gdk_x11_get_xatom_by_name ("GDK_TIMESTAMP_PROP");
1921
1922   xdisplay = GDK_WINDOW_XDISPLAY (window);
1923   xwindow = GDK_WINDOW_XWINDOW (window);
1924   
1925   XChangeProperty (xdisplay, xwindow,
1926                    timestamp_prop_atom, timestamp_prop_atom,
1927                    8, PropModeReplace, &c, 1);
1928
1929   XIfEvent (xdisplay, &xevent,
1930             timestamp_predicate, GUINT_TO_POINTER(xwindow));
1931
1932   return xevent.xproperty.time;
1933 }
1934
1935
1936 /**
1937  * gdk_net_wm_supports:
1938  * @property: a property atom
1939  * 
1940  * This function is specific to the X11 backend of GDK, and indicates
1941  * whether the window manager supports a certain hint from the
1942  * Extended Window Manager Hints Specification. You can find this
1943  * specification on http://www.freedesktop.org.
1944  *
1945  * When using this function, keep in mind that the window manager
1946  * can change over time; so you shouldn't use this function in
1947  * a way that impacts persistent application state. A common bug
1948  * is that your application can start up before the window manager
1949  * does when the user logs in, and before the window manager starts
1950  * gdk_net_wm_supports() will return %FALSE for every property.
1951  * 
1952  * Return value: %TRUE if the window manager supports @property
1953  **/
1954 gboolean
1955 gdk_net_wm_supports (GdkAtom property)
1956 {
1957   static Atom wmspec_check_atom = 0;
1958   static Atom wmspec_supported_atom = 0;
1959   static Atom *atoms = NULL;
1960   static gulong n_atoms = 0;
1961   Atom xproperty = gdk_x11_atom_to_xatom (property);
1962   Atom type;
1963   gint format;
1964   gulong nitems;
1965   gulong bytes_after;
1966   Window *xwindow;
1967   gulong i;
1968
1969   if (wmspec_check_window != None)
1970     {
1971       if (atoms == NULL)
1972         return FALSE;
1973
1974       i = 0;
1975       while (i < n_atoms)
1976         {
1977           if (atoms[i] == xproperty)
1978             return TRUE;
1979           
1980           ++i;
1981         }
1982
1983       return FALSE;
1984     }
1985
1986   if (atoms)
1987     XFree (atoms);
1988
1989   atoms = NULL;
1990   n_atoms = 0;
1991   
1992   /* This function is very slow on every call if you are not running a
1993    * spec-supporting WM. For now not optimized, because it isn't in
1994    * any critical code paths, but if you used it somewhere that had to
1995    * be fast you want to avoid "GTK is slow with old WMs" complaints.
1996    * Probably at that point the function should be changed to query
1997    * _NET_SUPPORTING_WM_CHECK only once every 10 seconds or something.
1998    */
1999   
2000   if (wmspec_check_atom == 0)
2001     wmspec_check_atom = gdk_x11_get_xatom_by_name ("_NET_SUPPORTING_WM_CHECK");
2002       
2003   if (wmspec_supported_atom == 0)
2004     wmspec_supported_atom = gdk_x11_get_xatom_by_name ("_NET_SUPPORTED");
2005   
2006   XGetWindowProperty (gdk_display, _gdk_root_window,
2007                       wmspec_check_atom, 0, G_MAXLONG,
2008                       False, XA_WINDOW, &type, &format, &nitems,
2009                       &bytes_after, (guchar **)&xwindow);
2010
2011   if (type != XA_WINDOW)
2012     return FALSE;
2013
2014   gdk_error_trap_push ();
2015
2016   /* Find out if this WM goes away, so we can reset everything. */
2017   XSelectInput (gdk_display, *xwindow,
2018                 StructureNotifyMask);
2019   
2020   gdk_flush ();
2021   
2022   if (gdk_error_trap_pop ())
2023     {
2024       XFree (xwindow);
2025       return FALSE;
2026     }
2027
2028   XGetWindowProperty (gdk_display, _gdk_root_window,
2029                       wmspec_supported_atom, 0, G_MAXLONG,
2030                       False, XA_ATOM, &type, &format, &n_atoms,
2031                       &bytes_after, (guchar **)&atoms);
2032   
2033   if (type != XA_ATOM)
2034     return FALSE;
2035   
2036   wmspec_check_window = *xwindow;
2037   XFree (xwindow);
2038   
2039   /* since wmspec_check_window != None this isn't infinite. ;-) */
2040   return gdk_net_wm_supports (property);
2041 }
2042
2043 static struct
2044 {
2045   const char *xsettings_name;
2046   const char *gdk_name;
2047 } settings_map[] = {
2048   { "Net/DoubleClickTime", "gtk-double-click-timeout" },
2049   { "Net/DndDragThreshold", "gtk-dnd-drag-threshold" },
2050   { "Gtk/ColorPalette", "gtk-color-palette" },
2051   { "Gtk/ToolbarStyle", "gtk-toolbar-style" },
2052   { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
2053   { "Net/CursorBlink", "gtk-cursor-blink" },
2054   { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
2055   { "Net/ThemeName", "gtk-theme-name" },
2056   { "Gtk/KeyThemeName", "gtk-key-theme-name" }
2057 };
2058
2059 static void
2060 gdk_xsettings_notify_cb (const char       *name,
2061                          XSettingsAction   action,
2062                          XSettingsSetting *setting,
2063                          void             *data)
2064 {
2065   GdkEvent new_event;
2066   int i;
2067
2068   new_event.type = GDK_SETTING;
2069   new_event.setting.window = NULL;
2070   new_event.setting.send_event = FALSE;
2071   new_event.setting.name = NULL;
2072
2073   for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
2074     if (strcmp (settings_map[i].xsettings_name, name) == 0)
2075       {
2076         new_event.setting.name = g_strdup (settings_map[i].gdk_name);
2077         break;
2078       }
2079
2080   if (!new_event.setting.name)
2081     return;
2082   
2083   switch (action)
2084     {
2085     case XSETTINGS_ACTION_NEW:
2086       new_event.setting.action = GDK_SETTING_ACTION_NEW;
2087       break;
2088     case XSETTINGS_ACTION_CHANGED:
2089       new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
2090       break;
2091     case XSETTINGS_ACTION_DELETED:
2092       new_event.setting.action = GDK_SETTING_ACTION_DELETED;
2093       break;
2094     }
2095
2096   gdk_event_put (&new_event);
2097 }
2098
2099 static gboolean
2100 check_transform (const gchar *xsettings_name,
2101                  GType        src_type,
2102                  GType        dest_type)
2103 {
2104   if (!g_value_type_transformable (src_type, dest_type))
2105     {
2106       g_warning ("Cannot tranform xsetting %s of type %s to type %s\n",
2107                  xsettings_name,
2108                  g_type_name (src_type),
2109                  g_type_name (dest_type));
2110       return FALSE;
2111     }
2112   else
2113     return TRUE;
2114 }
2115
2116 gboolean
2117 gdk_setting_get (const gchar *name,
2118                  GValue      *value)
2119 {
2120   const char *xsettings_name = NULL;
2121   XSettingsResult result;
2122   XSettingsSetting *setting;
2123   gboolean success = FALSE;
2124   gint i;
2125   GValue tmp_val = { 0, };
2126
2127   for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
2128     if (strcmp (settings_map[i].gdk_name, name) == 0)
2129       {
2130         xsettings_name = settings_map[i].xsettings_name;
2131         break;
2132       }
2133
2134   if (!xsettings_name)
2135     return FALSE;
2136
2137   result = xsettings_client_get_setting (xsettings_client, xsettings_name, &setting);
2138   if (result != XSETTINGS_SUCCESS)
2139     return FALSE;
2140
2141   switch (setting->type)
2142     {
2143     case XSETTINGS_TYPE_INT:
2144       if (check_transform (xsettings_name, G_TYPE_INT, G_VALUE_TYPE (value)))
2145         {
2146           g_value_init (&tmp_val, G_TYPE_INT);
2147           g_value_set_int (&tmp_val, setting->data.v_int);
2148           g_value_transform (&tmp_val, value);
2149
2150           success = TRUE;
2151         }
2152       break;
2153     case XSETTINGS_TYPE_STRING:
2154       if (check_transform (xsettings_name, G_TYPE_STRING, G_VALUE_TYPE (value)))
2155         {
2156           g_value_init (&tmp_val, G_TYPE_STRING);
2157           g_value_set_string (&tmp_val, setting->data.v_string);
2158           g_value_transform (&tmp_val, value);
2159
2160           success = TRUE;
2161         }
2162       break;
2163     case XSETTINGS_TYPE_COLOR:
2164       if (!check_transform (xsettings_name, GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
2165         {
2166           GdkColor color;
2167           
2168           g_value_init (&tmp_val, GDK_TYPE_COLOR);
2169
2170           color.pixel = 0;
2171           color.red = setting->data.v_color.red;
2172           color.green = setting->data.v_color.green;
2173           color.blue = setting->data.v_color.blue;
2174           
2175           g_value_set_boxed (&tmp_val, &color);
2176           
2177           g_value_transform (&tmp_val, value);
2178           
2179           success = TRUE;
2180         }
2181       break;
2182     }
2183   
2184   g_value_unset (&tmp_val);
2185
2186   xsettings_setting_free (setting);
2187
2188   return success;
2189 }
2190
2191 static GdkFilterReturn 
2192 gdk_xsettings_client_event_filter (GdkXEvent *xevent,
2193                                    GdkEvent  *event,
2194                                    gpointer   data)
2195 {
2196   if (xsettings_client_process_event (xsettings_client, (XEvent *)xevent))
2197     return GDK_FILTER_REMOVE;
2198   else
2199     return GDK_FILTER_CONTINUE;
2200 }
2201
2202 static void 
2203 gdk_xsettings_watch_cb (Window window,
2204                         Bool   is_start,
2205                         long   mask,
2206                         void  *cb_data)
2207 {
2208   GdkWindow *gdkwin;
2209
2210   gdkwin = gdk_window_lookup (window);
2211   if (is_start)
2212     gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, NULL);
2213   else
2214     gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, NULL);
2215 }