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