]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkevents-x11.c
Robustify tracking of pointer grab window.
[~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       event->key.group = (xevent->xkey.state & KEYBOARD_GROUP_MASK) >> KEYBOARD_GROUP_SHIFT;
683
684       break;
685       
686     case ButtonPress:
687       GDK_NOTE (EVENTS, 
688                 g_message ("button press:\t\twindow: %ld  x,y: %d %d  button: %d",
689                            xevent->xbutton.window,
690                            xevent->xbutton.x, xevent->xbutton.y,
691                            xevent->xbutton.button));
692       
693       if (window_private == NULL || 
694           ((window_private->extension_events != 0) &&
695            _gdk_input_ignore_core))
696         {
697           return_val = FALSE;
698           break;
699         }
700       
701       /* If we get a ButtonPress event where the button is 4 or 5,
702          it's a Scroll event */
703       switch (xevent->xbutton.button)
704         {
705         case 4: /* up */
706         case 5: /* down */
707         case 6: /* left */
708         case 7: /* right */
709           event->scroll.type = GDK_SCROLL;
710
711           if (xevent->xbutton.button == 4)
712             event->scroll.direction = GDK_SCROLL_UP;
713           else if (xevent->xbutton.button == 5)
714             event->scroll.direction = GDK_SCROLL_DOWN;
715           else if (xevent->xbutton.button == 6)
716             event->scroll.direction = GDK_SCROLL_LEFT;
717           else
718             event->scroll.direction = GDK_SCROLL_RIGHT;
719
720           event->scroll.window = window;
721           event->scroll.time = xevent->xbutton.x;
722           event->scroll.x = xevent->xbutton.x + xoffset;
723           event->scroll.y = xevent->xbutton.y + yoffset;
724           event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
725           event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
726           event->scroll.state = (GdkModifierType) xevent->xbutton.state;
727           event->scroll.device = _gdk_core_pointer;
728           break;
729           
730         default:
731           event->button.type = GDK_BUTTON_PRESS;
732           event->button.window = window;
733           event->button.time = xevent->xbutton.time;
734           event->button.x = xevent->xbutton.x + xoffset;
735           event->button.y = xevent->xbutton.y + yoffset;
736           event->button.x_root = (gfloat)xevent->xbutton.x_root;
737           event->button.y_root = (gfloat)xevent->xbutton.y_root;
738           event->button.axes = NULL;
739           event->button.state = (GdkModifierType) xevent->xbutton.state;
740           event->button.button = xevent->xbutton.button;
741           event->button.device = _gdk_core_pointer;
742           
743           _gdk_event_button_generate (event);
744           break;
745         }
746
747       break;
748       
749     case ButtonRelease:
750       GDK_NOTE (EVENTS, 
751                 g_message ("button release:\twindow: %ld  x,y: %d %d  button: %d",
752                            xevent->xbutton.window,
753                            xevent->xbutton.x, xevent->xbutton.y,
754                            xevent->xbutton.button));
755       
756       if (window_private == NULL ||
757           ((window_private->extension_events != 0) &&
758            _gdk_input_ignore_core))
759         {
760           return_val = FALSE;
761           break;
762         }
763       
764       /* We treat button presses as scroll wheel events, so ignore the release */
765       if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5 ||
766           xevent->xbutton.button == 6 || xevent->xbutton.button ==7)
767         {
768           return_val = FALSE;
769           break;
770         }
771
772       event->button.type = GDK_BUTTON_RELEASE;
773       event->button.window = window;
774       event->button.time = xevent->xbutton.time;
775       event->button.x = xevent->xbutton.x + xoffset;
776       event->button.y = xevent->xbutton.y + yoffset;
777       event->button.x_root = (gfloat)xevent->xbutton.x_root;
778       event->button.y_root = (gfloat)xevent->xbutton.y_root;
779       event->button.axes = NULL;
780       event->button.state = (GdkModifierType) xevent->xbutton.state;
781       event->button.button = xevent->xbutton.button;
782       event->button.device = _gdk_core_pointer;
783       
784       break;
785       
786     case MotionNotify:
787       GDK_NOTE (EVENTS,
788                 g_message ("motion notify:\t\twindow: %ld  x,y: %d %d  hint: %s", 
789                            xevent->xmotion.window,
790                            xevent->xmotion.x, xevent->xmotion.y,
791                            (xevent->xmotion.is_hint) ? "true" : "false"));
792       
793       if (window_private == NULL ||
794           ((window_private->extension_events != 0) &&
795            _gdk_input_ignore_core))
796         {
797           return_val = FALSE;
798           break;
799         }
800       
801       event->motion.type = GDK_MOTION_NOTIFY;
802       event->motion.window = window;
803       event->motion.time = xevent->xmotion.time;
804       event->motion.x = xevent->xmotion.x + xoffset;
805       event->motion.y = xevent->xmotion.y + yoffset;
806       event->motion.x_root = (gfloat)xevent->xmotion.x_root;
807       event->motion.y_root = (gfloat)xevent->xmotion.y_root;
808       event->motion.axes = NULL;
809       event->motion.state = (GdkModifierType) xevent->xmotion.state;
810       event->motion.is_hint = xevent->xmotion.is_hint;
811       event->motion.device = _gdk_core_pointer;
812       
813       break;
814       
815     case EnterNotify:
816       GDK_NOTE (EVENTS,
817                 g_message ("enter notify:\t\twindow: %ld  detail: %d subwin: %ld",
818                            xevent->xcrossing.window,
819                            xevent->xcrossing.detail,
820                            xevent->xcrossing.subwindow));
821  
822       if (window_private == NULL)
823         {
824           return_val = FALSE;
825           break;
826         }
827       
828       /* Handle focusing (in the case where no window manager is running */
829       if (window &&
830           GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
831           xevent->xcrossing.detail != NotifyInferior &&
832           xevent->xcrossing.focus && !window_impl->has_focus)
833         {
834           gboolean had_focus = HAS_FOCUS (window_impl);
835           
836           window_impl->has_pointer_focus = TRUE;
837
838           if (HAS_FOCUS (window_impl) != had_focus)
839             generate_focus_event (window, TRUE);
840         }
841
842       /* Tell XInput stuff about it if appropriate */
843       if (window_private &&
844           !GDK_WINDOW_DESTROYED (window) &&
845           window_private->extension_events != 0)
846         _gdk_input_enter_event (&xevent->xcrossing, window);
847       
848       event->crossing.type = GDK_ENTER_NOTIFY;
849       event->crossing.window = window;
850       
851       /* If the subwindow field of the XEvent is non-NULL, then
852        *  lookup the corresponding GdkWindow.
853        */
854       if (xevent->xcrossing.subwindow != None)
855         event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
856       else
857         event->crossing.subwindow = NULL;
858       
859       event->crossing.time = xevent->xcrossing.time;
860       event->crossing.x = xevent->xcrossing.x + xoffset;
861       event->crossing.y = xevent->xcrossing.y + yoffset;
862       event->crossing.x_root = xevent->xcrossing.x_root;
863       event->crossing.y_root = xevent->xcrossing.y_root;
864       
865       /* Translate the crossing mode into Gdk terms.
866        */
867       switch (xevent->xcrossing.mode)
868         {
869         case NotifyNormal:
870           event->crossing.mode = GDK_CROSSING_NORMAL;
871           break;
872         case NotifyGrab:
873           event->crossing.mode = GDK_CROSSING_GRAB;
874           break;
875         case NotifyUngrab:
876           event->crossing.mode = GDK_CROSSING_UNGRAB;
877           break;
878         };
879       
880       /* Translate the crossing detail into Gdk terms.
881        */
882       switch (xevent->xcrossing.detail)
883         {
884         case NotifyInferior:
885           event->crossing.detail = GDK_NOTIFY_INFERIOR;
886           break;
887         case NotifyAncestor:
888           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
889           break;
890         case NotifyVirtual:
891           event->crossing.detail = GDK_NOTIFY_VIRTUAL;
892           break;
893         case NotifyNonlinear:
894           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
895           break;
896         case NotifyNonlinearVirtual:
897           event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
898           break;
899         default:
900           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
901           break;
902         }
903       
904       event->crossing.focus = xevent->xcrossing.focus;
905       event->crossing.state = xevent->xcrossing.state;
906   
907       break;
908       
909     case LeaveNotify:
910       GDK_NOTE (EVENTS, 
911                 g_message ("leave notify:\t\twindow: %ld  detail: %d subwin: %ld",
912                            xevent->xcrossing.window,
913                            xevent->xcrossing.detail, xevent->xcrossing.subwindow));
914
915       if (window_private == NULL)
916         {
917           return_val = FALSE;
918           break;
919         }
920       
921       /* Handle focusing (in the case where no window manager is running */
922       if (window &&
923           GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
924           xevent->xcrossing.detail != NotifyInferior &&
925           xevent->xcrossing.focus && !window_impl->has_focus)
926         {
927           gboolean had_focus = HAS_FOCUS (window_impl);
928           
929           window_impl->has_pointer_focus = FALSE;
930
931           if (HAS_FOCUS (window_impl) != had_focus)
932             generate_focus_event (window, FALSE);
933         }
934
935       event->crossing.type = GDK_LEAVE_NOTIFY;
936       event->crossing.window = window;
937       
938       /* If the subwindow field of the XEvent is non-NULL, then
939        *  lookup the corresponding GdkWindow.
940        */
941       if (xevent->xcrossing.subwindow != None)
942         event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
943       else
944         event->crossing.subwindow = NULL;
945       
946       event->crossing.time = xevent->xcrossing.time;
947       event->crossing.x = xevent->xcrossing.x + xoffset;
948       event->crossing.y = xevent->xcrossing.y + yoffset;
949       event->crossing.x_root = xevent->xcrossing.x_root;
950       event->crossing.y_root = xevent->xcrossing.y_root;
951       
952       /* Translate the crossing mode into Gdk terms.
953        */
954       switch (xevent->xcrossing.mode)
955         {
956         case NotifyNormal:
957           event->crossing.mode = GDK_CROSSING_NORMAL;
958           break;
959         case NotifyGrab:
960           event->crossing.mode = GDK_CROSSING_GRAB;
961           break;
962         case NotifyUngrab:
963           event->crossing.mode = GDK_CROSSING_UNGRAB;
964           break;
965         };
966       
967       /* Translate the crossing detail into Gdk terms.
968        */
969       switch (xevent->xcrossing.detail)
970         {
971         case NotifyInferior:
972           event->crossing.detail = GDK_NOTIFY_INFERIOR;
973           break;
974         case NotifyAncestor:
975           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
976           break;
977         case NotifyVirtual:
978           event->crossing.detail = GDK_NOTIFY_VIRTUAL;
979           break;
980         case NotifyNonlinear:
981           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
982           break;
983         case NotifyNonlinearVirtual:
984           event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
985           break;
986         default:
987           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
988           break;
989         }
990       
991       event->crossing.focus = xevent->xcrossing.focus;
992       event->crossing.state = xevent->xcrossing.state;
993       
994       break;
995       
996       /* We only care about focus events that indicate that _this_
997        * window (not a ancestor or child) got or lost the focus
998        */
999     case FocusIn:
1000       GDK_NOTE (EVENTS,
1001                 g_message ("focus in:\t\twindow: %ld", xevent->xfocus.window));
1002       
1003       if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
1004         {
1005           gboolean had_focus = HAS_FOCUS (window_impl);
1006           
1007           switch (xevent->xfocus.detail)
1008             {
1009             case NotifyAncestor:
1010             case NotifyNonlinear:
1011             case NotifyVirtual:
1012             case NotifyNonlinearVirtual:
1013               window_impl->has_focus = TRUE;
1014               break;
1015             case NotifyPointer:
1016               window_impl->has_pointer_focus = TRUE;
1017               break;
1018             case NotifyInferior:
1019             case NotifyPointerRoot:
1020             case NotifyDetailNone:
1021               break;
1022             }
1023
1024           if (HAS_FOCUS (window_impl) != had_focus)
1025             generate_focus_event (window, TRUE);
1026         }
1027       break;
1028     case FocusOut:
1029       GDK_NOTE (EVENTS,
1030                 g_message ("focus out:\t\twindow: %ld", xevent->xfocus.window));
1031
1032       if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
1033         {
1034           gboolean had_focus = HAS_FOCUS (window_impl);
1035             
1036           switch (xevent->xfocus.detail)
1037             {
1038             case NotifyAncestor:
1039             case NotifyNonlinear:
1040             case NotifyVirtual:
1041             case NotifyNonlinearVirtual:
1042               window_impl->has_focus = FALSE;
1043               break;
1044             case NotifyPointer:
1045               window_impl->has_pointer_focus = FALSE;
1046             break;
1047             case NotifyInferior:
1048             case NotifyPointerRoot:
1049             case NotifyDetailNone:
1050               break;
1051             }
1052
1053           if (HAS_FOCUS (window_impl) != had_focus)
1054             generate_focus_event (window, FALSE);
1055         }
1056       break;
1057
1058 #if 0      
1059           /* gdk_keyboard_grab() causes following events. These events confuse
1060            * the XIM focus, so ignore them.
1061            */
1062           if (xevent->xfocus.mode == NotifyGrab ||
1063               xevent->xfocus.mode == NotifyUngrab)
1064             break;
1065 #endif
1066
1067     case KeymapNotify:
1068       GDK_NOTE (EVENTS,
1069                 g_message ("keymap notify"));
1070
1071       /* Not currently handled */
1072       return_val = FALSE;
1073       break;
1074       
1075     case Expose:
1076       GDK_NOTE (EVENTS,
1077                 g_message ("expose:\t\twindow: %ld  %d  x,y: %d %d  w,h: %d %d%s",
1078                            xevent->xexpose.window, xevent->xexpose.count,
1079                            xevent->xexpose.x, xevent->xexpose.y,
1080                            xevent->xexpose.width, xevent->xexpose.height,
1081                            event->any.send_event ? " (send)" : ""));
1082       
1083       if (window_private == NULL)
1084         {
1085           return_val = FALSE;
1086           break;
1087         }
1088       
1089       {
1090         GdkRectangle expose_rect;
1091
1092         expose_rect.x = xevent->xexpose.x + xoffset;
1093         expose_rect.y = xevent->xexpose.y + yoffset;
1094         expose_rect.width = xevent->xexpose.width;
1095         expose_rect.height = xevent->xexpose.height;
1096
1097         if (return_exposes)
1098           {
1099             event->expose.type = GDK_EXPOSE;
1100             event->expose.area = expose_rect;
1101             event->expose.region = gdk_region_rectangle (&expose_rect);
1102             event->expose.window = window;
1103             event->expose.count = xevent->xexpose.count;
1104
1105             return_val = TRUE;
1106           }
1107         else
1108           {
1109             _gdk_window_process_expose (window, xevent->xexpose.serial, &expose_rect);
1110
1111             return_val = FALSE;
1112           }
1113         
1114         return_val = FALSE;
1115       }
1116         
1117       break;
1118       
1119     case GraphicsExpose:
1120       {
1121         GdkRectangle expose_rect;
1122
1123         GDK_NOTE (EVENTS,
1124                   g_message ("graphics expose:\tdrawable: %ld",
1125                              xevent->xgraphicsexpose.drawable));
1126  
1127         if (window_private == NULL)
1128           {
1129             return_val = FALSE;
1130             break;
1131           }
1132         
1133         expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
1134         expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
1135         expose_rect.width = xevent->xgraphicsexpose.width;
1136         expose_rect.height = xevent->xgraphicsexpose.height;
1137             
1138         if (return_exposes)
1139           {
1140             event->expose.type = GDK_EXPOSE;
1141             event->expose.area = expose_rect;
1142             event->expose.region = gdk_region_rectangle (&expose_rect);
1143             event->expose.window = window;
1144             event->expose.count = xevent->xgraphicsexpose.count;
1145
1146             return_val = TRUE;
1147           }
1148         else
1149           {
1150             _gdk_window_process_expose (window, xevent->xgraphicsexpose.serial, &expose_rect);
1151             
1152             return_val = FALSE;
1153           }
1154         
1155       }
1156       break;
1157       
1158     case NoExpose:
1159       GDK_NOTE (EVENTS,
1160                 g_message ("no expose:\t\tdrawable: %ld",
1161                            xevent->xnoexpose.drawable));
1162       
1163       event->no_expose.type = GDK_NO_EXPOSE;
1164       event->no_expose.window = window;
1165       
1166       break;
1167       
1168     case VisibilityNotify:
1169 #ifdef G_ENABLE_DEBUG
1170       if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
1171         switch (xevent->xvisibility.state)
1172           {
1173           case VisibilityFullyObscured:
1174             g_message ("visibility notify:\twindow: %ld  none",
1175                        xevent->xvisibility.window);
1176             break;
1177           case VisibilityPartiallyObscured:
1178             g_message ("visibility notify:\twindow: %ld  partial",
1179                        xevent->xvisibility.window);
1180             break;
1181           case VisibilityUnobscured:
1182             g_message ("visibility notify:\twindow: %ld  full",
1183                        xevent->xvisibility.window);
1184             break;
1185           }
1186 #endif /* G_ENABLE_DEBUG */
1187       
1188       if (window_private == NULL)
1189         {
1190           return_val = FALSE;
1191           break;
1192         }
1193       
1194       event->visibility.type = GDK_VISIBILITY_NOTIFY;
1195       event->visibility.window = window;
1196       
1197       switch (xevent->xvisibility.state)
1198         {
1199         case VisibilityFullyObscured:
1200           event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
1201           break;
1202           
1203         case VisibilityPartiallyObscured:
1204           event->visibility.state = GDK_VISIBILITY_PARTIAL;
1205           break;
1206           
1207         case VisibilityUnobscured:
1208           event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
1209           break;
1210         }
1211       
1212       break;
1213       
1214     case CreateNotify:
1215       GDK_NOTE (EVENTS,
1216                 g_message ("create notify:\twindow: %ld  x,y: %d %d     w,h: %d %d  b-w: %d  parent: %ld         ovr: %d",
1217                            xevent->xcreatewindow.window,
1218                            xevent->xcreatewindow.x,
1219                            xevent->xcreatewindow.y,
1220                            xevent->xcreatewindow.width,
1221                            xevent->xcreatewindow.height,
1222                            xevent->xcreatewindow.border_width,
1223                            xevent->xcreatewindow.parent,
1224                            xevent->xcreatewindow.override_redirect));
1225       /* not really handled */
1226       break;
1227       
1228     case DestroyNotify:
1229       GDK_NOTE (EVENTS,
1230                 g_message ("destroy notify:\twindow: %ld",
1231                            xevent->xdestroywindow.window));
1232
1233       /* Ignore DestroyNotify from SubstructureNotifyMask */
1234       if (xevent->xdestroywindow.window == xevent->xdestroywindow.event)
1235         {
1236           event->any.type = GDK_DESTROY;
1237           event->any.window = window;
1238           
1239           return_val = window_private && !GDK_WINDOW_DESTROYED (window);
1240           
1241           if (window && GDK_WINDOW_XID (window) != GDK_ROOT_WINDOW())
1242             gdk_window_destroy_notify (window);
1243         }
1244       else
1245         return_val = FALSE;
1246       break;
1247       
1248     case UnmapNotify:
1249       GDK_NOTE (EVENTS,
1250                 g_message ("unmap notify:\t\twindow: %ld",
1251                            xevent->xmap.window));
1252       
1253       event->any.type = GDK_UNMAP;
1254       event->any.window = window;      
1255
1256       /* If we are shown (not withdrawn) and get an unmap, it means we
1257        * were iconified in the X sense. If we are withdrawn, and get
1258        * an unmap, it means we hid the window ourselves, so we
1259        * will have already flipped the iconified bit off.
1260        */
1261       if (window && GDK_WINDOW_IS_MAPPED (window))
1262         gdk_synthesize_window_state (window,
1263                                      0,
1264                                      GDK_WINDOW_STATE_ICONIFIED);
1265
1266       _gdk_xgrab_check_unmap (window, xevent->xany.serial);
1267       
1268       break;
1269       
1270     case MapNotify:
1271       GDK_NOTE (EVENTS,
1272                 g_message ("map notify:\t\twindow: %ld",
1273                            xevent->xmap.window));
1274       
1275       event->any.type = GDK_MAP;
1276       event->any.window = window;
1277
1278       /* Unset iconified if it was set */
1279       if (window && (((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_ICONIFIED))
1280         gdk_synthesize_window_state (window,
1281                                      GDK_WINDOW_STATE_ICONIFIED,
1282                                      0);
1283       
1284       break;
1285       
1286     case ReparentNotify:
1287       GDK_NOTE (EVENTS,
1288                 g_message ("reparent notify:\twindow: %ld  x,y: %d %d  parent: %ld      ovr: %d",
1289                            xevent->xreparent.window,
1290                            xevent->xreparent.x,
1291                            xevent->xreparent.y,
1292                            xevent->xreparent.parent,
1293                            xevent->xreparent.override_redirect));
1294
1295       /* Not currently handled */
1296       return_val = FALSE;
1297       break;
1298       
1299     case ConfigureNotify:
1300       GDK_NOTE (EVENTS,
1301                 g_message ("configure notify:\twindow: %ld  x,y: %d %d  w,h: %d %d  b-w: %d  above: %ld  ovr: %d%s",
1302                            xevent->xconfigure.window,
1303                            xevent->xconfigure.x,
1304                            xevent->xconfigure.y,
1305                            xevent->xconfigure.width,
1306                            xevent->xconfigure.height,
1307                            xevent->xconfigure.border_width,
1308                            xevent->xconfigure.above,
1309                            xevent->xconfigure.override_redirect,
1310                            !window
1311                            ? " (discarding)"
1312                            : GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD
1313                            ? " (discarding child)"
1314                            : ""));
1315       if (window &&
1316           !GDK_WINDOW_DESTROYED (window) &&
1317           (window_private->extension_events != 0))
1318         _gdk_input_configure_event (&xevent->xconfigure, window);
1319
1320       if (!window ||
1321           GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
1322           GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
1323         return_val = FALSE;
1324       else
1325         {
1326           event->configure.type = GDK_CONFIGURE;
1327           event->configure.window = window;
1328           event->configure.width = xevent->xconfigure.width;
1329           event->configure.height = xevent->xconfigure.height;
1330           
1331           if (!xevent->xconfigure.send_event && 
1332               !GDK_WINDOW_DESTROYED (window))
1333             {
1334               gint tx = 0;
1335               gint ty = 0;
1336               Window child_window = 0;
1337
1338               gdk_error_trap_push ();
1339               if (XTranslateCoordinates (GDK_DRAWABLE_XDISPLAY (window),
1340                                          GDK_DRAWABLE_XID (window),
1341                                          _gdk_root_window,
1342                                          0, 0,
1343                                          &tx, &ty,
1344                                          &child_window))
1345                 {
1346                   if (!gdk_error_trap_pop ())
1347                     {
1348                       event->configure.x = tx;
1349                       event->configure.y = ty;
1350                     }
1351                 }
1352               else
1353                 gdk_error_trap_pop ();
1354             }
1355           else
1356             {
1357               event->configure.x = xevent->xconfigure.x;
1358               event->configure.y = xevent->xconfigure.y;
1359             }
1360           window_private->x = event->configure.x;
1361           window_private->y = event->configure.y;
1362           GDK_WINDOW_IMPL_X11 (window_private->impl)->width = xevent->xconfigure.width;
1363           GDK_WINDOW_IMPL_X11 (window_private->impl)->height = xevent->xconfigure.height;
1364           if (window_private->resize_count >= 1)
1365             {
1366               window_private->resize_count -= 1;
1367
1368               if (window_private->resize_count == 0 &&
1369                   window == _gdk_moveresize_window)
1370                 _gdk_moveresize_configure_done ();
1371             }
1372         }
1373       break;
1374       
1375     case PropertyNotify:
1376       GDK_NOTE (EVENTS,
1377                 g_message ("property notify:\twindow: %ld, atom(%ld): %s%s%s",
1378                            xevent->xproperty.window,
1379                            xevent->xproperty.atom,
1380                            "\"",
1381                            gdk_x11_get_xatom_name (xevent->xproperty.atom),
1382                            "\""));
1383
1384       if (window_private == NULL)
1385         {
1386           return_val = FALSE;
1387           break;
1388         }
1389       
1390       event->property.type = GDK_PROPERTY_NOTIFY;
1391       event->property.window = window;
1392       event->property.atom = gdk_x11_xatom_to_atom (xevent->xproperty.atom);
1393       event->property.time = xevent->xproperty.time;
1394       event->property.state = xevent->xproperty.state;
1395
1396       if (wm_state_atom == 0)
1397         wm_state_atom = gdk_x11_get_xatom_by_name ("_NET_WM_STATE");
1398
1399       if (wm_desktop_atom == 0)
1400         wm_desktop_atom = gdk_x11_get_xatom_by_name ("_NET_WM_DESKTOP");
1401       
1402       if (xevent->xproperty.atom == wm_state_atom || 
1403           xevent->xproperty.atom == wm_desktop_atom)
1404         {
1405           /* If window state changed, then synthesize those events. */
1406           gdk_check_wm_state_changed (event->property.window);
1407         }
1408       
1409       break;
1410       
1411     case SelectionClear:
1412       GDK_NOTE (EVENTS,
1413                 g_message ("selection clear:\twindow: %ld",
1414                            xevent->xproperty.window));
1415
1416       if (_gdk_selection_filter_clear_event (&xevent->xselectionclear))
1417         {
1418           event->selection.type = GDK_SELECTION_CLEAR;
1419           event->selection.window = window;
1420           event->selection.selection = gdk_x11_xatom_to_atom (xevent->xselectionclear.selection);
1421           event->selection.time = xevent->xselectionclear.time;
1422         }
1423       else
1424         return_val = FALSE;
1425           
1426       break;
1427       
1428     case SelectionRequest:
1429       GDK_NOTE (EVENTS,
1430                 g_message ("selection request:\twindow: %ld",
1431                            xevent->xproperty.window));
1432       
1433       event->selection.type = GDK_SELECTION_REQUEST;
1434       event->selection.window = window;
1435       event->selection.selection = gdk_x11_xatom_to_atom (xevent->xselectionrequest.selection);
1436       event->selection.target = gdk_x11_xatom_to_atom (xevent->xselectionrequest.target);
1437       event->selection.property = gdk_x11_xatom_to_atom (xevent->xselectionrequest.property);
1438       event->selection.requestor = xevent->xselectionrequest.requestor;
1439       event->selection.time = xevent->xselectionrequest.time;
1440       
1441       break;
1442       
1443     case SelectionNotify:
1444       GDK_NOTE (EVENTS,
1445                 g_message ("selection notify:\twindow: %ld",
1446                            xevent->xproperty.window));
1447       
1448       
1449       event->selection.type = GDK_SELECTION_NOTIFY;
1450       event->selection.window = window;
1451       event->selection.selection = gdk_x11_xatom_to_atom (xevent->xselection.selection);
1452       event->selection.target = gdk_x11_xatom_to_atom (xevent->xselection.target);
1453       event->selection.property = gdk_x11_xatom_to_atom (xevent->xselection.property);
1454       event->selection.time = xevent->xselection.time;
1455       
1456       break;
1457       
1458     case ColormapNotify:
1459       GDK_NOTE (EVENTS,
1460                 g_message ("colormap notify:\twindow: %ld",
1461                            xevent->xcolormap.window));
1462       
1463       /* Not currently handled */
1464       return_val = FALSE;
1465       break;
1466       
1467     case ClientMessage:
1468       {
1469         GList *tmp_list;
1470         GdkFilterReturn result = GDK_FILTER_CONTINUE;
1471         GdkAtom message_type = gdk_x11_xatom_to_atom (xevent->xclient.message_type);
1472
1473         GDK_NOTE (EVENTS,
1474                   g_message ("client message:\twindow: %ld",
1475                              xevent->xclient.window));
1476         
1477         tmp_list = client_filters;
1478         while (tmp_list)
1479           {
1480             GdkClientFilter *filter = tmp_list->data;
1481             if (filter->type == message_type)
1482               {
1483                 result = (*filter->function) (xevent, event, filter->data);
1484                 break;
1485               }
1486             
1487             tmp_list = tmp_list->next;
1488           }
1489
1490         switch (result)
1491           {
1492           case GDK_FILTER_REMOVE:
1493             return_val = FALSE;
1494             break;
1495           case GDK_FILTER_TRANSLATE:
1496             return_val = TRUE;
1497             break;
1498           case GDK_FILTER_CONTINUE:
1499             /* Send unknown ClientMessage's on to Gtk for it to use */
1500             if (window_private == NULL)
1501               {
1502                 return_val = FALSE;
1503               }
1504             else
1505               {
1506                 event->client.type = GDK_CLIENT_EVENT;
1507                 event->client.window = window;
1508                 event->client.message_type = message_type;
1509                 event->client.data_format = xevent->xclient.format;
1510                 memcpy(&event->client.data, &xevent->xclient.data,
1511                        sizeof(event->client.data));
1512               }
1513             break;
1514           }
1515       }
1516       
1517       break;
1518       
1519     case MappingNotify:
1520       GDK_NOTE (EVENTS,
1521                 g_message ("mapping notify"));
1522       
1523       /* Let XLib know that there is a new keyboard mapping.
1524        */
1525       XRefreshKeyboardMapping (&xevent->xmapping);
1526       ++_gdk_keymap_serial;
1527       return_val = FALSE;
1528       break;
1529
1530     default:
1531 #ifdef HAVE_XKB
1532       if (xevent->type == _gdk_xkb_event_type)
1533         {
1534           XkbEvent *xkb_event = (XkbEvent *)xevent;
1535
1536           switch (xkb_event->any.xkb_type)
1537             {
1538             case XkbMapNotify:
1539               ++_gdk_keymap_serial;
1540               return_val = FALSE;
1541               break;
1542               
1543             case XkbStateNotify:
1544               _gdk_keymap_state_changed ();
1545               break;
1546             }
1547         }
1548       else
1549 #endif
1550         {
1551           /* something else - (e.g., a Xinput event) */
1552           
1553           if (window_private &&
1554               !GDK_WINDOW_DESTROYED (window_private) &&
1555               (window_private->extension_events != 0))
1556             return_val = _gdk_input_other_event(event, xevent, window);
1557           else
1558             return_val = FALSE;
1559           
1560           break;
1561         }
1562     }
1563
1564  done:
1565   if (return_val)
1566     {
1567       if (event->any.window)
1568         gdk_window_ref (event->any.window);
1569       if (((event->any.type == GDK_ENTER_NOTIFY) ||
1570            (event->any.type == GDK_LEAVE_NOTIFY)) &&
1571           (event->crossing.subwindow != NULL))
1572         gdk_window_ref (event->crossing.subwindow);
1573     }
1574   else
1575     {
1576       /* Mark this event as having no resources to be freed */
1577       event->any.window = NULL;
1578       event->any.type = GDK_NOTHING;
1579     }
1580   
1581   if (window)
1582     gdk_window_unref (window);
1583   
1584   return return_val;
1585 }
1586
1587 static GdkFilterReturn
1588 gdk_wm_protocols_filter (GdkXEvent *xev,
1589                          GdkEvent  *event,
1590                          gpointer data)
1591 {
1592   XEvent *xevent = (XEvent *)xev;
1593
1594   if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name ("WM_DELETE_WINDOW"))
1595     {
1596   /* The delete window request specifies a window
1597    *  to delete. We don't actually destroy the
1598    *  window because "it is only a request". (The
1599    *  window might contain vital data that the
1600    *  program does not want destroyed). Instead
1601    *  the event is passed along to the program,
1602    *  which should then destroy the window.
1603    */
1604       GDK_NOTE (EVENTS,
1605                 g_message ("delete window:\t\twindow: %ld",
1606                            xevent->xclient.window));
1607       
1608       event->any.type = GDK_DELETE;
1609
1610       return GDK_FILTER_TRANSLATE;
1611     }
1612   else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name ("WM_TAKE_FOCUS"))
1613     {
1614       GdkWindow *win = event->any.window;
1615       Window focus_win = GDK_WINDOW_IMPL_X11(((GdkWindowObject *)win)->impl)->focus_window;
1616
1617       /* There is no way of knowing reliably whether we are viewable so we need
1618        * to trap errors so we don't cause a BadMatch.
1619        */
1620       gdk_error_trap_push ();
1621       XSetInputFocus (GDK_WINDOW_XDISPLAY (win),
1622                       focus_win,
1623                       RevertToParent,
1624                       xevent->xclient.data.l[1]);
1625       XSync (GDK_WINDOW_XDISPLAY (win), False);
1626       gdk_error_trap_pop ();
1627     }
1628   else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name ("_NET_WM_PING"))
1629     {
1630       XEvent xev = *xevent;
1631       
1632       xev.xclient.window = _gdk_root_window;
1633       XSendEvent (gdk_display, _gdk_root_window, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
1634     }
1635
1636   return GDK_FILTER_REMOVE;
1637 }
1638
1639 #if 0
1640 static Bool
1641 gdk_event_get_type (Display  *display,
1642                     XEvent   *xevent,
1643                     XPointer  arg)
1644 {
1645   GdkEvent event;
1646   GdkPredicate *pred;
1647   
1648   if (gdk_event_translate (&event, xevent, FALSE))
1649     {
1650       pred = (GdkPredicate*) arg;
1651       return (* pred->func) (&event, pred->data);
1652     }
1653   
1654   return FALSE;
1655 }
1656 #endif
1657
1658 void
1659 _gdk_events_queue (void)
1660 {
1661   GList *node;
1662   GdkEvent *event;
1663   XEvent xevent;
1664
1665   while (!_gdk_event_queue_find_first() && XPending (gdk_display))
1666     {
1667       XNextEvent (gdk_display, &xevent);
1668
1669       switch (xevent.type)
1670         {
1671         case KeyPress:
1672         case KeyRelease:
1673           break;
1674         default:
1675           if (XFilterEvent (&xevent, None))
1676             continue;
1677         }
1678       
1679       event = _gdk_event_new ();
1680       
1681       event->any.type = GDK_NOTHING;
1682       event->any.window = NULL;
1683       event->any.send_event = xevent.xany.send_event ? TRUE : FALSE;
1684
1685       ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
1686
1687       _gdk_event_queue_append (event);
1688       node = _gdk_queued_tail;
1689
1690       if (gdk_event_translate (event, &xevent, FALSE))
1691         {
1692           ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
1693         }
1694       else
1695         {
1696           _gdk_event_queue_remove_link (node);
1697           g_list_free_1 (node);
1698           gdk_event_free (event);
1699         }
1700     }
1701 }
1702
1703 static gboolean  
1704 gdk_event_prepare (GSource  *source,
1705                    gint     *timeout)
1706 {
1707   gboolean retval;
1708   
1709   GDK_THREADS_ENTER ();
1710
1711   *timeout = -1;
1712
1713   retval = (_gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
1714
1715   GDK_THREADS_LEAVE ();
1716
1717   return retval;
1718 }
1719
1720 static gboolean  
1721 gdk_event_check (GSource  *source) 
1722 {
1723   gboolean retval;
1724   
1725   GDK_THREADS_ENTER ();
1726
1727   if (event_poll_fd.revents & G_IO_IN)
1728     retval = (_gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
1729   else
1730     retval = FALSE;
1731
1732   GDK_THREADS_LEAVE ();
1733
1734   return retval;
1735 }
1736
1737 static gboolean  
1738 gdk_event_dispatch (GSource    *source,
1739                     GSourceFunc callback,
1740                     gpointer    user_data)
1741 {
1742   GdkEvent *event;
1743  
1744   GDK_THREADS_ENTER ();
1745
1746   _gdk_events_queue();
1747   event = _gdk_event_unqueue();
1748
1749   if (event)
1750     {
1751       if (_gdk_event_func)
1752         (*_gdk_event_func) (event, _gdk_event_data);
1753       
1754       gdk_event_free (event);
1755     }
1756   
1757   GDK_THREADS_LEAVE ();
1758
1759   return TRUE;
1760 }
1761
1762 /* Sends a ClientMessage to all toplevel client windows */
1763 gboolean
1764 gdk_event_send_client_message (GdkEvent *event, guint32 xid)
1765 {
1766   XEvent sev;
1767   
1768   g_return_val_if_fail(event != NULL, FALSE);
1769   
1770   /* Set up our event to send, with the exception of its target window */
1771   sev.xclient.type = ClientMessage;
1772   sev.xclient.display = gdk_display;
1773   sev.xclient.format = event->client.data_format;
1774   sev.xclient.window = xid;
1775   memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
1776   sev.xclient.message_type = gdk_x11_atom_to_xatom (event->client.message_type);
1777   
1778   return gdk_send_xevent (xid, False, NoEventMask, &sev);
1779 }
1780
1781 /* Sends a ClientMessage to all toplevel client windows */
1782 gboolean
1783 gdk_event_send_client_message_to_all_recurse (XEvent  *xev, 
1784                                               guint32  xid,
1785                                               guint    level)
1786 {
1787   static Atom wm_state_atom = None;
1788   Atom type = None;
1789   int format;
1790   unsigned long nitems, after;
1791   unsigned char *data;
1792   Window *ret_children, ret_root, ret_parent;
1793   unsigned int ret_nchildren;
1794   gboolean send = FALSE;
1795   gboolean found = FALSE;
1796   gboolean result = FALSE;
1797   int i;
1798
1799   if (!wm_state_atom)
1800     wm_state_atom = gdk_x11_get_xatom_by_name ("WM_STATE");
1801
1802   gdk_error_trap_push ();
1803   
1804   if (XGetWindowProperty (gdk_display, xid, wm_state_atom, 0, 0, False, AnyPropertyType,
1805                           &type, &format, &nitems, &after, &data) != Success)
1806     goto out;
1807
1808   if (type)
1809     {
1810       send = TRUE;
1811       XFree (data);
1812     }
1813   else
1814     {
1815       /* OK, we're all set, now let's find some windows to send this to */
1816       if (!XQueryTree (gdk_display, xid, &ret_root, &ret_parent,
1817                        &ret_children, &ret_nchildren))
1818         goto out;
1819
1820       for(i = 0; i < ret_nchildren; i++)
1821         if (gdk_event_send_client_message_to_all_recurse (xev, ret_children[i], level + 1))
1822           found = TRUE;
1823
1824       XFree (ret_children);
1825     }
1826
1827   if (send || (!found && (level == 1)))
1828     {
1829       xev->xclient.window = xid;
1830       gdk_send_xevent (xid, False, NoEventMask, xev);
1831     }
1832
1833   result = send || found;
1834
1835  out:
1836   gdk_error_trap_pop ();
1837
1838   return result;
1839 }
1840
1841 void
1842 gdk_event_send_clientmessage_toall (GdkEvent *event)
1843 {
1844   XEvent sev;
1845
1846   g_return_if_fail(event != NULL);
1847   
1848   /* Set up our event to send, with the exception of its target window */
1849   sev.xclient.type = ClientMessage;
1850   sev.xclient.display = gdk_display;
1851   sev.xclient.format = event->client.data_format;
1852   memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
1853   sev.xclient.message_type = gdk_x11_atom_to_xatom (event->client.message_type);
1854
1855   gdk_event_send_client_message_to_all_recurse(&sev, _gdk_root_window, 0);
1856 }
1857
1858 /*
1859  *--------------------------------------------------------------
1860  * gdk_flush
1861  *
1862  *   Flushes the Xlib output buffer and then waits
1863  *   until all requests have been received and processed
1864  *   by the X server. The only real use for this function
1865  *   is in dealing with XShm.
1866  *
1867  * Arguments:
1868  *
1869  * Results:
1870  *
1871  * Side effects:
1872  *
1873  *--------------------------------------------------------------
1874  */
1875
1876 void
1877 gdk_flush (void)
1878 {
1879   XSync (gdk_display, False);
1880 }
1881
1882 static Atom timestamp_prop_atom = 0;
1883
1884 static Bool
1885 timestamp_predicate (Display *display,
1886                      XEvent  *xevent,
1887                      XPointer arg)
1888 {
1889   Window xwindow = GPOINTER_TO_UINT (arg);
1890
1891   if (xevent->type == PropertyNotify &&
1892       xevent->xproperty.window == xwindow &&
1893       xevent->xproperty.atom == timestamp_prop_atom)
1894     return True;
1895
1896   return False;
1897 }
1898
1899 /**
1900  * gdk_x11_get_server_time:
1901  * @window: a #GdkWindow, used for communication with the server.
1902  *          The window must have GDK_PROPERTY_CHANGE_MASK in its
1903  *          events mask or a hang will result.
1904  * 
1905  * Routine to get the current X server time stamp. 
1906  * 
1907  * Return value: the time stamp.
1908  **/
1909 guint32
1910 gdk_x11_get_server_time (GdkWindow *window)
1911 {
1912   Display *xdisplay;
1913   Window   xwindow;
1914   guchar c = 'a';
1915   XEvent xevent;
1916
1917   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
1918   g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
1919
1920   if (!timestamp_prop_atom)
1921     timestamp_prop_atom = gdk_x11_get_xatom_by_name ("GDK_TIMESTAMP_PROP");
1922
1923   xdisplay = GDK_WINDOW_XDISPLAY (window);
1924   xwindow = GDK_WINDOW_XWINDOW (window);
1925   
1926   XChangeProperty (xdisplay, xwindow,
1927                    timestamp_prop_atom, timestamp_prop_atom,
1928                    8, PropModeReplace, &c, 1);
1929
1930   XIfEvent (xdisplay, &xevent,
1931             timestamp_predicate, GUINT_TO_POINTER(xwindow));
1932
1933   return xevent.xproperty.time;
1934 }
1935
1936
1937 /**
1938  * gdk_net_wm_supports:
1939  * @property: a property atom
1940  * 
1941  * This function is specific to the X11 backend of GDK, and indicates
1942  * whether the window manager supports a certain hint from the
1943  * Extended Window Manager Hints Specification. You can find this
1944  * specification on http://www.freedesktop.org.
1945  *
1946  * When using this function, keep in mind that the window manager
1947  * can change over time; so you shouldn't use this function in
1948  * a way that impacts persistent application state. A common bug
1949  * is that your application can start up before the window manager
1950  * does when the user logs in, and before the window manager starts
1951  * gdk_net_wm_supports() will return %FALSE for every property.
1952  * 
1953  * Return value: %TRUE if the window manager supports @property
1954  **/
1955 gboolean
1956 gdk_net_wm_supports (GdkAtom property)
1957 {
1958   static Atom wmspec_check_atom = 0;
1959   static Atom wmspec_supported_atom = 0;
1960   static Atom *atoms = NULL;
1961   static gulong n_atoms = 0;
1962   Atom xproperty = gdk_x11_atom_to_xatom (property);
1963   Atom type;
1964   gint format;
1965   gulong nitems;
1966   gulong bytes_after;
1967   Window *xwindow;
1968   gulong i;
1969
1970   if (wmspec_check_window != None)
1971     {
1972       if (atoms == NULL)
1973         return FALSE;
1974
1975       i = 0;
1976       while (i < n_atoms)
1977         {
1978           if (atoms[i] == xproperty)
1979             return TRUE;
1980           
1981           ++i;
1982         }
1983
1984       return FALSE;
1985     }
1986
1987   if (atoms)
1988     XFree (atoms);
1989
1990   atoms = NULL;
1991   n_atoms = 0;
1992   
1993   /* This function is very slow on every call if you are not running a
1994    * spec-supporting WM. For now not optimized, because it isn't in
1995    * any critical code paths, but if you used it somewhere that had to
1996    * be fast you want to avoid "GTK is slow with old WMs" complaints.
1997    * Probably at that point the function should be changed to query
1998    * _NET_SUPPORTING_WM_CHECK only once every 10 seconds or something.
1999    */
2000   
2001   if (wmspec_check_atom == 0)
2002     wmspec_check_atom = gdk_x11_get_xatom_by_name ("_NET_SUPPORTING_WM_CHECK");
2003       
2004   if (wmspec_supported_atom == 0)
2005     wmspec_supported_atom = gdk_x11_get_xatom_by_name ("_NET_SUPPORTED");
2006   
2007   XGetWindowProperty (gdk_display, _gdk_root_window,
2008                       wmspec_check_atom, 0, G_MAXLONG,
2009                       False, XA_WINDOW, &type, &format, &nitems,
2010                       &bytes_after, (guchar **)&xwindow);
2011
2012   if (type != XA_WINDOW)
2013     return FALSE;
2014
2015   gdk_error_trap_push ();
2016
2017   /* Find out if this WM goes away, so we can reset everything. */
2018   XSelectInput (gdk_display, *xwindow,
2019                 StructureNotifyMask);
2020   
2021   gdk_flush ();
2022   
2023   if (gdk_error_trap_pop ())
2024     {
2025       XFree (xwindow);
2026       return FALSE;
2027     }
2028
2029   XGetWindowProperty (gdk_display, _gdk_root_window,
2030                       wmspec_supported_atom, 0, G_MAXLONG,
2031                       False, XA_ATOM, &type, &format, &n_atoms,
2032                       &bytes_after, (guchar **)&atoms);
2033   
2034   if (type != XA_ATOM)
2035     return FALSE;
2036   
2037   wmspec_check_window = *xwindow;
2038   XFree (xwindow);
2039   
2040   /* since wmspec_check_window != None this isn't infinite. ;-) */
2041   return gdk_net_wm_supports (property);
2042 }
2043
2044 static struct
2045 {
2046   const char *xsettings_name;
2047   const char *gdk_name;
2048 } settings_map[] = {
2049   { "Net/DoubleClickTime", "gtk-double-click-time" },
2050   { "Net/DndDragThreshold", "gtk-dnd-drag-threshold" },
2051   { "Gtk/CanChangeAccels", "gtk-can-change-accels" },
2052   { "Gtk/ColorPalette", "gtk-color-palette" },
2053   { "Gtk/FontName", "gtk-font-name" },
2054   { "Gtk/KeyThemeName", "gtk-key-theme-name" },
2055   { "Gtk/ToolbarStyle", "gtk-toolbar-style" },
2056   { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
2057   { "Net/CursorBlink", "gtk-cursor-blink" },
2058   { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
2059   { "Net/ThemeName", "gtk-theme-name" }
2060 };
2061
2062 static void
2063 gdk_xsettings_notify_cb (const char       *name,
2064                          XSettingsAction   action,
2065                          XSettingsSetting *setting,
2066                          void             *data)
2067 {
2068   GdkEvent new_event;
2069   int i;
2070
2071   new_event.type = GDK_SETTING;
2072   new_event.setting.window = NULL;
2073   new_event.setting.send_event = FALSE;
2074   new_event.setting.name = NULL;
2075
2076   for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
2077     if (strcmp (settings_map[i].xsettings_name, name) == 0)
2078       {
2079         new_event.setting.name = g_strdup (settings_map[i].gdk_name);
2080         break;
2081       }
2082
2083   if (!new_event.setting.name)
2084     return;
2085   
2086   switch (action)
2087     {
2088     case XSETTINGS_ACTION_NEW:
2089       new_event.setting.action = GDK_SETTING_ACTION_NEW;
2090       break;
2091     case XSETTINGS_ACTION_CHANGED:
2092       new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
2093       break;
2094     case XSETTINGS_ACTION_DELETED:
2095       new_event.setting.action = GDK_SETTING_ACTION_DELETED;
2096       break;
2097     }
2098
2099   gdk_event_put (&new_event);
2100 }
2101
2102 static gboolean
2103 check_transform (const gchar *xsettings_name,
2104                  GType        src_type,
2105                  GType        dest_type)
2106 {
2107   if (!g_value_type_transformable (src_type, dest_type))
2108     {
2109       g_warning ("Cannot tranform xsetting %s of type %s to type %s\n",
2110                  xsettings_name,
2111                  g_type_name (src_type),
2112                  g_type_name (dest_type));
2113       return FALSE;
2114     }
2115   else
2116     return TRUE;
2117 }
2118
2119 gboolean
2120 gdk_setting_get (const gchar *name,
2121                  GValue      *value)
2122 {
2123   const char *xsettings_name = NULL;
2124   XSettingsResult result;
2125   XSettingsSetting *setting;
2126   gboolean success = FALSE;
2127   gint i;
2128   GValue tmp_val = { 0, };
2129
2130   for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
2131     if (strcmp (settings_map[i].gdk_name, name) == 0)
2132       {
2133         xsettings_name = settings_map[i].xsettings_name;
2134         break;
2135       }
2136
2137   if (!xsettings_name)
2138     return FALSE;
2139
2140   result = xsettings_client_get_setting (xsettings_client, xsettings_name, &setting);
2141   if (result != XSETTINGS_SUCCESS)
2142     return FALSE;
2143
2144   switch (setting->type)
2145     {
2146     case XSETTINGS_TYPE_INT:
2147       if (check_transform (xsettings_name, G_TYPE_INT, G_VALUE_TYPE (value)))
2148         {
2149           g_value_init (&tmp_val, G_TYPE_INT);
2150           g_value_set_int (&tmp_val, setting->data.v_int);
2151           g_value_transform (&tmp_val, value);
2152
2153           success = TRUE;
2154         }
2155       break;
2156     case XSETTINGS_TYPE_STRING:
2157       if (check_transform (xsettings_name, G_TYPE_STRING, G_VALUE_TYPE (value)))
2158         {
2159           g_value_init (&tmp_val, G_TYPE_STRING);
2160           g_value_set_string (&tmp_val, setting->data.v_string);
2161           g_value_transform (&tmp_val, value);
2162
2163           success = TRUE;
2164         }
2165       break;
2166     case XSETTINGS_TYPE_COLOR:
2167       if (!check_transform (xsettings_name, GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
2168         {
2169           GdkColor color;
2170           
2171           g_value_init (&tmp_val, GDK_TYPE_COLOR);
2172
2173           color.pixel = 0;
2174           color.red = setting->data.v_color.red;
2175           color.green = setting->data.v_color.green;
2176           color.blue = setting->data.v_color.blue;
2177           
2178           g_value_set_boxed (&tmp_val, &color);
2179           
2180           g_value_transform (&tmp_val, value);
2181           
2182           success = TRUE;
2183         }
2184       break;
2185     }
2186   
2187   g_value_unset (&tmp_val);
2188
2189   xsettings_setting_free (setting);
2190
2191   return success;
2192 }
2193
2194 static GdkFilterReturn 
2195 gdk_xsettings_client_event_filter (GdkXEvent *xevent,
2196                                    GdkEvent  *event,
2197                                    gpointer   data)
2198 {
2199   if (xsettings_client_process_event (xsettings_client, (XEvent *)xevent))
2200     return GDK_FILTER_REMOVE;
2201   else
2202     return GDK_FILTER_CONTINUE;
2203 }
2204
2205 static void 
2206 gdk_xsettings_watch_cb (Window window,
2207                         Bool   is_start,
2208                         long   mask,
2209                         void  *cb_data)
2210 {
2211   GdkWindow *gdkwin;
2212
2213   gdkwin = gdk_window_lookup (window);
2214   if (is_start)
2215     gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, NULL);
2216   else
2217     gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, NULL);
2218 }