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