]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkevents-x11.c
When actually returning expose events, make sure to set the count field
[~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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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-1999.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "gdk.h"
28 #include "gdkprivate-x11.h"
29 #include "gdkinternals.h"
30 #include "gdkx.h"
31
32 #include "gdkkeysyms.h"
33
34 #if HAVE_CONFIG_H
35 #  include <config.h>
36 #  if STDC_HEADERS
37 #    include <string.h>
38 #  endif
39 #endif
40
41 #include "gdkinputprivate.h"
42
43 typedef struct _GdkIOClosure GdkIOClosure;
44 typedef struct _GdkEventPrivate GdkEventPrivate;
45
46 #define DOUBLE_CLICK_TIME      250
47 #define TRIPLE_CLICK_TIME      500
48 #define DOUBLE_CLICK_DIST      5
49 #define TRIPLE_CLICK_DIST      5
50
51 typedef enum
52 {
53   /* Following flag is set for events on the event queue during
54    * translation and cleared afterwards.
55    */
56   GDK_EVENT_PENDING = 1 << 0
57 } GdkEventFlags;
58
59 struct _GdkIOClosure
60 {
61   GdkInputFunction function;
62   GdkInputCondition condition;
63   GdkDestroyNotify notify;
64   gpointer data;
65 };
66
67 struct _GdkEventPrivate
68 {
69   GdkEvent event;
70   guint    flags;
71 };
72
73 /* 
74  * Private function declarations
75  */
76
77 static gint      gdk_event_apply_filters (XEvent   *xevent,
78                                           GdkEvent *event,
79                                           GList    *filters);
80 static gint      gdk_event_translate     (GdkEvent *event, 
81                                           XEvent   *xevent,
82                                           gboolean  return_exposes);
83 #if 0
84 static Bool      gdk_event_get_type     (Display   *display, 
85                                          XEvent    *xevent, 
86                                          XPointer   arg);
87 #endif
88
89 static gboolean  gdk_event_prepare      (gpointer   source_data, 
90                                          GTimeVal  *current_time,
91                                          gint      *timeout,
92                                          gpointer   user_data);
93 static gboolean  gdk_event_check        (gpointer   source_data,
94                                          GTimeVal  *current_time,
95                                          gpointer   user_data);
96 static gboolean  gdk_event_dispatch     (gpointer   source_data,
97                                          GTimeVal  *current_time,
98                                          gpointer   user_data);
99
100 GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
101                                          GdkEvent  *event,
102                                          gpointer   data);
103
104 /* Private variable declarations
105  */
106
107 static int connection_number = 0;           /* The file descriptor number of our
108                                              *  connection to the X server. This
109                                              *  is used so that we may determine
110                                              *  when events are pending by using
111                                              *  the "select" system call.
112                                              */
113 static GList *client_filters;               /* Filters for client messages */
114
115 static GSourceFuncs event_funcs = {
116   gdk_event_prepare,
117   gdk_event_check,
118   gdk_event_dispatch,
119   (GDestroyNotify)g_free
120 };
121
122 GPollFD event_poll_fd;
123
124 /*********************************************
125  * Functions for maintaining the event queue *
126  *********************************************/
127
128 void 
129 gdk_events_init (void)
130 {
131   connection_number = ConnectionNumber (gdk_display);
132   GDK_NOTE (MISC,
133             g_message ("connection number: %d", connection_number));
134
135   g_source_add (GDK_PRIORITY_EVENTS, TRUE, &event_funcs, NULL, NULL, NULL);
136
137   event_poll_fd.fd = connection_number;
138   event_poll_fd.events = G_IO_IN;
139   
140   g_main_add_poll (&event_poll_fd, GDK_PRIORITY_EVENTS);
141
142   gdk_add_client_message_filter (gdk_wm_protocols, 
143                                  gdk_wm_protocols_filter, NULL);
144 }
145
146 /*
147  *--------------------------------------------------------------
148  * gdk_events_pending
149  *
150  *   Returns if events are pending on the queue.
151  *
152  * Arguments:
153  *
154  * Results:
155  *   Returns TRUE if events are pending
156  *
157  * Side effects:
158  *
159  *--------------------------------------------------------------
160  */
161
162 gboolean
163 gdk_events_pending (void)
164 {
165   return (gdk_event_queue_find_first() || XPending (gdk_display));
166 }
167
168 /*
169  *--------------------------------------------------------------
170  * gdk_event_get_graphics_expose
171  *
172  *   Waits for a GraphicsExpose or NoExpose event
173  *
174  * Arguments:
175  *
176  * Results: 
177  *   For GraphicsExpose events, returns a pointer to the event
178  *   converted into a GdkEvent Otherwise, returns NULL.
179  *
180  * Side effects:
181  *
182  *-------------------------------------------------------------- */
183
184 static Bool
185 graphics_expose_predicate (Display  *display,
186                            XEvent   *xevent,
187                            XPointer  arg)
188 {
189   if (xevent->xany.window == GDK_DRAWABLE_XID (arg) &&
190       (xevent->xany.type == GraphicsExpose ||
191        xevent->xany.type == NoExpose))
192     return True;
193   else
194     return False;
195 }
196
197 GdkEvent*
198 gdk_event_get_graphics_expose (GdkWindow *window)
199 {
200   XEvent xevent;
201   GdkEvent *event;
202   
203   g_return_val_if_fail (window != NULL, NULL);
204   
205   XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer) window);
206   
207   if (xevent.xany.type == GraphicsExpose)
208     {
209       event = gdk_event_new ();
210       
211       if (gdk_event_translate (event, &xevent, TRUE))
212         return event;
213       else
214         gdk_event_free (event);
215     }
216   
217   return NULL;  
218 }
219
220 static gint
221 gdk_event_apply_filters (XEvent *xevent,
222                          GdkEvent *event,
223                          GList *filters)
224 {
225   GList *tmp_list;
226   GdkFilterReturn result;
227   
228   tmp_list = filters;
229   
230   while (tmp_list)
231     {
232       GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
233       
234       tmp_list = tmp_list->next;
235       result = filter->function (xevent, event, filter->data);
236       if (result !=  GDK_FILTER_CONTINUE)
237         return result;
238     }
239   
240   return GDK_FILTER_CONTINUE;
241 }
242
243 void 
244 gdk_add_client_message_filter (GdkAtom       message_type,
245                                GdkFilterFunc func,
246                                gpointer      data)
247 {
248   GdkClientFilter *filter = g_new (GdkClientFilter, 1);
249
250   filter->type = message_type;
251   filter->function = func;
252   filter->data = data;
253   
254   client_filters = g_list_prepend (client_filters, filter);
255 }
256
257 static gint
258 gdk_event_translate (GdkEvent *event,
259                      XEvent   *xevent,
260                      gboolean  return_exposes)
261 {
262   
263   GdkWindow *window;
264   GdkWindowObject *window_private;
265   static XComposeStatus compose;
266   KeySym keysym;
267   int charcount;
268 #ifdef USE_XIM
269   static gchar* buf = NULL;
270   static gint buf_len= 0;
271 #else
272   char buf[16];
273 #endif
274   gint return_val;
275   gint xoffset, yoffset;
276   
277   return_val = FALSE;
278   
279   /* Find the GdkWindow that this event occurred in.
280    * 
281    * We handle events with window=None
282    *  specially - they are generated by XFree86's XInput under
283    *  some circumstances.
284    */
285   
286   if ((xevent->xany.window == None) &&
287       gdk_input_vtable.window_none_event)
288     {
289       return_val = gdk_input_vtable.window_none_event (event,xevent);
290       
291       if (return_val >= 0)      /* was handled */
292         return return_val;
293       else
294         return_val = FALSE;
295     }
296   
297   window = gdk_window_lookup (xevent->xany.window);
298   /* FIXME: window might be a GdkPixmap!!! */
299   
300   window_private = (GdkWindowObject *) window;
301   
302   if (window != NULL)
303     gdk_window_ref (window);
304   
305   event->any.window = window;
306   event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
307   
308   if (window_private && GDK_WINDOW_DESTROYED (window))
309     {
310       if (xevent->type != DestroyNotify)
311         return FALSE;
312     }
313   else
314     {
315       /* Check for filters for this window
316        */
317       GdkFilterReturn result;
318       result = gdk_event_apply_filters (xevent, event,
319                                         window_private
320                                         ?window_private->filters
321                                         :gdk_default_filters);
322       
323       if (result != GDK_FILTER_CONTINUE)
324         {
325           return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
326           goto done;
327         }
328     }
329
330 #ifdef USE_XIM
331   if (window == NULL && gdk_xim_window && xevent->type == KeyPress &&
332       !GDK_WINDOW_DESTROYED (gdk_xim_window))
333     {
334       /*
335        * If user presses a key in Preedit or Status window, keypress event
336        * is sometimes sent to these windows. These windows are not managed
337        * by GDK, so we redirect KeyPress event to xim_window.
338        *
339        * If someone want to use the window whitch is not managed by GDK
340        * and want to get KeyPress event, he/she must register the filter
341        * function to gdk_default_filters to intercept the event.
342        */
343
344       GdkFilterReturn result;
345
346       window = gdk_xim_window;
347       window_private = (GdkWindowObject *) window;
348       gdk_window_ref (window);
349       event->any.window = window;
350
351       GDK_NOTE (XIM,
352         g_message ("KeyPress event is redirected to xim_window: %#lx",
353                    xevent->xany.window));
354
355       result = gdk_event_apply_filters (xevent, event,
356                                         window_private->filters);
357       if (result != GDK_FILTER_CONTINUE)
358         {
359           return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
360           goto done;
361         }
362     }
363 #endif
364
365   /* We do a "manual" conversion of the XEvent to a
366    *  GdkEvent. The structures are mostly the same so
367    *  the conversion is fairly straightforward. We also
368    *  optionally print debugging info regarding events
369    *  received.
370    */
371
372   return_val = TRUE;
373
374   if (window)
375     {
376       _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
377     }
378   else
379     {
380       xoffset = 0;
381       yoffset = 0;
382     }
383
384   switch (xevent->type)
385     {
386     case KeyPress:
387       /* Lookup the string corresponding to the given keysym.
388        */
389       
390 #ifdef USE_XIM
391       if (buf_len == 0) 
392         {
393           buf_len = 128;
394           buf = g_new (gchar, buf_len);
395         }
396       keysym = GDK_VoidSymbol;
397       
398       if (gdk_xim_ic && gdk_xim_ic->xic)
399         {
400           Status status;
401           
402           /* Clear keyval. Depending on status, may not be set */
403           charcount = XmbLookupString(gdk_xim_ic->xic,
404                                       &xevent->xkey, buf, buf_len-1,
405                                       &keysym, &status);
406           if (status == XBufferOverflow)
407             {                     /* retry */
408               /* alloc adequate size of buffer */
409               GDK_NOTE (XIM,
410                         g_message("XIM: overflow (required %i)", charcount));
411               
412               while (buf_len <= charcount)
413                 buf_len *= 2;
414               buf = (gchar *) g_realloc (buf, buf_len);
415               
416               charcount = XmbLookupString (gdk_xim_ic->xic,
417                                            &xevent->xkey, buf, buf_len-1,
418                                            &keysym, &status);
419             }
420           if (status == XLookupNone)
421             {
422               return_val = FALSE;
423               break;
424             }
425         }
426       else
427         charcount = XLookupString (&xevent->xkey, buf, buf_len,
428                                    &keysym, &compose);
429 #else
430       charcount = XLookupString (&xevent->xkey, buf, 16,
431                                  &keysym, &compose);
432 #endif
433       event->key.keyval = keysym;
434       
435       if (charcount > 0 && buf[charcount-1] == '\0')
436         charcount --;
437       else
438         buf[charcount] = '\0';
439       
440 #ifdef G_ENABLE_DEBUG
441       if (gdk_debug_flags & GDK_DEBUG_EVENTS)
442         {
443           g_message ("key press:\twindow: %ld  key: %12s  %d",
444                      xevent->xkey.window,
445                      event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
446                      event->key.keyval);
447           if (charcount > 0)
448             g_message ("\t\tlength: %4d string: \"%s\"",
449                        charcount, buf);
450         }
451 #endif /* G_ENABLE_DEBUG */
452       
453       event->key.type = GDK_KEY_PRESS;
454       event->key.window = window;
455       event->key.time = xevent->xkey.time;
456       event->key.state = (GdkModifierType) xevent->xkey.state;
457       event->key.string = g_strdup (buf);
458       event->key.length = charcount;
459       
460       break;
461       
462     case KeyRelease:
463       /* Lookup the string corresponding to the given keysym.
464        */
465 #ifdef USE_XIM
466       if (buf_len == 0) 
467         {
468           buf_len = 128;
469           buf = g_new (gchar, buf_len);
470         }
471 #endif
472       keysym = GDK_VoidSymbol;
473       charcount = XLookupString (&xevent->xkey, buf, 16,
474                                  &keysym, &compose);
475       event->key.keyval = keysym;      
476       
477       GDK_NOTE (EVENTS, 
478                 g_message ("key release:\t\twindow: %ld  key: %12s  %d",
479                            xevent->xkey.window,
480                            XKeysymToString (event->key.keyval),
481                            event->key.keyval));
482       
483       event->key.type = GDK_KEY_RELEASE;
484       event->key.window = window;
485       event->key.time = xevent->xkey.time;
486       event->key.state = (GdkModifierType) xevent->xkey.state;
487       event->key.length = 0;
488       event->key.string = NULL;
489       
490       break;
491       
492     case ButtonPress:
493       GDK_NOTE (EVENTS, 
494                 g_message ("button press:\t\twindow: %ld  x,y: %d %d  button: %d",
495                            xevent->xbutton.window,
496                            xevent->xbutton.x, xevent->xbutton.y,
497                            xevent->xbutton.button));
498       
499       if (window_private &&
500           (window_private->extension_events != 0) &&
501           gdk_input_ignore_core)
502         {
503           return_val = FALSE;
504           break;
505         }
506       
507       /* If we get a ButtonPress event where the button is 4 or 5,
508          it's a Scroll event */
509       if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5)
510         {
511           event->scroll.type = GDK_SCROLL;
512           event->scroll.direction = (xevent->xbutton.button == 4) ? 
513             GDK_SCROLL_UP : GDK_SCROLL_DOWN;
514           event->scroll.window = window;
515           event->scroll.time = xevent->xbutton.x;
516           event->scroll.x = xevent->xbutton.x + xoffset;
517           event->scroll.y = xevent->xbutton.y + yoffset;
518           event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
519           event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
520           event->scroll.pressure = 0.5;
521           event->scroll.xtilt = 0;
522           event->scroll.ytilt = 0;
523           event->scroll.state = (GdkModifierType) xevent->xbutton.state;
524           event->scroll.source = GDK_SOURCE_MOUSE;
525           event->scroll.deviceid = GDK_CORE_POINTER;
526         }
527       else
528         {
529           event->button.type = GDK_BUTTON_PRESS;
530           event->button.window = window;
531           event->button.time = xevent->xbutton.time;
532           event->button.x = xevent->xbutton.x + xoffset;
533           event->button.y = xevent->xbutton.y + yoffset;
534           event->button.x_root = (gfloat)xevent->xbutton.x_root;
535           event->button.y_root = (gfloat)xevent->xbutton.y_root;
536           event->button.pressure = 0.5;
537           event->button.xtilt = 0;
538           event->button.ytilt = 0;
539           event->button.state = (GdkModifierType) xevent->xbutton.state;
540           event->button.button = xevent->xbutton.button;
541           event->button.source = GDK_SOURCE_MOUSE;
542           event->button.deviceid = GDK_CORE_POINTER;
543           
544           gdk_event_button_generate (event);
545         }
546
547       break;
548       
549     case ButtonRelease:
550       GDK_NOTE (EVENTS, 
551                 g_message ("button release:\twindow: %ld  x,y: %d %d  button: %d",
552                            xevent->xbutton.window,
553                            xevent->xbutton.x, xevent->xbutton.y,
554                            xevent->xbutton.button));
555       
556       if (window_private &&
557           (window_private->extension_events != 0) &&
558           gdk_input_ignore_core)
559         {
560           return_val = FALSE;
561           break;
562         }
563       
564       /* We treat button presses as scroll wheel events, so ignore the release */
565       if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5)
566         {
567           return_val = FALSE;
568           break;
569         }
570
571       event->button.type = GDK_BUTTON_RELEASE;
572       event->button.window = window;
573       event->button.time = xevent->xbutton.time;
574       event->button.x = xevent->xbutton.x + xoffset;
575       event->button.y = xevent->xbutton.y + yoffset;
576       event->button.x_root = (gfloat)xevent->xbutton.x_root;
577       event->button.y_root = (gfloat)xevent->xbutton.y_root;
578       event->button.pressure = 0.5;
579       event->button.xtilt = 0;
580       event->button.ytilt = 0;
581       event->button.state = (GdkModifierType) xevent->xbutton.state;
582       event->button.button = xevent->xbutton.button;
583       event->button.source = GDK_SOURCE_MOUSE;
584       event->button.deviceid = GDK_CORE_POINTER;
585       
586       break;
587       
588     case MotionNotify:
589       GDK_NOTE (EVENTS,
590                 g_message ("motion notify:\t\twindow: %ld  x,y: %d %d  hint: %s", 
591                            xevent->xmotion.window,
592                            xevent->xmotion.x, xevent->xmotion.y,
593                            (xevent->xmotion.is_hint) ? "true" : "false"));
594       
595       if (window_private &&
596           (window_private->extension_events != 0) &&
597           gdk_input_ignore_core)
598         {
599           return_val = FALSE;
600           break;
601         }
602       
603       event->motion.type = GDK_MOTION_NOTIFY;
604       event->motion.window = window;
605       event->motion.time = xevent->xmotion.time;
606       event->motion.x = xevent->xmotion.x + xoffset;
607       event->motion.y = xevent->xmotion.y + yoffset;
608       event->motion.x_root = (gfloat)xevent->xmotion.x_root;
609       event->motion.y_root = (gfloat)xevent->xmotion.y_root;
610       event->motion.pressure = 0.5;
611       event->motion.xtilt = 0;
612       event->motion.ytilt = 0;
613       event->motion.state = (GdkModifierType) xevent->xmotion.state;
614       event->motion.is_hint = xevent->xmotion.is_hint;
615       event->motion.source = GDK_SOURCE_MOUSE;
616       event->motion.deviceid = GDK_CORE_POINTER;
617       
618       break;
619       
620     case EnterNotify:
621       GDK_NOTE (EVENTS,
622                 g_message ("enter notify:\t\twindow: %ld  detail: %d subwin: %ld",
623                            xevent->xcrossing.window,
624                            xevent->xcrossing.detail,
625                            xevent->xcrossing.subwindow));
626       
627       /* Tell XInput stuff about it if appropriate */
628       if (window_private &&
629           !GDK_WINDOW_DESTROYED (window) &&
630           (window_private->extension_events != 0) &&
631           gdk_input_vtable.enter_event)
632         gdk_input_vtable.enter_event (&xevent->xcrossing, window);
633       
634       event->crossing.type = GDK_ENTER_NOTIFY;
635       event->crossing.window = window;
636       
637       /* If the subwindow field of the XEvent is non-NULL, then
638        *  lookup the corresponding GdkWindow.
639        */
640       if (xevent->xcrossing.subwindow != None)
641         event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
642       else
643         event->crossing.subwindow = NULL;
644       
645       event->crossing.time = xevent->xcrossing.time;
646       event->crossing.x = xevent->xcrossing.x + xoffset;
647       event->crossing.y = xevent->xcrossing.y + yoffset;
648       event->crossing.x_root = xevent->xcrossing.x_root;
649       event->crossing.y_root = xevent->xcrossing.y_root;
650       
651       /* Translate the crossing mode into Gdk terms.
652        */
653       switch (xevent->xcrossing.mode)
654         {
655         case NotifyNormal:
656           event->crossing.mode = GDK_CROSSING_NORMAL;
657           break;
658         case NotifyGrab:
659           event->crossing.mode = GDK_CROSSING_GRAB;
660           break;
661         case NotifyUngrab:
662           event->crossing.mode = GDK_CROSSING_UNGRAB;
663           break;
664         };
665       
666       /* Translate the crossing detail into Gdk terms.
667        */
668       switch (xevent->xcrossing.detail)
669         {
670         case NotifyInferior:
671           event->crossing.detail = GDK_NOTIFY_INFERIOR;
672           break;
673         case NotifyAncestor:
674           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
675           break;
676         case NotifyVirtual:
677           event->crossing.detail = GDK_NOTIFY_VIRTUAL;
678           break;
679         case NotifyNonlinear:
680           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
681           break;
682         case NotifyNonlinearVirtual:
683           event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
684           break;
685         default:
686           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
687           break;
688         }
689       
690       event->crossing.focus = xevent->xcrossing.focus;
691       event->crossing.state = xevent->xcrossing.state;
692   
693       break;
694       
695     case LeaveNotify:
696       GDK_NOTE (EVENTS, 
697                 g_message ("leave notify:\t\twindow: %ld  detail: %d subwin: %ld",
698                            xevent->xcrossing.window,
699                            xevent->xcrossing.detail, xevent->xcrossing.subwindow));
700       
701       event->crossing.type = GDK_LEAVE_NOTIFY;
702       event->crossing.window = window;
703       
704       /* If the subwindow field of the XEvent is non-NULL, then
705        *  lookup the corresponding GdkWindow.
706        */
707       if (xevent->xcrossing.subwindow != None)
708         event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
709       else
710         event->crossing.subwindow = NULL;
711       
712       event->crossing.time = xevent->xcrossing.time;
713       event->crossing.x = xevent->xcrossing.x + xoffset;
714       event->crossing.y = xevent->xcrossing.y + yoffset;
715       event->crossing.x_root = xevent->xcrossing.x_root;
716       event->crossing.y_root = xevent->xcrossing.y_root;
717       
718       /* Translate the crossing mode into Gdk terms.
719        */
720       switch (xevent->xcrossing.mode)
721         {
722         case NotifyNormal:
723           event->crossing.mode = GDK_CROSSING_NORMAL;
724           break;
725         case NotifyGrab:
726           event->crossing.mode = GDK_CROSSING_GRAB;
727           break;
728         case NotifyUngrab:
729           event->crossing.mode = GDK_CROSSING_UNGRAB;
730           break;
731         };
732       
733       /* Translate the crossing detail into Gdk terms.
734        */
735       switch (xevent->xcrossing.detail)
736         {
737         case NotifyInferior:
738           event->crossing.detail = GDK_NOTIFY_INFERIOR;
739           break;
740         case NotifyAncestor:
741           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
742           break;
743         case NotifyVirtual:
744           event->crossing.detail = GDK_NOTIFY_VIRTUAL;
745           break;
746         case NotifyNonlinear:
747           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
748           break;
749         case NotifyNonlinearVirtual:
750           event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
751           break;
752         default:
753           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
754           break;
755         }
756       
757       event->crossing.focus = xevent->xcrossing.focus;
758       event->crossing.state = xevent->xcrossing.state;
759       
760       break;
761       
762     case FocusIn:
763     case FocusOut:
764       /* We only care about focus events that indicate that _this_
765        * window (not a ancestor or child) got or lost the focus
766        */
767       switch (xevent->xfocus.detail)
768         {
769         case NotifyAncestor:
770         case NotifyInferior:
771         case NotifyNonlinear:
772           GDK_NOTE (EVENTS,
773                     g_message ("focus %s:\t\twindow: %ld",
774                                (xevent->xany.type == FocusIn) ? "in" : "out",
775                                xevent->xfocus.window));
776           
777           /* gdk_keyboard_grab() causes following events. These events confuse
778            * the XIM focus, so ignore them.
779            */
780           if (xevent->xfocus.mode == NotifyGrab ||
781               xevent->xfocus.mode == NotifyUngrab)
782             break;
783           
784           event->focus_change.type = GDK_FOCUS_CHANGE;
785           event->focus_change.window = window;
786           event->focus_change.in = (xevent->xany.type == FocusIn);
787
788           break;
789         default:
790           return_val = FALSE;
791         }
792       break;
793       
794     case KeymapNotify:
795       GDK_NOTE (EVENTS,
796                 g_message ("keymap notify"));
797
798       /* Not currently handled */
799       return_val = FALSE;
800       break;
801       
802     case Expose:
803       GDK_NOTE (EVENTS,
804                 g_message ("expose:\t\twindow: %ld  %d  x,y: %d %d  w,h: %d %d%s",
805                            xevent->xexpose.window, xevent->xexpose.count,
806                            xevent->xexpose.x, xevent->xexpose.y,
807                            xevent->xexpose.width, xevent->xexpose.height,
808                            event->any.send_event ? " (send)" : ""));
809       {
810         GdkRectangle expose_rect;
811
812         expose_rect.x = xevent->xexpose.x + xoffset;
813         expose_rect.y = xevent->xexpose.y + yoffset;
814         expose_rect.width = xevent->xexpose.width;
815         expose_rect.height = xevent->xexpose.height;
816
817         if (return_exposes)
818           {
819             event->expose.type = GDK_EXPOSE;
820             event->expose.area = expose_rect;
821             event->expose.window = window;
822             event->expose.count = xevent->xexpose.count;
823
824             return_val = TRUE;
825           }
826         else
827           {
828             _gdk_window_process_expose (window, xevent->xexpose.serial, &expose_rect);
829
830             return_val = FALSE;
831           }
832         
833         return_val = FALSE;
834       }
835         
836       break;
837       
838     case GraphicsExpose:
839       {
840         GdkRectangle expose_rect;
841
842         GDK_NOTE (EVENTS,
843                   g_message ("graphics expose:\tdrawable: %ld",
844                              xevent->xgraphicsexpose.drawable));
845
846         expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
847         expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
848         expose_rect.width = xevent->xgraphicsexpose.width;
849         expose_rect.height = xevent->xgraphicsexpose.height;
850             
851         if (return_exposes)
852           {
853             event->expose.type = GDK_EXPOSE;
854             event->expose.area = expose_rect;
855             event->expose.window = window;
856             event->expose.count = xevent->xgraphicsexpose.count;
857
858             return_val = TRUE;
859           }
860         else
861           {
862             _gdk_window_process_expose (window, xevent->xgraphicsexpose.serial, &expose_rect);
863             
864             return_val = FALSE;
865           }
866         
867       }
868       break;
869       
870     case NoExpose:
871       GDK_NOTE (EVENTS,
872                 g_message ("no expose:\t\tdrawable: %ld",
873                            xevent->xnoexpose.drawable));
874       
875       event->no_expose.type = GDK_NO_EXPOSE;
876       event->no_expose.window = window;
877       
878       break;
879       
880     case VisibilityNotify:
881 #ifdef G_ENABLE_DEBUG
882       if (gdk_debug_flags & GDK_DEBUG_EVENTS)
883         switch (xevent->xvisibility.state)
884           {
885           case VisibilityFullyObscured:
886             g_message ("visibility notify:\twindow: %ld  none",
887                        xevent->xvisibility.window);
888             break;
889           case VisibilityPartiallyObscured:
890             g_message ("visibility notify:\twindow: %ld  partial",
891                        xevent->xvisibility.window);
892             break;
893           case VisibilityUnobscured:
894             g_message ("visibility notify:\twindow: %ld  full",
895                        xevent->xvisibility.window);
896             break;
897           }
898 #endif /* G_ENABLE_DEBUG */
899       
900       event->visibility.type = GDK_VISIBILITY_NOTIFY;
901       event->visibility.window = window;
902       
903       switch (xevent->xvisibility.state)
904         {
905         case VisibilityFullyObscured:
906           event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
907           break;
908           
909         case VisibilityPartiallyObscured:
910           event->visibility.state = GDK_VISIBILITY_PARTIAL;
911           break;
912           
913         case VisibilityUnobscured:
914           event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
915           break;
916         }
917       
918       break;
919       
920     case CreateNotify:
921       GDK_NOTE (EVENTS,
922                 g_message ("create notify:\twindow: %ld  x,y: %d %d     w,h: %d %d  b-w: %d  parent: %ld         ovr: %d",
923                            xevent->xcreatewindow.window,
924                            xevent->xcreatewindow.x,
925                            xevent->xcreatewindow.y,
926                            xevent->xcreatewindow.width,
927                            xevent->xcreatewindow.height,
928                            xevent->xcreatewindow.border_width,
929                            xevent->xcreatewindow.parent,
930                            xevent->xcreatewindow.override_redirect));
931       /* not really handled */
932       break;
933       
934     case DestroyNotify:
935       GDK_NOTE (EVENTS,
936                 g_message ("destroy notify:\twindow: %ld",
937                            xevent->xdestroywindow.window));
938       
939       event->any.type = GDK_DESTROY;
940       event->any.window = window;
941       
942       return_val = window_private && !GDK_WINDOW_DESTROYED (window);
943       
944       if (window && GDK_WINDOW_XID (window) != GDK_ROOT_WINDOW())
945         gdk_window_destroy_notify (window);
946       break;
947       
948     case UnmapNotify:
949       GDK_NOTE (EVENTS,
950                 g_message ("unmap notify:\t\twindow: %ld",
951                            xevent->xmap.window));
952       
953       event->any.type = GDK_UNMAP;
954       event->any.window = window;
955       
956       if (gdk_xgrab_window == window_private)
957         gdk_xgrab_window = NULL;
958       
959       break;
960       
961     case MapNotify:
962       GDK_NOTE (EVENTS,
963                 g_message ("map notify:\t\twindow: %ld",
964                            xevent->xmap.window));
965       
966       event->any.type = GDK_MAP;
967       event->any.window = window;
968       
969       break;
970       
971     case ReparentNotify:
972       GDK_NOTE (EVENTS,
973                 g_message ("reparent notify:\twindow: %ld  x,y: %d %d  parent: %ld      ovr: %d",
974                            xevent->xreparent.window,
975                            xevent->xreparent.x,
976                            xevent->xreparent.y,
977                            xevent->xreparent.parent,
978                            xevent->xreparent.override_redirect));
979
980       /* Not currently handled */
981       return_val = FALSE;
982       break;
983       
984     case ConfigureNotify:
985       GDK_NOTE (EVENTS,
986                 g_message ("configure notify:\twindow: %ld  x,y: %d %d  w,h: %d %d  b-w: %d  above: %ld  ovr: %d%s",
987                            xevent->xconfigure.window,
988                            xevent->xconfigure.x,
989                            xevent->xconfigure.y,
990                            xevent->xconfigure.width,
991                            xevent->xconfigure.height,
992                            xevent->xconfigure.border_width,
993                            xevent->xconfigure.above,
994                            xevent->xconfigure.override_redirect,
995                            !window
996                            ? " (discarding)"
997                            : GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD
998                            ? " (discarding child)"
999                            : ""));
1000       if (window &&
1001           !GDK_WINDOW_DESTROYED (window) &&
1002           (window_private->extension_events != 0) &&
1003           gdk_input_vtable.configure_event)
1004         gdk_input_vtable.configure_event (&xevent->xconfigure, window);
1005
1006       if (!window || GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1007         return_val = FALSE;
1008       else
1009         {
1010           event->configure.type = GDK_CONFIGURE;
1011           event->configure.window = window;
1012           event->configure.width = xevent->xconfigure.width;
1013           event->configure.height = xevent->xconfigure.height;
1014           
1015           if (!xevent->xconfigure.x &&
1016               !xevent->xconfigure.y &&
1017               !GDK_WINDOW_DESTROYED (window))
1018             {
1019               gint tx = 0;
1020               gint ty = 0;
1021               Window child_window = 0;
1022
1023               gdk_error_trap_push ();
1024               if (XTranslateCoordinates (GDK_DRAWABLE_XDISPLAY (window),
1025                                          GDK_DRAWABLE_XID (window),
1026                                          gdk_root_window,
1027                                          0, 0,
1028                                          &tx, &ty,
1029                                          &child_window))
1030                 {
1031                   if (!gdk_error_trap_pop ())
1032                     {
1033                       event->configure.x = tx;
1034                       event->configure.y = ty;
1035                     }
1036                 }
1037               else
1038                 gdk_error_trap_pop ();
1039             }
1040           else
1041             {
1042               event->configure.x = xevent->xconfigure.x;
1043               event->configure.y = xevent->xconfigure.y;
1044             }
1045           window_private->x = event->configure.x;
1046           window_private->y = event->configure.y;
1047           GDK_WINDOW_IMPL_X11 (window_private->impl)->width = xevent->xconfigure.width;
1048           GDK_WINDOW_IMPL_X11 (window_private->impl)->height = xevent->xconfigure.height;
1049           if (window_private->resize_count > 1)
1050             window_private->resize_count -= 1;
1051         }
1052       break;
1053       
1054     case PropertyNotify:
1055       GDK_NOTE (EVENTS,
1056                 gchar *atom = gdk_atom_name (xevent->xproperty.atom);
1057                 g_message ("property notify:\twindow: %ld, atom(%ld): %s%s%s",
1058                            xevent->xproperty.window,
1059                            xevent->xproperty.atom,
1060                            atom ? "\"" : "",
1061                            atom ? atom : "unknown",
1062                            atom ? "\"" : "");
1063                 g_free (atom);
1064                 );
1065       
1066       event->property.type = GDK_PROPERTY_NOTIFY;
1067       event->property.window = window;
1068       event->property.atom = xevent->xproperty.atom;
1069       event->property.time = xevent->xproperty.time;
1070       event->property.state = xevent->xproperty.state;
1071       
1072       break;
1073       
1074     case SelectionClear:
1075       GDK_NOTE (EVENTS,
1076                 g_message ("selection clear:\twindow: %ld",
1077                            xevent->xproperty.window));
1078       
1079       event->selection.type = GDK_SELECTION_CLEAR;
1080       event->selection.window = window;
1081       event->selection.selection = xevent->xselectionclear.selection;
1082       event->selection.time = xevent->xselectionclear.time;
1083       
1084       break;
1085       
1086     case SelectionRequest:
1087       GDK_NOTE (EVENTS,
1088                 g_message ("selection request:\twindow: %ld",
1089                            xevent->xproperty.window));
1090       
1091       event->selection.type = GDK_SELECTION_REQUEST;
1092       event->selection.window = window;
1093       event->selection.selection = xevent->xselectionrequest.selection;
1094       event->selection.target = xevent->xselectionrequest.target;
1095       event->selection.property = xevent->xselectionrequest.property;
1096       event->selection.requestor = xevent->xselectionrequest.requestor;
1097       event->selection.time = xevent->xselectionrequest.time;
1098       
1099       break;
1100       
1101     case SelectionNotify:
1102       GDK_NOTE (EVENTS,
1103                 g_message ("selection notify:\twindow: %ld",
1104                            xevent->xproperty.window));
1105       
1106       
1107       event->selection.type = GDK_SELECTION_NOTIFY;
1108       event->selection.window = window;
1109       event->selection.selection = xevent->xselection.selection;
1110       event->selection.target = xevent->xselection.target;
1111       event->selection.property = xevent->xselection.property;
1112       event->selection.time = xevent->xselection.time;
1113       
1114       break;
1115       
1116     case ColormapNotify:
1117       GDK_NOTE (EVENTS,
1118                 g_message ("colormap notify:\twindow: %ld",
1119                            xevent->xcolormap.window));
1120       
1121       /* Not currently handled */
1122       return_val = FALSE;
1123       break;
1124       
1125     case ClientMessage:
1126       {
1127         GList *tmp_list;
1128         GdkFilterReturn result = GDK_FILTER_CONTINUE;
1129
1130         GDK_NOTE (EVENTS,
1131                   g_message ("client message:\twindow: %ld",
1132                              xevent->xclient.window));
1133         
1134         tmp_list = client_filters;
1135         while (tmp_list)
1136           {
1137             GdkClientFilter *filter = tmp_list->data;
1138             if (filter->type == xevent->xclient.message_type)
1139               {
1140                 result = (*filter->function) (xevent, event, filter->data);
1141                 break;
1142               }
1143             
1144             tmp_list = tmp_list->next;
1145           }
1146
1147         switch (result)
1148           {
1149           case GDK_FILTER_REMOVE:
1150             return_val = FALSE;
1151             break;
1152           case GDK_FILTER_TRANSLATE:
1153             return_val = TRUE;
1154             break;
1155           case GDK_FILTER_CONTINUE:
1156             /* Send unknown ClientMessage's on to Gtk for it to use */
1157             event->client.type = GDK_CLIENT_EVENT;
1158             event->client.window = window;
1159             event->client.message_type = xevent->xclient.message_type;
1160             event->client.data_format = xevent->xclient.format;
1161             memcpy(&event->client.data, &xevent->xclient.data,
1162                    sizeof(event->client.data));
1163           }
1164       }
1165       
1166       break;
1167       
1168     case MappingNotify:
1169       GDK_NOTE (EVENTS,
1170                 g_message ("mapping notify"));
1171       
1172       /* Let XLib know that there is a new keyboard mapping.
1173        */
1174       XRefreshKeyboardMapping (&xevent->xmapping);
1175       return_val = FALSE;
1176       break;
1177       
1178     default:
1179       /* something else - (e.g., a Xinput event) */
1180       
1181       if (window_private &&
1182           !GDK_WINDOW_DESTROYED (window_private) &&
1183           (window_private->extension_events != 0) &&
1184           gdk_input_vtable.other_event)
1185         return_val = gdk_input_vtable.other_event(event, xevent, window);
1186       else
1187         return_val = FALSE;
1188       
1189       break;
1190     }
1191
1192  done:
1193   if (return_val)
1194     {
1195       if (event->any.window)
1196         gdk_window_ref (event->any.window);
1197       if (((event->any.type == GDK_ENTER_NOTIFY) ||
1198            (event->any.type == GDK_LEAVE_NOTIFY)) &&
1199           (event->crossing.subwindow != NULL))
1200         gdk_window_ref (event->crossing.subwindow);
1201     }
1202   else
1203     {
1204       /* Mark this event as having no resources to be freed */
1205       event->any.window = NULL;
1206       event->any.type = GDK_NOTHING;
1207     }
1208   
1209   if (window)
1210     gdk_window_unref (window);
1211   
1212   return return_val;
1213 }
1214
1215 GdkFilterReturn
1216 gdk_wm_protocols_filter (GdkXEvent *xev,
1217                          GdkEvent  *event,
1218                          gpointer data)
1219 {
1220   XEvent *xevent = (XEvent *)xev;
1221
1222   if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
1223     {
1224   /* The delete window request specifies a window
1225    *  to delete. We don't actually destroy the
1226    *  window because "it is only a request". (The
1227    *  window might contain vital data that the
1228    *  program does not want destroyed). Instead
1229    *  the event is passed along to the program,
1230    *  which should then destroy the window.
1231    */
1232       GDK_NOTE (EVENTS,
1233                 g_message ("delete window:\t\twindow: %ld",
1234                            xevent->xclient.window));
1235       
1236       event->any.type = GDK_DELETE;
1237
1238       return GDK_FILTER_TRANSLATE;
1239     }
1240   else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
1241     {
1242     }
1243
1244   return GDK_FILTER_REMOVE;
1245 }
1246
1247 #if 0
1248 static Bool
1249 gdk_event_get_type (Display  *display,
1250                     XEvent   *xevent,
1251                     XPointer  arg)
1252 {
1253   GdkEvent event;
1254   GdkPredicate *pred;
1255   
1256   if (gdk_event_translate (&event, xevent, FALSE))
1257     {
1258       pred = (GdkPredicate*) arg;
1259       return (* pred->func) (&event, pred->data);
1260     }
1261   
1262   return FALSE;
1263 }
1264 #endif
1265
1266 void
1267 gdk_events_queue (void)
1268 {
1269   GList *node;
1270   GdkEvent *event;
1271   XEvent xevent;
1272
1273   while (!gdk_event_queue_find_first() && XPending (gdk_display))
1274     {
1275 #ifdef USE_XIM
1276       Window w = None;
1277       
1278       XNextEvent (gdk_display, &xevent);
1279       if (gdk_xim_window)
1280         switch (xevent.type)
1281           {
1282           case KeyPress:
1283           case KeyRelease:
1284           case ButtonPress:
1285           case ButtonRelease:
1286             w = GDK_WINDOW_XWINDOW (gdk_xim_window);
1287             break;
1288           }
1289       
1290       if (XFilterEvent (&xevent, w))
1291         continue;
1292 #else
1293       XNextEvent (gdk_display, &xevent);
1294 #endif
1295       
1296       event = gdk_event_new ();
1297       
1298       event->any.type = GDK_NOTHING;
1299       event->any.window = NULL;
1300       event->any.send_event = xevent.xany.send_event ? TRUE : FALSE;
1301
1302       ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
1303
1304       gdk_event_queue_append (event);
1305       node = gdk_queued_tail;
1306
1307       if (gdk_event_translate (event, &xevent, FALSE))
1308         {
1309           ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
1310         }
1311       else
1312         {
1313           gdk_event_queue_remove_link (node);
1314           g_list_free_1 (node);
1315           gdk_event_free (event);
1316         }
1317     }
1318 }
1319
1320 static gboolean  
1321 gdk_event_prepare (gpointer  source_data, 
1322                    GTimeVal *current_time,
1323                    gint     *timeout,
1324                    gpointer  user_data)
1325 {
1326   gboolean retval;
1327   
1328   GDK_THREADS_ENTER ();
1329
1330   *timeout = -1;
1331
1332   retval = (gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
1333
1334   GDK_THREADS_LEAVE ();
1335
1336   return retval;
1337 }
1338
1339 static gboolean  
1340 gdk_event_check (gpointer  source_data,
1341                  GTimeVal *current_time,
1342                  gpointer  user_data)
1343 {
1344   gboolean retval;
1345   
1346   GDK_THREADS_ENTER ();
1347
1348   if (event_poll_fd.revents & G_IO_IN)
1349     retval = (gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
1350   else
1351     retval = FALSE;
1352
1353   GDK_THREADS_LEAVE ();
1354
1355   return retval;
1356 }
1357
1358 static gboolean  
1359 gdk_event_dispatch (gpointer  source_data,
1360                     GTimeVal *current_time,
1361                     gpointer  user_data)
1362 {
1363   GdkEvent *event;
1364  
1365   GDK_THREADS_ENTER ();
1366
1367   gdk_events_queue();
1368   event = gdk_event_unqueue();
1369
1370   if (event)
1371     {
1372       if (gdk_event_func)
1373         (*gdk_event_func) (event, gdk_event_data);
1374       
1375       gdk_event_free (event);
1376     }
1377   
1378   GDK_THREADS_LEAVE ();
1379
1380   return TRUE;
1381 }
1382
1383 /* Sends a ClientMessage to all toplevel client windows */
1384 gboolean
1385 gdk_event_send_client_message (GdkEvent *event, guint32 xid)
1386 {
1387   XEvent sev;
1388   
1389   g_return_val_if_fail(event != NULL, FALSE);
1390   
1391   /* Set up our event to send, with the exception of its target window */
1392   sev.xclient.type = ClientMessage;
1393   sev.xclient.display = gdk_display;
1394   sev.xclient.format = event->client.data_format;
1395   sev.xclient.window = xid;
1396   memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
1397   sev.xclient.message_type = event->client.message_type;
1398   
1399   return gdk_send_xevent (xid, False, NoEventMask, &sev);
1400 }
1401
1402 /* Sends a ClientMessage to all toplevel client windows */
1403 gboolean
1404 gdk_event_send_client_message_to_all_recurse (XEvent  *xev, 
1405                                               guint32  xid,
1406                                               guint    level)
1407 {
1408   static GdkAtom wm_state_atom = GDK_NONE;
1409   Atom type = None;
1410   int format;
1411   unsigned long nitems, after;
1412   unsigned char *data;
1413   Window *ret_children, ret_root, ret_parent;
1414   unsigned int ret_nchildren;
1415   gint old_warnings = gdk_error_warnings;
1416   gboolean send = FALSE;
1417   gboolean found = FALSE;
1418   int i;
1419
1420   if (!wm_state_atom)
1421     wm_state_atom = gdk_atom_intern ("WM_STATE", FALSE);
1422
1423   gdk_error_warnings = FALSE;
1424   gdk_error_code = 0;
1425   XGetWindowProperty (gdk_display, xid, wm_state_atom, 0, 0, False, AnyPropertyType,
1426                       &type, &format, &nitems, &after, &data);
1427
1428   if (gdk_error_code)
1429     {
1430       gdk_error_warnings = old_warnings;
1431
1432       return FALSE;
1433     }
1434
1435   if (type)
1436     {
1437       send = TRUE;
1438       XFree (data);
1439     }
1440   else
1441     {
1442       /* OK, we're all set, now let's find some windows to send this to */
1443       if (XQueryTree (gdk_display, xid, &ret_root, &ret_parent,
1444                       &ret_children, &ret_nchildren) != True ||
1445           gdk_error_code)
1446         {
1447           gdk_error_warnings = old_warnings;
1448
1449           return FALSE;
1450         }
1451
1452       for(i = 0; i < ret_nchildren; i++)
1453         if (gdk_event_send_client_message_to_all_recurse (xev, ret_children[i], level + 1))
1454           found = TRUE;
1455
1456       XFree (ret_children);
1457     }
1458
1459   if (send || (!found && (level == 1)))
1460     {
1461       xev->xclient.window = xid;
1462       gdk_send_xevent (xid, False, NoEventMask, xev);
1463     }
1464
1465   gdk_error_warnings = old_warnings;
1466
1467   return (send || found);
1468 }
1469
1470 void
1471 gdk_event_send_clientmessage_toall (GdkEvent *event)
1472 {
1473   XEvent sev;
1474   gint old_warnings = gdk_error_warnings;
1475
1476   g_return_if_fail(event != NULL);
1477   
1478   /* Set up our event to send, with the exception of its target window */
1479   sev.xclient.type = ClientMessage;
1480   sev.xclient.display = gdk_display;
1481   sev.xclient.format = event->client.data_format;
1482   memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
1483   sev.xclient.message_type = event->client.message_type;
1484
1485   gdk_event_send_client_message_to_all_recurse(&sev, gdk_root_window, 0);
1486
1487   gdk_error_warnings = old_warnings;
1488 }
1489
1490 /*
1491  *--------------------------------------------------------------
1492  * gdk_flush
1493  *
1494  *   Flushes the Xlib output buffer and then waits
1495  *   until all requests have been received and processed
1496  *   by the X server. The only real use for this function
1497  *   is in dealing with XShm.
1498  *
1499  * Arguments:
1500  *
1501  * Results:
1502  *
1503  * Side effects:
1504  *
1505  *--------------------------------------------------------------
1506  */
1507
1508 void
1509 gdk_flush (void)
1510 {
1511   XSync (gdk_display, False);
1512 }
1513
1514