]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkmain-x11.c
DnD bugfixes (hopefully :). Rasters code is still buggy, methinks - try the dnd in...
[~andy/gtk] / gdk / x11 / gdkmain-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 Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include "../config.h"
19
20 /* If you don't want to use gdk's signal handlers define this */
21 /* #define I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS 1 */
22
23 #include <X11/Xlocale.h>
24 #include <ctype.h>
25 #include <signal.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <limits.h>
30 #ifdef USE_XIM
31 #include <stdarg.h>
32 #endif
33
34 #ifdef HAVE_SYS_SELECT_H
35 #include <sys/select.h>
36 #endif /* HAVE_SYS_SELECT_H_ */
37
38 #define XLIB_ILLEGAL_ACCESS
39 #include <X11/Xatom.h>
40 #include <X11/Xlib.h>
41 #include <X11/Xos.h>
42 #include <X11/Xutil.h>
43 #include <X11/Xmu/WinUtil.h>
44 #ifdef USE_XIM
45 #include <X11/Xresource.h>
46 #endif
47 #include <X11/cursorfont.h>
48 #include "gdk.h"
49 #include "gdkprivate.h"
50 #include "gdkinput.h"
51 #ifdef USE_XIM
52 #include "gdkx.h"
53 #include "gdkkeysyms.h"
54 #endif
55 #include "gdki18n.h"
56
57 #ifndef X_GETTIMEOFDAY
58 #define X_GETTIMEOFDAY(tv)  gettimeofday (tv, NULL)
59 #endif /* X_GETTIMEOFDAY */
60
61
62 #define DOUBLE_CLICK_TIME      250
63 #define TRIPLE_CLICK_TIME      500
64 #define DOUBLE_CLICK_DIST      5
65 #define TRIPLE_CLICK_DIST      5
66
67
68 #ifndef NO_FD_SET
69 #  define SELECT_MASK fd_set
70 #else
71 #  ifndef _AIX
72      typedef long fd_mask;
73 #  endif
74 #  if defined(_IBMR2)
75 #    define SELECT_MASK void
76 #  else
77 #    define SELECT_MASK int
78 #  endif
79 #endif
80
81
82 typedef struct _GdkInput      GdkInput;
83 typedef struct _GdkPredicate  GdkPredicate;
84
85 struct _GdkInput
86 {
87   gint tag;
88   gint source;
89   GdkInputCondition condition;
90   GdkInputFunction function;
91   gpointer data;
92   GdkDestroyNotify destroy;
93 };
94
95 struct _GdkPredicate
96 {
97   GdkEventFunc func;
98   gpointer data;
99 };
100
101 /* 
102  * Private function declarations
103  */
104
105 static GdkEvent *gdk_event_new          (void);
106 static gint      gdk_event_wait         (void);
107 static gint      gdk_event_apply_filters (XEvent *xevent,
108                                           GdkEvent *event,
109                                           GList *filters);
110 static gint      gdk_event_translate    (GdkEvent     *event, 
111                                          XEvent       *xevent);
112 #if 0
113 static Bool      gdk_event_get_type     (Display      *display, 
114                                          XEvent       *xevent, 
115                                          XPointer      arg);
116 #endif
117 static void      gdk_synthesize_click   (GdkEvent     *event, 
118                                          gint          nclicks);
119
120 static void      gdk_dnd_drag_begin     (GdkWindow    *initial_window);
121 static void      gdk_dnd_drag_enter     (Window        dest);
122 static void      gdk_dnd_drag_leave     (Window        dest);
123 static void      gdk_dnd_drag_end       (Window        dest,
124                                          GdkPoint      coords);
125 static GdkAtom   gdk_dnd_check_types    (GdkWindow    *window,
126                                          XEvent       *xevent);
127 #ifdef DEBUG_DND
128 static void      gdk_print_atom         (GdkAtom       anatom);
129 #endif
130
131 /* 
132  * old junk from offix, we might use it though so leave it 
133  */
134 Window       gdk_get_client_window   (Display     *dpy, 
135                                       Window       win);
136 #ifdef WE_HAVE_MOTIF_DROPS_DONE
137 static GdkWindow *  gdk_drop_get_real_window     (GdkWindow   *w, 
138                                                   guint16     *x,
139                                                   guint16     *y);
140 #endif
141 static void         gdk_exit_func                (void);
142 static int          gdk_x_error                  (Display     *display, 
143                                                   XErrorEvent *error);
144 static int          gdk_x_io_error               (Display     *display);
145 static RETSIGTYPE   gdk_signal                   (int          signum);
146
147
148 #ifdef USE_XIM
149 static GdkIM  gdk_im_get                (void);
150 static gint   gdk_im_open               (XrmDatabase db,
151                                          gchar* res_name,
152                                          gchar* rec_class);
153 static void   gdk_im_close              (void);
154 static void   gdk_ic_cleanup            (void);
155 #endif /* USE_XIM */
156
157 /* Private variable declarations
158  */
159 static int initialized = 0;                         /* 1 if the library is initialized,
160                                                      * 0 otherwise.
161                                                      */
162 static int connection_number = 0;                   /* The file descriptor number of our
163                                                      *  connection to the X server. This
164                                                      *  is used so that we may determine
165                                                      *  when events are pending by using
166                                                      *  the "select" system call.
167                                                      */
168
169
170 static struct timeval start;                        /* The time at which the library was
171                                                      *  last initialized.
172                                                      */
173 static struct timeval timer;                        /* Timeout interval to use in the call
174                                                      *  to "select". This is used in
175                                                      *  conjunction with "timerp" to create
176                                                      *  a maximum time to wait for an event
177                                                      *  to arrive.
178                                                      */
179 static struct timeval *timerp;                      /* The actual timer passed to "select"
180                                                      *  This may be NULL, in which case
181                                                      *  "select" will block until an event
182                                                      *  arrives.
183                                                      */
184 static guint32 timer_val;                           /* The timeout length as specified by
185                                                      *  the user in milliseconds.
186                                                      */
187 static GList *inputs;                               /* A list of the input file descriptors
188                                                      *  that we care about. Each list node
189                                                      *  contains a GdkInput struct that describes
190                                                      *  when we are interested in the specified
191                                                      *  file descriptor. That is, when it is
192                                                      *  available for read, write or has an
193                                                      *  exception pending.
194                                                      */
195 static guint32 button_click_time[2];                /* The last 2 button click times. Used
196                                                      *  to determine if the latest button click
197                                                      *  is part of a double or triple click.
198                                                      */
199 static GdkWindow *button_window[2];                 /* The last 2 windows to receive button presses.
200                                                      *  Also used to determine if the latest button
201                                                      *  click is part of a double or triple click.
202                                                      */
203 static guint button_number[2];                      /* The last 2 buttons to be pressed.
204                                                      */
205 static GdkWindowPrivate *xgrab_window = NULL;       /* Window that currently holds the
206                                                      *  x pointer grab
207                                                      */
208
209 #ifdef USE_XIM
210 static gint xim_using;                          /* using XIM Protocol if TRUE */
211 static GdkIM xim_im;                            /* global IM */
212 static XIMStyles* xim_styles;                   /* im supports these styles */
213 static XIMStyle xim_best_allowed_style;
214 static GdkICPrivate *xim_ic;                    /* currently using IC */
215 static GdkWindow* xim_window;                   /* currently using Widow */
216 static GList* xim_ic_list;
217
218 #endif
219
220 #define OTHER_XEVENT_BUFSIZE 4
221 static XEvent other_xevent[OTHER_XEVENT_BUFSIZE];   /* XEvents passed along to user  */
222 static int other_xevent_i = 0;
223 static GList *putback_events = NULL;
224
225 static gulong base_id;
226 static gint autorepeat;
227
228 #ifdef G_ENABLE_DEBUG
229 static GDebugKey gdk_debug_keys[] = {
230   {"events",        GDK_DEBUG_EVENTS},
231   {"misc",          GDK_DEBUG_MISC},
232   {"dnd",           GDK_DEBUG_DND},
233   {"color-context", GDK_DEBUG_COLOR_CONTEXT},
234   {"xim",           GDK_DEBUG_XIM}
235 };
236
237 static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey);
238
239 #endif /* G_ENABLE_DEBUG */
240
241 /*
242  *--------------------------------------------------------------
243  * gdk_init
244  *
245  *   Initialize the library for use.
246  *
247  * Arguments:
248  *   "argc" is the number of arguments.
249  *   "argv" is an array of strings.
250  *
251  * Results:
252  *   "argc" and "argv" are modified to reflect any arguments
253  *   which were not handled. (Such arguments should either
254  *   be handled by the application or dismissed).
255  *
256  * Side effects:
257  *   The library is initialized.
258  *
259  *--------------------------------------------------------------
260  */
261
262 void
263 gdk_init (int    *argc,
264           char ***argv)
265 {
266   XKeyboardState keyboard_state;
267   gint synchronize;
268   gint i, j, k;
269   XClassHint *class_hint;
270   gint argc_orig = *argc;
271   gchar **argv_orig;
272
273   argv_orig = g_malloc ((argc_orig + 1) * sizeof (char*));
274   for (i = 0; i < argc_orig; i++)
275     argv_orig[i] = g_strdup ((*argv)[i]);
276   argv_orig[argc_orig] = NULL;
277
278   X_GETTIMEOFDAY (&start);
279
280 #ifndef I_NEED_TO_ACTUALLY_DEBUG_MY_PROGRAMS
281   signal (SIGHUP, gdk_signal);
282   signal (SIGINT, gdk_signal);
283   signal (SIGQUIT, gdk_signal);
284   signal (SIGBUS, gdk_signal);
285   signal (SIGSEGV, gdk_signal);
286   signal (SIGPIPE, gdk_signal);
287   signal (SIGTERM, gdk_signal);
288 #endif
289
290   gdk_display_name = NULL;
291
292   XSetErrorHandler (gdk_x_error);
293   XSetIOErrorHandler (gdk_x_io_error);
294
295   synchronize = FALSE;
296
297 #ifdef G_ENABLE_DEBUG
298   {
299     gchar *debug_string = getenv("GDK_DEBUG");
300     if (debug_string != NULL)
301       gdk_debug_flags = g_parse_debug_string (debug_string,
302                                               gdk_debug_keys,
303                                               gdk_ndebug_keys);
304   }
305 #endif  /* G_ENABLE_DEBUG */
306
307   if (argc && argv)
308     {
309       if (*argc > 0)
310         gdk_progname = (*argv)[0];
311
312       for (i = 1; i < *argc;)
313         {
314           if ((*argv)[i] == NULL)
315             {
316               i += 1;
317               continue;
318             }
319           
320 #ifdef G_ENABLE_DEBUG     
321           if (strcmp ("--gdk-debug", (*argv)[i]) == 0)
322             {
323               (*argv)[i] = NULL;
324
325               if ((i + 1) < *argc && (*argv)[i + 1])
326                 {
327                   gdk_debug_flags |= g_parse_debug_string ((*argv)[i+1],
328                                                            gdk_debug_keys,
329                                                            gdk_ndebug_keys);
330                   (*argv)[i + 1] = NULL;
331                   i += 1;
332                 }
333             }
334           else if (strcmp ("--gdk-no-debug", (*argv)[i]) == 0)
335             {
336               (*argv)[i] = NULL;
337
338               if ((i + 1) < *argc && (*argv)[i + 1])
339                 {
340                   gdk_debug_flags &= ~g_parse_debug_string ((*argv)[i+1],
341                                                             gdk_debug_keys,
342                                                             gdk_ndebug_keys);
343                   (*argv)[i + 1] = NULL;
344                   i += 1;
345                 }
346             }
347 #endif /* G_ENABLE_DEBUG */
348           else if (strcmp ("--display", (*argv)[i]) == 0)
349             {
350               (*argv)[i] = NULL;
351
352               if ((i + 1) < *argc && (*argv)[i + 1])
353                 {
354                   gdk_display_name = g_strdup ((*argv)[i + 1]);
355                   (*argv)[i + 1] = NULL;
356                   i += 1;
357                 }
358             }
359           else if (strcmp ("--sync", (*argv)[i]) == 0)
360             {
361               (*argv)[i] = NULL;
362               synchronize = TRUE;
363             }
364           else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
365             {
366               (*argv)[i] = NULL;
367               gdk_use_xshm = FALSE;
368             }
369           else if (strcmp ("--name", (*argv)[i]) == 0)
370             {
371               if ((i + 1) < *argc && (*argv)[i + 1])
372                 {
373                   (*argv)[i++] = NULL;
374                   gdk_progname = (*argv)[i];
375                   (*argv)[i] = NULL;
376                 }
377             }
378           else if (strcmp ("--class", (*argv)[i]) == 0)
379             {
380               if ((i + 1) < *argc && (*argv)[i + 1])
381                 {
382                   (*argv)[i++] = NULL;
383                   gdk_progclass = (*argv)[i];
384                   (*argv)[i] = NULL;
385                 }
386             }
387 #ifdef XINPUT_GXI
388           else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
389             {
390               if ((i + 1) < *argc && (*argv)[i + 1])
391                 {
392                   (*argv)[i++] = NULL;
393                   gdk_input_gxid_host = ((*argv)[i]);
394                   (*argv)[i] = NULL;
395                 }
396             }
397           else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
398             {
399               if ((i + 1) < *argc && (*argv)[i + 1])
400                 {
401                   (*argv)[i++] = NULL;
402                   gdk_input_gxid_port = atoi ((*argv)[i]);
403                   (*argv)[i] = NULL;
404                 }
405             }
406 #endif
407 #ifdef USE_XIM
408           else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
409             {
410               if ((i + 1) < *argc && (*argv)[i + 1])
411                 {
412                   (*argv)[i++] = NULL;
413                   if (strcmp ("none", (*argv)[i]) == 0)
414                     gdk_im_set_best_style (GdkIMPreeditNone);
415                   else if (strcmp ("nothing", (*argv)[i]) == 0)
416                     gdk_im_set_best_style (GdkIMPreeditNothing);
417                   else if (strcmp ("area", (*argv)[i]) == 0)
418                     gdk_im_set_best_style (GdkIMPreeditArea);
419                   else if (strcmp ("position", (*argv)[i]) == 0)
420                     gdk_im_set_best_style (GdkIMPreeditPosition);
421                   else if (strcmp ("callbacks", (*argv)[i]) == 0)
422                     gdk_im_set_best_style (GdkIMPreeditCallbacks);
423                 }
424             }
425           else if (strcmp ("--xim-status", (*argv)[i]) == 0)
426             {
427               if ((i + 1) < *argc && (*argv)[i + 1])
428                 {
429                   (*argv)[i++] = NULL;
430                   if (strcmp ("none", (*argv)[i]) == 0)
431                     gdk_im_set_best_style (GdkIMStatusNone);
432                   else if (strcmp ("nothing", (*argv)[i]) == 0)
433                     gdk_im_set_best_style (GdkIMStatusNothing);
434                   else if (strcmp ("area", (*argv)[i]) == 0)
435                     gdk_im_set_best_style (GdkIMStatusArea);
436                   else if (strcmp ("callbacks", (*argv)[i]) == 0)
437                     gdk_im_set_best_style (GdkIMStatusCallbacks);
438                 }
439             }
440 #endif
441
442           i += 1;
443         }
444
445       for (i = 1; i < *argc; i++)
446         {
447           for (k = i; k < *argc; k++)
448             if ((*argv)[k] != NULL)
449               break;
450
451           if (k > i)
452             {
453               k -= i;
454               for (j = i + k; j < *argc; j++)
455                 (*argv)[j-k] = (*argv)[j];
456               *argc -= k;
457             }
458         }
459     }
460   else
461     {
462       gdk_progname = "<unknown>";
463     }
464
465   gdk_display = XOpenDisplay (gdk_display_name);
466   if (!gdk_display)
467     {
468       g_warning ("cannot open display: %s", XDisplayName (gdk_display_name));
469       exit(1);
470     }
471
472   /* This is really crappy. We have to look into the display structure
473    *  to find the base resource id. This is only needed for recording
474    *  and playback of events.
475    */
476   /* base_id = RESOURCE_BASE; */
477   base_id = 0;
478   GDK_NOTE (EVENTS, g_print ("base id: %lu\n", base_id));
479
480   connection_number = ConnectionNumber (gdk_display);
481   GDK_NOTE (MISC,
482     g_print ("connection number: %d\n", connection_number));
483
484   if (synchronize)
485     XSynchronize (gdk_display, True);
486
487   gdk_screen = DefaultScreen (gdk_display);
488   gdk_root_window = RootWindow (gdk_display, gdk_screen);
489
490   gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
491                                           10, 10, 10, 10, 0, 0 , 0);
492   class_hint = XAllocClassHint();
493   class_hint->res_name = gdk_progname;
494   if (gdk_progclass == NULL)
495     {
496       gdk_progclass = g_strdup (gdk_progname);
497       gdk_progclass[0] = toupper (gdk_progclass[0]);
498     }
499   class_hint->res_class = gdk_progclass;
500   XSetClassHint(gdk_display, gdk_leader_window, class_hint);
501   XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
502   XFree (class_hint);
503   
504   for (i = 0; i < argc_orig; i++)
505     g_free(argv_orig[i]);
506   g_free(argv_orig);
507   
508   gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
509   gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
510   gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
511   gdk_wm_window_protocols[0] = gdk_wm_delete_window;
512   gdk_wm_window_protocols[1] = gdk_wm_take_focus;
513   gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
514
515   gdk_dnd.gdk_XdeEnter = gdk_atom_intern("_XDE_ENTER", FALSE);
516   gdk_dnd.gdk_XdeLeave = gdk_atom_intern("_XDE_LEAVE", FALSE);
517   gdk_dnd.gdk_XdeRequest = gdk_atom_intern("_XDE_REQUEST", FALSE);
518   gdk_dnd.gdk_XdeDataAvailable = gdk_atom_intern("_XDE_DATA_AVAILABLE", FALSE);
519   gdk_dnd.gdk_XdeTypelist = gdk_atom_intern("_XDE_TYPELIST", FALSE);
520   gdk_dnd.c->gdk_cursor_dragdefault = XCreateFontCursor(gdk_display, XC_bogosity);
521   gdk_dnd.c->gdk_cursor_dragok = XCreateFontCursor(gdk_display, XC_heart);
522
523   XGetKeyboardControl (gdk_display, &keyboard_state);
524   autorepeat = keyboard_state.global_auto_repeat;
525
526   timer.tv_sec = 0;
527   timer.tv_usec = 0;
528   timerp = NULL;
529
530   button_click_time[0] = 0;
531   button_click_time[1] = 0;
532   button_window[0] = NULL;
533   button_window[1] = NULL;
534   button_number[0] = -1;
535   button_number[1] = -1;
536
537   if (ATEXIT (gdk_exit_func))
538     g_warning ("unable to register exit function");
539
540   gdk_visual_init ();
541   gdk_window_init ();
542   gdk_image_init ();
543   gdk_input_init ();
544
545 #ifdef USE_XIM
546   /* initialize XIM Protocol variables */
547   xim_using = FALSE;
548   xim_im = NULL;
549   xim_styles = NULL;
550   if (!(xim_best_allowed_style & GdkIMPreeditMask))
551     gdk_im_set_best_style (GdkIMPreeditCallbacks);
552   if (!(xim_best_allowed_style & GdkIMStatusMask))
553     gdk_im_set_best_style (GdkIMStatusCallbacks);
554   xim_ic = NULL;
555   xim_window = (GdkWindow*)NULL;
556
557   gdk_im_open (NULL, NULL, NULL);
558 #endif
559
560   initialized = 1;
561 }
562
563 /*
564  *--------------------------------------------------------------
565  * gdk_exit
566  *
567  *   Restores the library to an un-itialized state and exits
568  *   the program using the "exit" system call.
569  *
570  * Arguments:
571  *   "errorcode" is the error value to pass to "exit".
572  *
573  * Results:
574  *   Allocated structures are freed and the program exits
575  *   cleanly.
576  *
577  * Side effects:
578  *
579  *--------------------------------------------------------------
580  */
581
582 void
583 gdk_exit (int errorcode)
584 {
585  /* de-initialisation is done by the gdk_exit_funct(),
586     no need to do this here (Alex J.) */
587  exit (errorcode);
588 }
589
590 /*
591  *--------------------------------------------------------------
592  * gdk_set_locale
593  *
594  * Arguments:
595  *
596  * Results:
597  *
598  * Side effects:
599  *
600  *--------------------------------------------------------------
601  */
602
603 gchar*
604 gdk_set_locale ()
605 {
606   if (!setlocale (LC_ALL,""))
607     g_print ("locale not supported by C library\n");
608
609   if (!XSupportsLocale ())
610     {
611       g_print ("locale not supported by Xlib, locale set to C\n");
612       setlocale (LC_ALL, "C");
613     }
614
615   if (!XSetLocaleModifiers (""))
616     {
617       g_print ("can not set locale modifiers\n");
618     }
619
620   return setlocale (LC_ALL,NULL);
621 }
622
623 /*
624  *--------------------------------------------------------------
625  * gdk_events_pending
626  *
627  *   Returns the number of events pending on the queue.
628  *   These events have already been read from the server
629  *   connection.
630  *
631  * Arguments:
632  *
633  * Results:
634  *   Returns the number of events on XLib's event queue.
635  *
636  * Side effects:
637  *
638  *--------------------------------------------------------------
639  */
640
641 gint
642 gdk_events_pending ()
643 {
644   gint result;
645   GList *tmp_list;
646
647   result = XPending (gdk_display);
648
649   tmp_list = putback_events;
650   while (tmp_list)
651     {
652       result++;
653       tmp_list = tmp_list->next;
654     }
655   
656   return result;
657 }
658
659 /*
660  *--------------------------------------------------------------
661  * gdk_event_get_graphics_expose
662  *
663  *   Waits for a GraphicsExpose or NoExpose event
664  *
665  * Arguments:
666  *
667  * Results: 
668  *   For GraphicsExpose events, returns a pointer to the event
669  *   converted into a GdkEvent Otherwise, returns NULL.
670  *
671  * Side effects:
672  *
673  *-------------------------------------------------------------- */
674
675 static Bool
676 graphics_expose_predicate  (Display  *display,
677                             XEvent   *xevent,
678                             XPointer  arg)
679 {
680   GdkWindowPrivate *private = (GdkWindowPrivate *)arg;
681   
682   g_return_val_if_fail (private != NULL, False);
683
684   if ((xevent->xany.window == private->xwindow) &&
685       ((xevent->xany.type == GraphicsExpose) ||
686        (xevent->xany.type == NoExpose)))
687     return True;
688   else
689     return False;
690 }
691
692 GdkEvent *
693 gdk_event_get_graphics_expose (GdkWindow *window)
694 {
695   XEvent xevent;
696   GdkEvent *event;
697   
698   g_return_val_if_fail (window != NULL, NULL);
699
700   XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer)window);
701
702   if (xevent.xany.type == GraphicsExpose)
703     {
704       event = gdk_event_new ();
705
706       if (gdk_event_translate (event, &xevent))
707         return event;
708       else
709         gdk_event_free (event);
710     }
711   
712   return NULL;  
713 }
714
715 /*
716  *--------------------------------------------------------------
717  * gdk_event_get
718  *
719  *   Gets the next event.
720  *
721  * Arguments:
722  *
723  * Results:
724  *   If an event was received that we care about, returns 
725  *   a pointer to that event, to be freed with gdk_event_free.
726  *   Otherwise, returns NULL. This function will also return
727  *   before an event is received if the timeout interval
728  *   runs out.
729  *
730  * Side effects:
731  *
732  *--------------------------------------------------------------
733  */
734
735 GdkEvent *
736 gdk_event_get (void)
737 {
738   GdkEvent *event;
739   GList *temp_list;
740   XEvent xevent;
741
742 #if 0
743   if (pred)
744     {
745       temp_list = putback_events;
746       while (temp_list)
747         {
748           temp_event = temp_list->data;
749
750           if ((* pred) (temp_event, data))
751             {
752               if (event)
753                 *event = *temp_event;
754               putback_events = g_list_remove_link (putback_events, temp_list);
755               g_list_free (temp_list);
756               return TRUE;
757             }
758
759           temp_list = temp_list->next;
760         }
761
762       event_pred.func = pred;
763       event_pred.data = data;
764
765       if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) & event_pred))
766         if (event)
767           return gdk_event_translate (event, &xevent);
768     }
769   else
770 #endif
771   if (putback_events)
772     {
773       event = putback_events->data;
774       
775       temp_list = putback_events;
776       putback_events = g_list_remove_link (putback_events, temp_list);
777       g_list_free_1 (temp_list);
778       
779       return event;
780     }
781   
782   /* Wait for an event to occur or the timeout to elapse.
783    * If an event occurs "gdk_event_wait" will return TRUE.
784    *  If the timeout elapses "gdk_event_wait" will return
785    *  FALSE.
786    */
787   if (gdk_event_wait ())
788     {
789       /* If we get here we can rest assurred that an event
790        *  has occurred. Read it.
791        */
792 #ifdef USE_XIM
793       gint filter_status;
794       if (xim_using && xim_window)
795         do
796           {             /* don't dispatch events used by IM */
797             XNextEvent (gdk_display, &xevent);
798             filter_status = XFilterEvent (&xevent, 
799                                           GDK_WINDOW_XWINDOW (xim_window));
800           } while (filter_status == True);
801       else
802         XNextEvent (gdk_display, &xevent);
803 #else
804       XNextEvent (gdk_display, &xevent);
805 #endif
806       event = gdk_event_new ();
807
808       event->any.type = GDK_NOTHING;
809       event->any.window = NULL;
810       event->any.send_event = FALSE;
811       event->any.send_event = xevent.xany.send_event;
812       
813       if (gdk_event_translate (event, &xevent))
814         return event;
815       else
816         gdk_event_free (event);
817     }
818
819   return NULL;
820 }
821
822 void
823 gdk_event_put (GdkEvent *event)
824 {
825   GdkEvent *new_event;
826
827   g_return_if_fail (event != NULL);
828
829   new_event = gdk_event_copy (event);
830
831   putback_events = g_list_prepend (putback_events, new_event);
832 }
833
834 /*
835  *--------------------------------------------------------------
836  * gdk_event_copy
837  *
838  *   Copy a event structure into new storage.
839  *
840  * Arguments:
841  *   "event" is the event struct to copy.
842  *
843  * Results:
844  *   A new event structure.  Free it with gdk_event_free.
845  *
846  * Side effects:
847  *   The reference count of the window in the event is increased.
848  *
849  *--------------------------------------------------------------
850  */
851
852 static GMemChunk *event_chunk;
853
854 static GdkEvent*
855 gdk_event_new (void)
856 {
857   GdkEvent *new_event;
858   
859   if (event_chunk == NULL)
860     event_chunk = g_mem_chunk_new ("events",
861                                    sizeof (GdkEvent),
862                                    4096,
863                                    G_ALLOC_AND_FREE);
864
865   new_event = g_chunk_new (GdkEvent, event_chunk);
866
867   return new_event;
868 }
869
870 GdkEvent*
871 gdk_event_copy (GdkEvent *event)
872 {
873   GdkEvent *new_event;
874   
875   g_return_val_if_fail (event != NULL, NULL);
876
877   new_event = gdk_event_new ();
878
879   *new_event = *event;
880   gdk_window_ref (new_event->any.window);
881
882   switch (event->any.type)
883     {
884     case GDK_KEY_PRESS:
885     case GDK_KEY_RELEASE:
886       new_event->key.string = g_strdup (event->key.string);
887       break;
888
889     case GDK_ENTER_NOTIFY:
890     case GDK_LEAVE_NOTIFY:
891       if (event->crossing.subwindow != NULL)
892         gdk_window_ref (event->crossing.subwindow);
893       break;
894
895     case GDK_DROP_DATA_AVAIL:
896       new_event->dropdataavailable.data_type = g_strdup (event->dropdataavailable.data_type);
897       new_event->dropdataavailable.data = g_malloc (event->dropdataavailable.data_numbytes);
898       memcpy (new_event->dropdataavailable.data,
899               event->dropdataavailable.data, 
900               event->dropdataavailable.data_numbytes);
901       break;
902
903     default:
904       break;
905     }
906
907   return new_event;
908 }
909
910 /*
911  *--------------------------------------------------------------
912  * gdk_event_free
913  *
914  *   Free a event structure obtained from gdk_event_copy.  Do not use
915  *   with other event structures.
916  *
917  * Arguments:
918  *   "event" is the event struct to free.
919  *
920  * Results:
921  *
922  * Side effects:
923  *   The reference count of the window in the event is decreased and
924  *   might be freed, too.
925  *
926  *-------------------------------------------------------------- */
927
928 void
929 gdk_event_free (GdkEvent *event)
930 {
931   g_assert (event_chunk != NULL);
932   g_return_if_fail (event != NULL);
933
934   if (event->any.window)
935     gdk_window_unref (event->any.window);
936
937   switch (event->any.type)
938     {
939     case GDK_KEY_PRESS:
940     case GDK_KEY_RELEASE:
941       g_free (event->key.string);
942       break;
943
944     case GDK_ENTER_NOTIFY:
945     case GDK_LEAVE_NOTIFY:
946       if (event->crossing.subwindow != NULL)
947         gdk_window_unref (event->crossing.subwindow);
948       break;
949
950     case GDK_DROP_DATA_AVAIL:
951       g_free (event->dropdataavailable.data_type);
952       g_free (event->dropdataavailable.data);
953       break;
954
955     case GDK_DRAG_REQUEST:
956       g_free (event->dragrequest.data_type);
957       break;
958
959     default:
960       break;
961     }
962
963   g_mem_chunk_free (event_chunk, event);
964 }
965
966 /*
967  *--------------------------------------------------------------
968  * gdk_set_show_events
969  *
970  *   Turns on/off the showing of events.
971  *
972  * Arguments:
973  *   "show_events" is a boolean describing whether or
974  *   not to show the events gdk receives.
975  *
976  * Results:
977  *
978  * Side effects:
979  *   When "show_events" is TRUE, calls to "gdk_event_get"
980  *   will output debugging informatin regarding the event
981  *   received to stdout.
982  *
983  *--------------------------------------------------------------
984  */
985
986 void
987 gdk_set_show_events (int show_events)
988 {
989   if (show_events)
990     gdk_debug_flags |= GDK_DEBUG_EVENTS;
991   else
992     gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
993 }
994
995 void
996 gdk_set_use_xshm (gint use_xshm)
997 {
998   gdk_use_xshm = use_xshm;
999 }
1000
1001 gint
1002 gdk_get_show_events ()
1003 {
1004   return gdk_debug_flags & GDK_DEBUG_EVENTS;
1005 }
1006
1007 gint
1008 gdk_get_use_xshm ()
1009 {
1010   return gdk_use_xshm;
1011 }
1012
1013 /*
1014  *--------------------------------------------------------------
1015  * gdk_time_get
1016  *
1017  *   Get the number of milliseconds since the library was
1018  *   initialized.
1019  *
1020  * Arguments:
1021  *
1022  * Results:
1023  *   The time since the library was initialized is returned.
1024  *   This time value is accurate to milliseconds even though
1025  *   a more accurate time down to the microsecond could be
1026  *   returned.
1027  *
1028  * Side effects:
1029  *
1030  *--------------------------------------------------------------
1031  */
1032
1033 guint32
1034 gdk_time_get ()
1035 {
1036   struct timeval end;
1037   struct timeval elapsed;
1038   guint32 milliseconds;
1039
1040   X_GETTIMEOFDAY (&end);
1041
1042   if (start.tv_usec > end.tv_usec)
1043     {
1044       end.tv_usec += 1000000;
1045       end.tv_sec--;
1046     }
1047   elapsed.tv_sec = end.tv_sec - start.tv_sec;
1048   elapsed.tv_usec = end.tv_usec - start.tv_usec;
1049
1050   milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
1051
1052   return milliseconds;
1053 }
1054
1055 /*
1056  *--------------------------------------------------------------
1057  * gdk_timer_get
1058  *
1059  *   Returns the current timer.
1060  *
1061  * Arguments:
1062  *
1063  * Results:
1064  *   Returns the current timer interval. This interval is
1065  *   in units of milliseconds.
1066  *
1067  * Side effects:
1068  *
1069  *--------------------------------------------------------------
1070  */
1071
1072 guint32
1073 gdk_timer_get ()
1074 {
1075   return timer_val;
1076 }
1077
1078 /*
1079  *--------------------------------------------------------------
1080  * gdk_timer_set
1081  *
1082  *   Sets the timer interval.
1083  *
1084  * Arguments:
1085  *   "milliseconds" is the new value for the timer.
1086  *
1087  * Results:
1088  *
1089  * Side effects:
1090  *   Calls to "gdk_event_get" will last for a maximum
1091  *   of time of "milliseconds". However, a value of 0
1092  *   milliseconds will cause "gdk_event_get" to block
1093  *   indefinately until an event is received.
1094  *
1095  *--------------------------------------------------------------
1096  */
1097
1098 void
1099 gdk_timer_set (guint32 milliseconds)
1100 {
1101   timer_val = milliseconds;
1102   timer.tv_sec = milliseconds / 1000;
1103   timer.tv_usec = (milliseconds % 1000) * 1000;
1104
1105 }
1106
1107 void
1108 gdk_timer_enable ()
1109 {
1110   timerp = &timer;
1111 }
1112
1113 void
1114 gdk_timer_disable ()
1115 {
1116   timerp = NULL;
1117 }
1118
1119 gint
1120 gdk_input_add_full (gint              source,
1121                     GdkInputCondition condition,
1122                     GdkInputFunction  function,
1123                     gpointer          data,
1124                     GdkDestroyNotify  destroy)
1125 {
1126   static gint next_tag = 1;
1127   GList *list;
1128   GdkInput *input;
1129   gint tag;
1130
1131   tag = 0;
1132   list = inputs;
1133
1134   while (list)
1135     {
1136       input = list->data;
1137       list = list->next;
1138
1139       if ((input->source == source) && (input->condition == condition))
1140         {
1141           if (input->destroy)
1142             (input->destroy) (input->data);
1143           input->function = function;
1144           input->data = data;
1145           input->destroy = destroy;
1146           tag = input->tag;
1147         }
1148     }
1149
1150   if (!tag)
1151     {
1152       input = g_new (GdkInput, 1);
1153       input->tag = next_tag++;
1154       input->source = source;
1155       input->condition = condition;
1156       input->function = function;
1157       input->data = data;
1158       input->destroy = destroy;
1159       tag = input->tag;
1160
1161       inputs = g_list_prepend (inputs, input);
1162     }
1163
1164   return tag;
1165 }
1166
1167 gint
1168 gdk_input_add (gint              source,
1169                GdkInputCondition condition,
1170                GdkInputFunction  function,
1171                gpointer          data)
1172 {
1173   return gdk_input_add_interp (source, condition, function, data, NULL);
1174 }
1175
1176 void
1177 gdk_input_remove (gint tag)
1178 {
1179   GList *list;
1180   GList *temp_list;
1181   GdkInput *input;
1182
1183   list = inputs;
1184   while (list)
1185     {
1186       input = list->data;
1187
1188       if (input->tag == tag)
1189         {
1190           if (input->destroy)
1191             (input->destroy) (input->data);
1192
1193           temp_list = list;
1194
1195           if (list->next)
1196             list->next->prev = list->prev;
1197           if (list->prev)
1198             list->prev->next = list->next;
1199           if (inputs == list)
1200             inputs = list->next;
1201
1202           temp_list->next = NULL;
1203           temp_list->prev = NULL;
1204
1205           g_free (temp_list->data);
1206           g_list_free (temp_list);
1207           break;
1208         }
1209
1210       list = list->next;
1211     }
1212 }
1213
1214 /*
1215  *--------------------------------------------------------------
1216  * gdk_pointer_grab
1217  *
1218  *   Grabs the pointer to a specific window
1219  *
1220  * Arguments:
1221  *   "window" is the window which will receive the grab
1222  *   "owner_events" specifies whether events will be reported as is,
1223  *     or relative to "window"
1224  *   "event_mask" masks only interesting events
1225  *   "confine_to" limits the cursor movement to the specified window
1226  *   "cursor" changes the cursor for the duration of the grab
1227  *   "time" specifies the time
1228  *
1229  * Results:
1230  *
1231  * Side effects:
1232  *   requires a corresponding call to gdk_pointer_ungrab
1233  *
1234  *--------------------------------------------------------------
1235  */
1236
1237 gint
1238 gdk_pointer_grab (GdkWindow *     window,
1239                   gint            owner_events,
1240                   GdkEventMask    event_mask,
1241                   GdkWindow *     confine_to,
1242                   GdkCursor *     cursor,
1243                   guint32         time)
1244 {
1245   /*  From gdkwindow.c  */
1246   extern int nevent_masks;
1247   extern int event_mask_table[];
1248
1249   gint return_val;
1250   GdkWindowPrivate *window_private;
1251   GdkWindowPrivate *confine_to_private;
1252   GdkCursorPrivate *cursor_private;
1253   guint xevent_mask;
1254   Window xwindow;
1255   Window xconfine_to;
1256   Cursor xcursor;
1257   int i;
1258
1259   g_return_val_if_fail (window != NULL, 0);
1260
1261   window_private = (GdkWindowPrivate*) window;
1262   confine_to_private = (GdkWindowPrivate*) confine_to;
1263   cursor_private = (GdkCursorPrivate*) cursor;
1264
1265   xwindow = window_private->xwindow;
1266
1267   if (!confine_to || confine_to_private->destroyed)
1268     xconfine_to = None;
1269   else
1270     xconfine_to = confine_to_private->xwindow;
1271
1272   if (!cursor)
1273     xcursor = None;
1274   else
1275     xcursor = cursor_private->xcursor;
1276
1277
1278   xevent_mask = 0;
1279   for (i = 0; i < nevent_masks; i++)
1280     {
1281       if (event_mask & (1 << (i + 1)))
1282         xevent_mask |= event_mask_table[i];
1283     }
1284
1285   if (((GdkWindowPrivate *)window)->extension_events &&
1286       gdk_input_vtable.grab_pointer)
1287     return_val = gdk_input_vtable.grab_pointer (window,
1288                                                 owner_events,
1289                                                 event_mask,
1290                                                 confine_to,
1291                                                 time);
1292   else
1293     return_val = Success;
1294   
1295   if (return_val == Success)
1296     {
1297       if (!window_private->destroyed)
1298         return_val = XGrabPointer (window_private->xdisplay,
1299                                    xwindow,
1300                                    owner_events,
1301                                    xevent_mask,
1302                                    GrabModeAsync, GrabModeAsync,
1303                                    xconfine_to,
1304                                    xcursor,
1305                                    time);
1306       else
1307         return_val = AlreadyGrabbed;
1308     }
1309
1310   if (return_val == GrabSuccess)
1311     xgrab_window = window_private;
1312   
1313   return return_val;
1314 }
1315
1316 /*
1317  *--------------------------------------------------------------
1318  * gdk_pointer_ungrab
1319  *
1320  *   Releases any pointer grab
1321  *
1322  * Arguments:
1323  *
1324  * Results:
1325  *
1326  * Side effects:
1327  *
1328  *--------------------------------------------------------------
1329  */
1330
1331 void
1332 gdk_pointer_ungrab (guint32 time)
1333 {
1334   if (gdk_input_vtable.ungrab_pointer)
1335     gdk_input_vtable.ungrab_pointer (time);
1336
1337   XUngrabPointer (gdk_display, time);
1338   xgrab_window = NULL;
1339 }
1340
1341 /*
1342  *--------------------------------------------------------------
1343  * gdk_pointer_is_grabbed
1344  *
1345  *   Tell wether there is an active x pointer grab in effect
1346  *
1347  * Arguments:
1348  *
1349  * Results:
1350  *
1351  * Side effects:
1352  *
1353  *--------------------------------------------------------------
1354  */
1355
1356 gint
1357 gdk_pointer_is_grabbed (void)
1358 {
1359   return xgrab_window != NULL;
1360 }
1361
1362 /*
1363  *--------------------------------------------------------------
1364  * gdk_keyboard_grab
1365  *
1366  *   Grabs the keyboard to a specific window
1367  *
1368  * Arguments:
1369  *   "window" is the window which will receive the grab
1370  *   "owner_events" specifies whether events will be reported as is,
1371  *     or relative to "window"
1372  *   "time" specifies the time
1373  *
1374  * Results:
1375  *
1376  * Side effects:
1377  *   requires a corresponding call to gdk_keyboard_ungrab
1378  *
1379  *--------------------------------------------------------------
1380  */
1381
1382 gint
1383 gdk_keyboard_grab (GdkWindow *     window,
1384                    gint            owner_events,
1385                    guint32         time)
1386 {
1387   GdkWindowPrivate *window_private;
1388   Window xwindow;
1389
1390   g_return_val_if_fail (window != NULL, 0);
1391
1392   window_private = (GdkWindowPrivate*) window;
1393   xwindow = window_private->xwindow;
1394
1395   if (!window_private->destroyed)
1396     return XGrabKeyboard (window_private->xdisplay,
1397                           xwindow,
1398                           owner_events,
1399                           GrabModeAsync, GrabModeAsync,
1400                           time);
1401   else
1402     return AlreadyGrabbed;
1403 }
1404
1405 /*
1406  *--------------------------------------------------------------
1407  * gdk_keyboard_ungrab
1408  *
1409  *   Releases any keyboard grab
1410  *
1411  * Arguments:
1412  *
1413  * Results:
1414  *
1415  * Side effects:
1416  *
1417  *--------------------------------------------------------------
1418  */
1419
1420 void
1421 gdk_keyboard_ungrab (guint32 time)
1422 {
1423   XUngrabKeyboard (gdk_display, time);
1424 }
1425
1426 /*
1427  *--------------------------------------------------------------
1428  * gdk_screen_width
1429  *
1430  *   Return the width of the screen.
1431  *
1432  * Arguments:
1433  *
1434  * Results:
1435  *
1436  * Side effects:
1437  *
1438  *--------------------------------------------------------------
1439  */
1440
1441 gint
1442 gdk_screen_width ()
1443 {
1444   gint return_val;
1445
1446   return_val = DisplayWidth (gdk_display, gdk_screen);
1447
1448   return return_val;
1449 }
1450
1451 /*
1452  *--------------------------------------------------------------
1453  * gdk_screen_height
1454  *
1455  *   Return the height of the screen.
1456  *
1457  * Arguments:
1458  *
1459  * Results:
1460  *
1461  * Side effects:
1462  *
1463  *--------------------------------------------------------------
1464  */
1465
1466 gint
1467 gdk_screen_height ()
1468 {
1469   gint return_val;
1470
1471   return_val = DisplayHeight (gdk_display, gdk_screen);
1472
1473   return return_val;
1474 }
1475
1476 void
1477 gdk_key_repeat_disable ()
1478 {
1479   XAutoRepeatOff (gdk_display);
1480 }
1481
1482 void
1483 gdk_key_repeat_restore ()
1484 {
1485   if (autorepeat)
1486     XAutoRepeatOn (gdk_display);
1487   else
1488     XAutoRepeatOff (gdk_display);
1489 }
1490
1491
1492 /*
1493  *--------------------------------------------------------------
1494  * gdk_flush
1495  *
1496  *   Flushes the Xlib output buffer and then waits
1497  *   until all requests have been received and processed
1498  *   by the X server. The only real use for this function
1499  *   is in dealing with XShm.
1500  *
1501  * Arguments:
1502  *
1503  * Results:
1504  *
1505  * Side effects:
1506  *
1507  *--------------------------------------------------------------
1508  */
1509
1510 void gdk_flush ()
1511 {
1512   XSync (gdk_display, False);
1513 }
1514
1515
1516 void
1517 gdk_beep ()
1518 {
1519   XBell(gdk_display, 100);
1520 }
1521
1522
1523 /*
1524  *--------------------------------------------------------------
1525  * gdk_event_wait
1526  *
1527  *   Waits until an event occurs or the timer runs out.
1528  *
1529  * Arguments:
1530  *
1531  * Results:
1532  *   Returns TRUE if an event is ready to be read and FALSE
1533  *   if the timer ran out.
1534  *
1535  * Side effects:
1536  *
1537  *--------------------------------------------------------------
1538  */
1539
1540 static gint
1541 gdk_event_wait ()
1542 {
1543   GList *list;
1544   GdkInput *input;
1545   GdkInputCondition condition;
1546   SELECT_MASK readfds;
1547   SELECT_MASK writefds;
1548   SELECT_MASK exceptfds;
1549   int max_input;
1550   int nfd;
1551
1552   /* If there are no events pending we will wait for an event.
1553    * The time we wait is dependant on the "timer". If no timer
1554    *  has been specified then we'll block until an event arrives.
1555    *  If a timer has been specified we'll block until an event
1556    *  arrives or the timer expires. (This is all done using the
1557    *  "select" system call).
1558    */
1559
1560   if (XPending (gdk_display) == 0)
1561     {
1562       FD_ZERO (&readfds);
1563       FD_ZERO (&writefds);
1564       FD_ZERO (&exceptfds);
1565
1566       FD_SET (connection_number, &readfds);
1567       max_input = connection_number;
1568
1569       list = inputs;
1570       while (list)
1571         {
1572           input = list->data;
1573           list = list->next;
1574
1575           if (input->condition & GDK_INPUT_READ)
1576             FD_SET (input->source, &readfds);
1577           if (input->condition & GDK_INPUT_WRITE)
1578             FD_SET (input->source, &writefds);
1579           if (input->condition & GDK_INPUT_EXCEPTION)
1580             FD_SET (input->source, &exceptfds);
1581
1582           max_input = MAX (max_input, input->source);
1583         }
1584
1585       nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
1586
1587       timerp = NULL;
1588       timer_val = 0;
1589
1590       if (nfd > 0)
1591         {
1592           if (FD_ISSET (connection_number, &readfds))
1593             {
1594               if (XPending (gdk_display) == 0)
1595                 {
1596                   if (nfd == 1)
1597                     {
1598                       XNoOp (gdk_display);
1599                       XFlush (gdk_display);
1600                     }
1601                   return FALSE;
1602                 }
1603               else
1604                 return TRUE;
1605             }
1606
1607           list = inputs;
1608           while (list)
1609             {
1610               input = list->data;
1611               list = list->next;
1612
1613               condition = 0;
1614               if (FD_ISSET (input->source, &readfds))
1615                 condition |= GDK_INPUT_READ;
1616               if (FD_ISSET (input->source, &writefds))
1617                 condition |= GDK_INPUT_WRITE;
1618               if (FD_ISSET (input->source, &exceptfds))
1619                 condition |= GDK_INPUT_EXCEPTION;
1620
1621               if (condition && input->function)
1622                 (* input->function) (input->data, input->source, condition);
1623             }
1624         }
1625     }
1626   else
1627     return TRUE;
1628
1629   return FALSE;
1630 }
1631
1632 static gint
1633 gdk_event_apply_filters (XEvent *xevent,
1634                          GdkEvent *event,
1635                          GList *filters)
1636 {
1637   GdkEventFilter *filter;
1638   GList *tmp_list;
1639   GdkFilterReturn result;
1640
1641   tmp_list = filters;
1642   
1643   while (tmp_list)
1644     {
1645       filter = (GdkEventFilter *)tmp_list->data;
1646
1647       result = (*filter->function)(xevent, event, filter->data);
1648       if (result !=  GDK_FILTER_CONTINUE)
1649         return result;
1650         
1651       tmp_list = tmp_list->next;
1652     }
1653
1654   return GDK_FILTER_CONTINUE;
1655 }
1656
1657 static gint
1658 gdk_event_translate (GdkEvent *event,
1659                      XEvent   *xevent)
1660 {
1661
1662   GdkWindow *window;
1663   GdkWindowPrivate *window_private;
1664   XComposeStatus compose;
1665   int charcount;
1666 #ifdef USE_XIM
1667   static gchar* buf = NULL;
1668   static gint buf_len= 0;
1669 #else
1670   char buf[16];
1671 #endif
1672   gint return_val;
1673
1674   /* Are static variables used for this purpose thread-safe? */
1675
1676   return_val = FALSE;
1677
1678   /* Find the GdkWindow that this event occurred in.
1679    * All events occur in some GdkWindow (otherwise, why
1680    *  would we be receiving them). It really is an error
1681    *  to receive an event for which we cannot find the
1682    *  corresponding GdkWindow. We handle events with window=None
1683    *  specially - they are generated by XFree86's XInput under
1684    *  some circumstances.
1685    */
1686
1687   if ((xevent->xany.window == None) &&
1688       gdk_input_vtable.window_none_event)
1689     {
1690       return_val = gdk_input_vtable.window_none_event (event,xevent);
1691
1692       if (return_val >= 0)      /* was handled */
1693         return return_val;
1694       else
1695         return_val = FALSE;
1696     }
1697
1698   window = gdk_window_lookup (xevent->xany.window);
1699   window_private = (GdkWindowPrivate *) window;
1700
1701   if (window != NULL)
1702     gdk_window_ref (window);
1703   else if(gdk_null_window_warnings) /* Special purpose programs that
1704                                        get events for other windows may
1705                                        want to disable this */
1706     g_warning ("%#lx -> NULL\n", xevent->xany.window);
1707
1708   /* Check for filters for this window */
1709
1710   {
1711     GdkFilterReturn result;
1712     result = gdk_event_apply_filters (xevent, event,
1713                                       window_private
1714                                       ?window_private->filters
1715                                       :gdk_default_filters);
1716     
1717     if (result != GDK_FILTER_CONTINUE)
1718       {
1719         return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1720       }
1721   }
1722
1723   /* We do a "manual" conversion of the XEvent to a
1724    *  GdkEvent. The structures are mostly the same so
1725    *  the conversion is fairly straightforward. We also
1726    *  optionally print debugging info regarding events
1727    *  received.
1728    */
1729   /* Addendum:
1730    * During drag & drop you get events where the pointer is
1731    * in other windows. Need to just do finer-grained checking
1732    */
1733   switch (xevent->type)
1734     {
1735     case KeyPress:
1736       /* Lookup the string corresponding to the given keysym.
1737        */
1738 #ifdef USE_XIM
1739       if (buf_len == 0) 
1740         {
1741           buf_len = 128;
1742           buf = g_new (gchar, buf_len);
1743         }
1744       if (xim_using == TRUE && xim_ic)
1745         {
1746           Status status;
1747           
1748           /* Clear keyval. Depending on status, may not be set */
1749           event->key.keyval = GDK_VoidSymbol;
1750           charcount = XmbLookupString(xim_ic->xic,
1751                                       &xevent->xkey, buf, buf_len-1,
1752                                       (KeySym*) &event->key.keyval,
1753                                       &status);
1754           if (status == XBufferOverflow)
1755             {                     /* retry */
1756               /* alloc adequate size of buffer */
1757               GDK_NOTE (XIM,
1758                 g_print("XIM: overflow (required %i)\n", charcount));
1759
1760               while (buf_len <= charcount)
1761                 buf_len *= 2;
1762               buf = (gchar *) g_realloc (buf, buf_len);
1763              
1764               charcount = XmbLookupString (xim_ic->xic,
1765                                            &xevent->xkey, buf, buf_len-1,
1766                                            (KeySym*) &event->key.keyval,
1767                                            &status);
1768             }
1769           if (status == XLookupNone)
1770             {
1771               return_val = FALSE;
1772               break;
1773             }
1774         }
1775       else
1776         charcount = XLookupString (&xevent->xkey, buf, buf_len,
1777                                    (KeySym*) &event->key.keyval,
1778                                    &compose);
1779 #else
1780       charcount = XLookupString (&xevent->xkey, buf, 16,
1781                                  (KeySym*) &event->key.keyval,
1782                                  &compose);
1783 #endif
1784       if (charcount > 0 && buf[charcount-1] == '\0')
1785         charcount --;
1786       else
1787         buf[charcount] = '\0';
1788
1789       /* Print debugging info.
1790        */
1791 #ifdef G_ENABLE_DEBUG
1792       if (gdk_debug_flags & GDK_DEBUG_EVENTS)
1793         {
1794           g_print ("key press:\twindow: %ld  key: %12s  %d\n",
1795                    xevent->xkey.window - base_id,
1796                    event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
1797                    event->key.keyval);
1798           if (charcount > 0)
1799             g_print ("\t\tlength: %4d string: \"%s\"\n",
1800                      charcount, buf);
1801         }
1802 #endif /* G_ENABLE_DEBUG */
1803
1804       event->key.type = GDK_KEY_PRESS;
1805       event->key.window = window;
1806       event->key.time = xevent->xkey.time;
1807       event->key.state = (GdkModifierType) xevent->xkey.state;
1808       event->key.string = g_strdup (buf);
1809       event->key.length = charcount;
1810
1811       return_val = window_private && !window_private->destroyed;
1812       
1813       if (!return_val)
1814         g_free (event->key.string);
1815       
1816       break;
1817
1818     case KeyRelease:
1819       /* Lookup the string corresponding to the given keysym.
1820        */
1821       charcount = XLookupString (&xevent->xkey, buf, 16,
1822                                  (KeySym*) &event->key.keyval,
1823                                  &compose);
1824
1825       /* Print debugging info.
1826        */
1827       GDK_NOTE (EVENTS, 
1828         g_print ("key release:\t\twindow: %ld  key: %12s  %d\n",
1829                  xevent->xkey.window - base_id,
1830                  XKeysymToString (event->key.keyval),
1831                  event->key.keyval));
1832
1833       event->key.type = GDK_KEY_RELEASE;
1834       event->key.window = window;
1835       event->key.time = xevent->xkey.time;
1836       event->key.state = (GdkModifierType) xevent->xkey.state;
1837       event->key.length = 0;
1838       event->key.string = NULL;
1839
1840       return_val = window_private && !window_private->destroyed;
1841       break;
1842
1843     case ButtonPress:
1844       /* Print debugging info.
1845        */
1846       GDK_NOTE (EVENTS, 
1847         g_print ("button press[%d]:\t\twindow: %ld  x,y: %d %d  button: %d\n",
1848                  window_private?window_private->dnd_drag_enabled:0,
1849                  xevent->xbutton.window - base_id,
1850                  xevent->xbutton.x, xevent->xbutton.y,
1851                  xevent->xbutton.button));
1852
1853       if (window_private &&
1854           (window_private->extension_events != 0) &&
1855           gdk_input_ignore_core)
1856         break;
1857
1858       event->button.type = GDK_BUTTON_PRESS;
1859       event->button.window = window;
1860       event->button.time = xevent->xbutton.time;
1861       event->button.x = xevent->xbutton.x;
1862       event->button.y = xevent->xbutton.y;
1863       event->button.x_root = (gfloat)xevent->xbutton.x_root;
1864       event->button.y_root = (gfloat)xevent->xbutton.y_root;
1865       event->button.pressure = 0.5;
1866       event->button.xtilt = 0;
1867       event->button.ytilt = 0;
1868       event->button.state = (GdkModifierType) xevent->xbutton.state;
1869       event->button.button = xevent->xbutton.button;
1870       event->button.source = GDK_SOURCE_MOUSE;
1871       event->button.deviceid = GDK_CORE_POINTER;
1872
1873       if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1874           (event->button.window == button_window[1]) &&
1875           (event->button.button == button_number[1]))
1876         {
1877           gdk_synthesize_click (event, 3);
1878
1879           button_click_time[1] = 0;
1880           button_click_time[0] = 0;
1881           button_window[1] = NULL;
1882           button_window[0] = 0;
1883           button_number[1] = -1;
1884           button_number[0] = -1;
1885         }
1886       else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1887                (event->button.window == button_window[0]) &&
1888                (event->button.button == button_number[0]))
1889         {
1890           gdk_synthesize_click (event, 2);
1891
1892           button_click_time[1] = button_click_time[0];
1893           button_click_time[0] = event->button.time;
1894           button_window[1] = button_window[0];
1895           button_window[0] = event->button.window;
1896           button_number[1] = button_number[0];
1897           button_number[0] = event->button.button;
1898         }
1899       else
1900         {
1901           button_click_time[1] = 0;
1902           button_click_time[0] = event->button.time;
1903           button_window[1] = NULL;
1904           button_window[0] = event->button.window;
1905           button_number[1] = -1;
1906           button_number[0] = event->button.button;
1907         }
1908       if(window_private
1909          && window_private->dnd_drag_enabled
1910          && !gdk_dnd.drag_perhaps
1911          && event->button.button == 1
1912          && !gdk_dnd.drag_really)
1913         {
1914           gdk_dnd.drag_perhaps = 1;
1915           gdk_dnd.dnd_drag_start.x = xevent->xbutton.x_root;
1916           gdk_dnd.dnd_drag_start.y = xevent->xbutton.y_root;
1917           gdk_dnd.real_sw = window_private;
1918           
1919           if(gdk_dnd.drag_startwindows)
1920             {
1921               g_free(gdk_dnd.drag_startwindows);
1922               gdk_dnd.drag_startwindows = NULL;
1923             }
1924           gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
1925           gdk_dnd.dnd_grabbed = FALSE;
1926
1927           {
1928             /* Set motion mask for first DnD'd window, since it
1929                will be the one that is actually dragged */
1930             XWindowAttributes dnd_winattr;
1931             XSetWindowAttributes dnd_setwinattr;
1932
1933             /* We need to get motion events while the button is down, so
1934                we can know whether to really start dragging or not... */
1935             XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
1936                                  &dnd_winattr);
1937             
1938             window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
1939             dnd_setwinattr.event_mask = 
1940               window_private->dnd_drag_eventmask = ButtonMotionMask |
1941                         EnterWindowMask | LeaveWindowMask;
1942             XChangeWindowAttributes(gdk_display, window_private->xwindow,
1943                                     CWEventMask, &dnd_setwinattr);
1944         }
1945       }
1946       return_val = window_private && !window_private->destroyed;
1947       break;
1948
1949     case ButtonRelease:
1950       /* Print debugging info.
1951        */
1952       GDK_NOTE (EVENTS, 
1953         g_print ("button release[%d]:\twindow: %ld  x,y: %d %d  button: %d\n",
1954                  window_private?window_private->dnd_drag_enabled:0,
1955                  xevent->xbutton.window - base_id,
1956                  xevent->xbutton.x, xevent->xbutton.y,
1957                  xevent->xbutton.button));
1958
1959       if (window_private &&
1960           (window_private->extension_events != 0) &&
1961           gdk_input_ignore_core)
1962         break;
1963
1964       event->button.type = GDK_BUTTON_RELEASE;
1965       event->button.window = window;
1966       event->button.time = xevent->xbutton.time;
1967       event->button.x = xevent->xbutton.x;
1968       event->button.y = xevent->xbutton.y;
1969       event->button.x_root = (gfloat)xevent->xbutton.x_root;
1970       event->button.y_root = (gfloat)xevent->xbutton.y_root;
1971       event->button.pressure = 0.5;
1972       event->button.xtilt = 0;
1973       event->button.ytilt = 0;
1974       event->button.state = (GdkModifierType) xevent->xbutton.state;
1975       event->button.button = xevent->xbutton.button;
1976       event->button.source = GDK_SOURCE_MOUSE;
1977       event->button.deviceid = GDK_CORE_POINTER;
1978
1979       gdk_dnd.last_drop_time = xevent->xbutton.time;
1980       if(gdk_dnd.drag_perhaps)
1981         {
1982           {
1983             XSetWindowAttributes attrs;
1984             /* Reset event mask to pre-drag value, assuming event_mask
1985                doesn't change during drag */
1986             attrs.event_mask = gdk_dnd.real_sw->dnd_drag_savedeventmask;
1987             XChangeWindowAttributes(gdk_display, gdk_dnd.real_sw->xwindow,
1988                                       CWEventMask, &attrs);
1989           }
1990           
1991           if (gdk_dnd.dnd_grabbed) 
1992             {
1993               gdk_dnd_display_drag_cursor(-2,
1994                                           -2,
1995                                           FALSE, TRUE);
1996               XUngrabPointer(gdk_display, CurrentTime);
1997               gdk_dnd.dnd_grabbed = FALSE;
1998             }
1999           
2000         if(gdk_dnd.drag_really)
2001           {
2002           GdkPoint foo;
2003           foo.x = xevent->xbutton.x_root;
2004           foo.y = xevent->xbutton.y_root;
2005                           
2006           if(gdk_dnd.dnd_drag_target != None)
2007             gdk_dnd_drag_end(gdk_dnd.dnd_drag_target, foo);
2008           gdk_dnd.drag_really = 0;
2009
2010           gdk_dnd.drag_numwindows = 0;
2011           if(gdk_dnd.drag_startwindows)
2012             {
2013             g_free(gdk_dnd.drag_startwindows);
2014             gdk_dnd.drag_startwindows = NULL;
2015             }
2016
2017           gdk_dnd.real_sw = NULL;
2018           }
2019
2020         gdk_dnd.drag_perhaps = 0;
2021         gdk_dnd.dnd_drag_start.x = gdk_dnd.dnd_drag_start.y = 0;
2022         gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2023         gdk_dnd.dnd_drag_dropzone.width = gdk_dnd.dnd_drag_dropzone.height = 0;
2024         gdk_dnd.dnd_drag_curwin = None;
2025         return_val = window_private?TRUE:FALSE;
2026       } else
2027         return_val = window_private && !window_private->destroyed;
2028       break;
2029
2030     case MotionNotify:
2031       /* Print debugging info.
2032        */
2033       GDK_NOTE (EVENTS,
2034         g_print ("motion notify:\t\twindow: %ld  x,y: %d %d  hint: %s d:%d r%d\n",
2035                  xevent->xmotion.window - base_id,
2036                  xevent->xmotion.x, xevent->xmotion.y,
2037                  (xevent->xmotion.is_hint) ? "true" : "false",
2038                  gdk_dnd.drag_perhaps, gdk_dnd.drag_really));
2039
2040       if (window_private &&
2041           (window_private->extension_events != 0) &&
2042           gdk_input_ignore_core)
2043         break;
2044
2045       event->motion.type = GDK_MOTION_NOTIFY;
2046       event->motion.window = window;
2047       event->motion.time = xevent->xmotion.time;
2048       event->motion.x = xevent->xmotion.x;
2049       event->motion.y = xevent->xmotion.y;
2050       event->motion.x_root = (gfloat)xevent->xmotion.x_root;
2051       event->motion.y_root = (gfloat)xevent->xmotion.y_root;
2052       event->motion.pressure = 0.5;
2053       event->motion.xtilt = 0;
2054       event->motion.ytilt = 0;
2055       event->motion.state = (GdkModifierType) xevent->xmotion.state;
2056       event->motion.is_hint = xevent->xmotion.is_hint;
2057       event->motion.source = GDK_SOURCE_MOUSE;
2058       event->motion.deviceid = GDK_CORE_POINTER;
2059
2060 #define IS_IN_ZONE(cx, cy) (cx >= gdk_dnd.dnd_drag_dropzone.x \
2061      && cy >= gdk_dnd.dnd_drag_dropzone.y \
2062      && cx < (gdk_dnd.dnd_drag_dropzone.x + gdk_dnd.dnd_drag_dropzone.width) \
2063      && cy < (gdk_dnd.dnd_drag_dropzone.y + gdk_dnd.dnd_drag_dropzone.height))
2064
2065       if(gdk_dnd.drag_perhaps && gdk_dnd.drag_really
2066          /* && event->motion.is_hint */ /* HINTME */)
2067         {
2068           /* First, we have to find what window the motion was in... */
2069           /* XXX there has to be a better way to do this, perhaps with
2070              XTranslateCoordinates or XQueryTree - I don't know how,
2071              and this sort of works */
2072           static Window lastwin = None, curwin = None;
2073 #if 0
2074           Window twin;
2075 #endif
2076           Window childwin = gdk_root_window;
2077           int x, y, ox, oy;
2078
2079           /* Interlude - display cursor for the drag ASAP */
2080           gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2081                                       xevent->xmotion.y_root,
2082                                       gdk_dnd.dnd_drag_target?TRUE:FALSE,
2083                                       FALSE);
2084
2085           lastwin = curwin;
2086           curwin = gdk_root_window;
2087           ox = x = xevent->xmotion.x_root;
2088           oy = y = xevent->xmotion.y_root;
2089 #if 1
2090           curwin = gdk_window_xid_at_coords(xevent->xmotion.x_root,
2091                                             xevent->xmotion.y_root,
2092                                             gdk_dnd.c->xids);
2093           XTranslateCoordinates(gdk_display, gdk_root_window, curwin,
2094                                 x, y, &x, &y, &childwin);
2095 #else
2096           while(childwin != None)
2097             {
2098               ox = x; oy = y;
2099               curwin = childwin;
2100               XTranslateCoordinates(gdk_display, curwin, curwin,
2101                                     x, y, &x, &y, &childwin);
2102               if(childwin != None) 
2103                 {
2104                   XTranslateCoordinates(gdk_display, curwin, childwin,
2105                                         x, y, &x, &y, &twin);
2106                 }
2107             }
2108 #endif
2109           GDK_NOTE (DND,
2110             g_print("Drag is now in window %#lx, lastwin was %#lx, ddc = %#lx\n",
2111                     curwin, lastwin, gdk_dnd.dnd_drag_curwin));
2112           if(curwin != gdk_dnd.dnd_drag_curwin && curwin != lastwin)
2113             {
2114               /* We have left one window and entered another
2115                  (do leave & enter bits) */
2116               if(gdk_dnd.dnd_drag_curwin != None)
2117                   gdk_dnd_drag_leave(gdk_dnd.dnd_drag_curwin);
2118               gdk_dnd.dnd_drag_curwin = curwin;
2119               gdk_dnd_drag_enter(gdk_dnd.dnd_drag_curwin);
2120               gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2121               gdk_dnd.dnd_drag_dropzone.width = gdk_dnd.dnd_drag_dropzone.height = 0;
2122               gdk_dnd.dnd_drag_target = None;
2123               GDK_NOTE (DND,
2124                 g_print("curwin = %#lx, lastwin = %#lx, dnd_drag_curwin = %#lx\n",
2125                         curwin, lastwin, gdk_dnd.dnd_drag_curwin));
2126
2127               gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2128                                           xevent->xmotion.y_root,
2129                                           FALSE, TRUE);
2130             }
2131           else if(gdk_dnd.dnd_drag_dropzone.width > 0
2132                   && gdk_dnd.dnd_drag_dropzone.height > 0
2133                   && curwin == gdk_dnd.dnd_drag_curwin)
2134             {
2135               /* Handle all that dropzone stuff - thanks John ;-) */
2136               if (gdk_dnd.dnd_drag_target != None)
2137                 {
2138                   gboolean in_zone = IS_IN_ZONE(xevent->xmotion.x_root,
2139                                                 xevent->xmotion.y_root);
2140                   gboolean old_in_zone = IS_IN_ZONE(gdk_dnd.dnd_drag_oldpos.x, 
2141                                                     gdk_dnd.dnd_drag_oldpos.y);
2142
2143                   if (!in_zone && old_in_zone)
2144                     {
2145                       /* We were in the drop zone and moved out */
2146                       gdk_dnd.dnd_drag_target = None;
2147                       gdk_dnd_drag_leave(curwin);
2148                       gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2149                                                   xevent->xmotion.y_root,
2150                                                   FALSE, TRUE);
2151                     }
2152                   else if (!in_zone && !old_in_zone)
2153                     {
2154                       /* We were outside drop zone but in the window
2155                          - have to send enter events */
2156                       gdk_dnd_drag_enter(curwin);
2157                       gdk_dnd.dnd_drag_curwin = curwin;
2158                       gdk_dnd.dnd_drag_dropzone.x = gdk_dnd.dnd_drag_dropzone.y = 0;
2159                       gdk_dnd.dnd_drag_target = None;
2160                     }
2161                 }
2162             } /* else
2163               dnd_drag_curwin = None; */
2164           return_val = FALSE;
2165         }
2166       else
2167         return_val = window_private && !window_private->destroyed;
2168       break;
2169
2170     case EnterNotify:
2171       /* Print debugging info.
2172        */
2173       GDK_NOTE (EVENTS,
2174         g_print ("enter notify:\t\twindow: %ld  detail: %d subwin: %ld\n",
2175                  xevent->xcrossing.window - base_id,
2176                  xevent->xcrossing.detail,
2177                  xevent->xcrossing.subwindow - base_id));
2178
2179       /* Tell XInput stuff about it if appropriate */
2180       if (window_private &&
2181           (window_private->extension_events != 0) &&
2182           gdk_input_vtable.enter_event)
2183         gdk_input_vtable.enter_event (&xevent->xcrossing, window);
2184
2185       event->crossing.type = GDK_ENTER_NOTIFY;
2186       event->crossing.window = window;
2187
2188       /* If the subwindow field of the XEvent is non-NULL, then
2189        *  lookup the corresponding GdkWindow.
2190        */
2191       if (xevent->xcrossing.subwindow != None)
2192         event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2193       else
2194         event->crossing.subwindow = NULL;
2195
2196       /* Translate the crossing detail into Gdk terms.
2197        */
2198       switch (xevent->xcrossing.detail)
2199         {
2200         case NotifyInferior:
2201           event->crossing.detail = GDK_NOTIFY_INFERIOR;
2202           break;
2203         case NotifyAncestor:
2204           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2205           break;
2206         case NotifyVirtual:
2207           event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2208           break;
2209         case NotifyNonlinear:
2210           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2211           break;
2212         case NotifyNonlinearVirtual:
2213           event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2214           break;
2215         default:
2216           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2217           break;
2218         }
2219
2220 #ifdef G_ENABLE_DEBUG
2221         if ((gdk_debug_flags & GDK_DEBUG_DND) & gdk_dnd.drag_perhaps)
2222           {
2223             g_print("We may[%d] have a drag into %#lx = %#lx\n",
2224                     gdk_dnd.drag_really,
2225                     xevent->xcrossing.window, gdk_dnd.real_sw->xwindow);
2226           }
2227 #endif /* G_ENABLE_DEBUG */
2228
2229         if (gdk_dnd.drag_perhaps && gdk_dnd.drag_really && 
2230             (xevent->xcrossing.window == gdk_dnd.real_sw->xwindow))
2231           {
2232             gdk_dnd.drag_really = 0;
2233
2234             GDK_NOTE (DND, g_print("Ungrabbed\n"));
2235
2236             gdk_dnd.drag_numwindows = 0;
2237             g_free(gdk_dnd.drag_startwindows);
2238             gdk_dnd.drag_startwindows = NULL;
2239             /* We don't want to ungrab the pointer here, or we'll
2240              * start getting spurious enter/leave events */
2241 #if 0
2242             XChangeActivePointerGrab (gdk_display, 0, None, CurrentTime);
2243 #endif
2244           }
2245         
2246         return_val = window_private && !window_private->destroyed;
2247         break;
2248
2249     case LeaveNotify:
2250       /* Print debugging info.
2251        */
2252       GDK_NOTE (EVENTS, 
2253         g_print ("leave notify:\t\twindow: %ld  detail: %d subwin: %ld\n",
2254                  xevent->xcrossing.window - base_id,
2255                  xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id));
2256
2257       event->crossing.type = GDK_LEAVE_NOTIFY;
2258       event->crossing.window = window;
2259
2260       /* If the subwindow field of the XEvent is non-NULL, then
2261        *  lookup the corresponding GdkWindow.
2262        */
2263       if (xevent->xcrossing.subwindow != None)
2264         event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
2265       else
2266         event->crossing.subwindow = NULL;
2267
2268       /* Translate the crossing detail into Gdk terms.
2269        */
2270       switch (xevent->xcrossing.detail)
2271         {
2272         case NotifyInferior:
2273           event->crossing.detail = GDK_NOTIFY_INFERIOR;
2274           break;
2275         case NotifyAncestor:
2276           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
2277           break;
2278         case NotifyVirtual:
2279           event->crossing.detail = GDK_NOTIFY_VIRTUAL;
2280           break;
2281         case NotifyNonlinear:
2282           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
2283           break;
2284         case NotifyNonlinearVirtual:
2285           event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
2286           break;
2287         default:
2288           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2289           break;
2290         }
2291 #ifdef G_ENABLE_DEBUG
2292       if ((gdk_debug_flags & GDK_DEBUG_DND) & gdk_dnd.drag_perhaps)
2293         {
2294           g_print("We may[%d] have a drag out of %#lx = %#lx\n",
2295                   gdk_dnd.drag_really,
2296                   xevent->xcrossing.window, gdk_dnd.real_sw->xwindow);
2297         }
2298 #endif /* G_ENABLE_DEBUG */
2299       if (gdk_dnd.drag_perhaps && !gdk_dnd.drag_really &&
2300           (xevent->xcrossing.window == gdk_dnd.real_sw->xwindow))
2301         {
2302           gboolean xgpret;
2303           gdk_dnd_drag_addwindow((GdkWindow *) gdk_dnd.real_sw);
2304           gdk_dnd_drag_begin((GdkWindow *) gdk_dnd.real_sw);
2305           xgpret = 
2306           XGrabPointer(gdk_display, gdk_dnd.real_sw->xwindow, False,
2307                        ButtonMotionMask | PointerMotionMask |
2308                        /* PointerMotionHintMask | */ /* HINTME */
2309                        ButtonPressMask | ButtonReleaseMask,
2310                        GrabModeAsync, GrabModeAsync, gdk_root_window,
2311                        None, CurrentTime);
2312 #ifdef G_ENABLE_DEBUG
2313           GDK_NOTE(DND, g_print("xgpret = %d\n", xgpret));
2314 #endif
2315           gdk_dnd.dnd_grabbed = TRUE;
2316           gdk_dnd.drag_really = 1;
2317           gdk_dnd_display_drag_cursor(xevent->xmotion.x_root,
2318                                       xevent->xmotion.y_root,
2319                                       FALSE, TRUE);
2320         }
2321
2322       return_val = window_private && !window_private->destroyed;
2323       break;
2324
2325     case FocusIn:
2326     case FocusOut:
2327       /* We only care about focus events that indicate that _this_
2328        * window (not a ancestor or child) got or lost the focus
2329        */
2330       switch (xevent->xfocus.detail)
2331         {
2332         case NotifyAncestor:
2333         case NotifyInferior:
2334         case NotifyNonlinear:
2335           /* Print debugging info.
2336            */
2337           GDK_NOTE (EVENTS,
2338             g_print ("focus %s:\t\twindow: %ld\n",
2339                      (xevent->xany.type == FocusIn) ? "in" : "out",
2340                      xevent->xfocus.window - base_id));
2341           
2342           event->focus_change.type = GDK_FOCUS_CHANGE;
2343           event->focus_change.window = window;
2344           event->focus_change.in = (xevent->xany.type == FocusIn);
2345           
2346           return_val = window_private && !window_private->destroyed;
2347           break;
2348         default:
2349           ;
2350         }
2351       break;
2352
2353     case KeymapNotify:
2354       /* Print debugging info.
2355        */
2356       GDK_NOTE (EVENTS,
2357         g_print ("keymap notify\n"));
2358
2359       /* Not currently handled */
2360       break;
2361
2362     case Expose:
2363       /* Print debugging info.
2364        */
2365       GDK_NOTE (EVENTS,
2366         g_print ("expose:\t\twindow: %ld  %d  x,y: %d %d  w,h: %d %d\n",
2367                  xevent->xexpose.window - base_id, xevent->xexpose.count,
2368                  xevent->xexpose.x, xevent->xexpose.y,
2369                  xevent->xexpose.width, xevent->xexpose.height));
2370
2371       event->expose.type = GDK_EXPOSE;
2372       event->expose.window = window;
2373       event->expose.area.x = xevent->xexpose.x;
2374       event->expose.area.y = xevent->xexpose.y;
2375       event->expose.area.width = xevent->xexpose.width;
2376       event->expose.area.height = xevent->xexpose.height;
2377       event->expose.count = xevent->xexpose.count;
2378
2379       return_val = window_private && !window_private->destroyed;
2380       break;
2381
2382     case GraphicsExpose:
2383       /* Print debugging info.
2384        */
2385       GDK_NOTE (EVENTS,
2386         g_print ("graphics expose:\tdrawable: %ld\n",
2387                  xevent->xgraphicsexpose.drawable - base_id));
2388
2389       event->expose.type = GDK_EXPOSE;
2390       event->expose.window = window;
2391       event->expose.area.x = xevent->xgraphicsexpose.x;
2392       event->expose.area.y = xevent->xgraphicsexpose.y;
2393       event->expose.area.width = xevent->xgraphicsexpose.width;
2394       event->expose.area.height = xevent->xgraphicsexpose.height;
2395       event->expose.count = xevent->xexpose.count;
2396
2397       return_val = window_private && !window_private->destroyed;
2398       break;
2399
2400     case NoExpose:
2401       /* Print debugging info.
2402        */
2403       GDK_NOTE (EVENTS,
2404         g_print ("no expose:\t\tdrawable: %ld\n",
2405                  xevent->xnoexpose.drawable - base_id));
2406
2407       event->no_expose.type = GDK_NO_EXPOSE;
2408       event->no_expose.window = window;
2409
2410       return_val = window_private && !window_private->destroyed;
2411       break;
2412
2413     case VisibilityNotify:
2414       /* Print debugging info.
2415        */
2416 #ifdef G_ENABLE_DEBUG
2417       if (gdk_debug_flags & GDK_DEBUG_EVENTS)
2418         switch (xevent->xvisibility.state)
2419           {
2420           case VisibilityFullyObscured:
2421             g_print ("visibility notify:\twindow: %ld  none\n",
2422                      xevent->xvisibility.window - base_id);
2423             break;
2424           case VisibilityPartiallyObscured:
2425             g_print ("visibility notify:\twindow: %ld  partial\n",
2426                      xevent->xvisibility.window - base_id);
2427             break;
2428           case VisibilityUnobscured:
2429             g_print ("visibility notify:\twindow: %ld  full\n",
2430                      xevent->xvisibility.window - base_id);
2431             break;
2432           }
2433 #endif /* G_ENABLE_DEBUG */
2434
2435       event->visibility.type = GDK_VISIBILITY_NOTIFY;
2436       event->visibility.window = window;
2437
2438       switch (xevent->xvisibility.state)
2439         {
2440         case VisibilityFullyObscured:
2441           event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
2442           break;
2443
2444         case VisibilityPartiallyObscured:
2445           event->visibility.state = GDK_VISIBILITY_PARTIAL;
2446           break;
2447
2448         case VisibilityUnobscured:
2449           event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
2450           break;
2451         }
2452       
2453       return_val = window_private && !window_private->destroyed;
2454       break;
2455
2456     case CreateNotify:
2457       /* Not currently handled */
2458       break;
2459
2460     case DestroyNotify:
2461       /* Print debugging info.
2462        */
2463       GDK_NOTE (EVENTS,
2464         g_print ("destroy notify:\twindow: %ld\n",
2465                  xevent->xdestroywindow.window - base_id));
2466
2467       event->any.type = GDK_DESTROY;
2468       event->any.window = window;
2469
2470       return_val = window_private && !window_private->destroyed;
2471
2472       gdk_window_destroy_notify (window);
2473       break;
2474
2475     case UnmapNotify:
2476       /* Print debugging info.
2477        */
2478       GDK_NOTE (EVENTS,
2479         g_print ("unmap notify:\t\twindow: %ld\n",
2480                  xevent->xmap.window - base_id));
2481
2482       event->any.type = GDK_UNMAP;
2483       event->any.window = window;
2484
2485       if (xgrab_window == window_private)
2486         xgrab_window = NULL;
2487
2488       return_val = window_private && !window_private->destroyed;
2489       break;
2490
2491     case MapNotify:
2492       /* Print debugging info.
2493        */
2494       GDK_NOTE (EVENTS,
2495         g_print ("map notify:\t\twindow: %ld\n",
2496                  xevent->xmap.window - base_id));
2497
2498       event->any.type = GDK_MAP;
2499       event->any.window = window;
2500
2501       return_val = window_private && !window_private->destroyed;
2502       break;
2503
2504     case ReparentNotify:
2505       /* Print debugging info.
2506        */
2507       GDK_NOTE (EVENTS,
2508         g_print ("reparent notify:\twindow: %ld\n",
2509                  xevent->xreparent.window - base_id));
2510
2511       /* Not currently handled */
2512       break;
2513
2514     case ConfigureNotify:
2515       /* Print debugging info.
2516        */
2517       while ((XPending (gdk_display) > 0) &&
2518              XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
2519                                     ConfigureNotify, xevent))
2520         /*XSync (gdk_display, 0)*/;
2521       
2522       GDK_NOTE (EVENTS,
2523         g_print ("configure notify:\twindow: %ld  x,y: %d %d  w,h: %d %d  b-w: %d  above: %ld  ovr: %d\n",
2524                  xevent->xconfigure.window - base_id,
2525                  xevent->xconfigure.x,
2526                  xevent->xconfigure.y,
2527                  xevent->xconfigure.width,
2528                  xevent->xconfigure.height,
2529                  xevent->xconfigure.border_width,
2530                  xevent->xconfigure.above - base_id,
2531                  xevent->xconfigure.override_redirect));
2532       
2533       if (window_private)
2534         {
2535           if ((window_private->extension_events != 0) &&
2536               gdk_input_vtable.configure_event)
2537             gdk_input_vtable.configure_event (&xevent->xconfigure, window);
2538           
2539           if (window_private->window_type != GDK_WINDOW_CHILD)
2540             {
2541               event->configure.type = GDK_CONFIGURE;
2542               event->configure.window = window;
2543               event->configure.width = xevent->xconfigure.width;
2544               event->configure.height = xevent->xconfigure.height;
2545               
2546               if (!xevent->xconfigure.x &&
2547                   !xevent->xconfigure.y)
2548                 {
2549                   gint tx = 0;
2550                   gint ty = 0;
2551                   Window child_window = 0;
2552
2553                   if (!XTranslateCoordinates (window_private->xdisplay,
2554                                               window_private->xwindow,
2555                                               gdk_root_window,
2556                                               0, 0,
2557                                               &tx, &ty,
2558                                               &child_window))
2559                     g_warning ("GdkWindow %ld doesn't share root windows display?",
2560                                window_private->xwindow - base_id);
2561                   event->configure.x = tx;
2562                   event->configure.y = ty;
2563                 }
2564               else
2565                 {
2566                   event->configure.x = xevent->xconfigure.x;
2567                   event->configure.y = xevent->xconfigure.y;
2568                 }
2569               window_private->x = event->configure.x;
2570               window_private->y = event->configure.y;
2571               window_private->width = xevent->xconfigure.width;
2572               window_private->height = xevent->xconfigure.height;
2573               if (window_private->resize_count > 1)
2574                 window_private->resize_count -= 1;
2575               
2576               return_val = !window_private->destroyed;
2577             }
2578         }
2579       break;
2580       
2581     case PropertyNotify:
2582       /* Print debugging info.
2583        */
2584       GDK_NOTE (EVENTS,
2585         g_print ("property notify:\twindow: %ld\n",
2586                  xevent->xproperty.window - base_id));
2587
2588       event->property.type = GDK_PROPERTY_NOTIFY;
2589       event->property.window = window;
2590       event->property.atom = xevent->xproperty.atom;
2591       event->property.time = xevent->xproperty.time;
2592       event->property.state = xevent->xproperty.state;
2593
2594       return_val = window_private && !window_private->destroyed;
2595       break;
2596
2597     case SelectionClear:
2598       GDK_NOTE (EVENTS,
2599         g_print ("selection clear:\twindow: %ld\n",
2600                  xevent->xproperty.window - base_id));
2601
2602       event->selection.type = GDK_SELECTION_CLEAR;
2603       event->selection.window = window;
2604       event->selection.selection = xevent->xselectionclear.selection;
2605       event->selection.time = xevent->xselectionclear.time;
2606
2607       return_val = window_private && !window_private->destroyed;
2608       break;
2609
2610     case SelectionRequest:
2611       GDK_NOTE (EVENTS,
2612         g_print ("selection request:\twindow: %ld\n",
2613                  xevent->xproperty.window - base_id));
2614
2615       event->selection.type = GDK_SELECTION_REQUEST;
2616       event->selection.window = window;
2617       event->selection.selection = xevent->xselectionrequest.selection;
2618       event->selection.target = xevent->xselectionrequest.target;
2619       event->selection.property = xevent->xselectionrequest.property;
2620       event->selection.requestor = xevent->xselectionrequest.requestor;
2621       event->selection.time = xevent->xselectionrequest.time;
2622
2623       return_val = window_private && !window_private->destroyed;
2624       break;
2625
2626     case SelectionNotify:
2627       GDK_NOTE (EVENTS,
2628         g_print ("selection notify:\twindow: %ld\n",
2629                  xevent->xproperty.window - base_id));
2630
2631
2632       event->selection.type = GDK_SELECTION_NOTIFY;
2633       event->selection.window = window;
2634       event->selection.selection = xevent->xselection.selection;
2635       event->selection.target = xevent->xselection.target;
2636       event->selection.property = xevent->xselection.property;
2637       event->selection.time = xevent->xselection.time;
2638
2639       return_val = window_private && !window_private->destroyed;
2640       break;
2641
2642     case ColormapNotify:
2643       /* Print debugging info.
2644        */
2645       GDK_NOTE (EVENTS,
2646         g_print ("colormap notify:\twindow: %ld\n",
2647                  xevent->xcolormap.window - base_id));
2648
2649       /* Not currently handled */
2650       break;
2651
2652     case ClientMessage:
2653       /* Print debugging info.
2654        */
2655       GDK_NOTE (EVENTS,
2656         g_print ("client message:\twindow: %ld\n",
2657                  xevent->xclient.window - base_id));
2658
2659       /* Client messages are the means of the window manager
2660        *  communicating with a program. We'll first check to
2661        *  see if this is really the window manager talking
2662        *  to us.
2663        */
2664       if (xevent->xclient.message_type == gdk_wm_protocols)
2665         {
2666           if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
2667             {
2668               /* The delete window request specifies a window
2669                *  to delete. We don't actually destroy the
2670                *  window because "it is only a request". (The
2671                *  window might contain vital data that the
2672                *  program does not want destroyed). Instead
2673                *  the event is passed along to the program,
2674                *  which should then destroy the window.
2675                */
2676
2677               /* Print debugging info.
2678                */
2679               GDK_NOTE (EVENTS,
2680                 g_print ("delete window:\t\twindow: %ld\n",
2681                          xevent->xclient.window - base_id));
2682
2683               event->any.type = GDK_DELETE;
2684               event->any.window = window;
2685
2686               return_val = window_private && !window_private->destroyed;
2687             }
2688           else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
2689             {
2690             }
2691         }
2692       else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
2693         {
2694           Atom reptype = 0;
2695
2696           event->dropenter.u.allflags = xevent->xclient.data.l[1];
2697
2698           GDK_NOTE (DND, g_print ("GDK_DROP_ENTER [%d][%d]\n",
2699                 window_private->dnd_drop_enabled, event->dropenter.u.flags.sendreply));
2700           return_val = FALSE;
2701
2702           /* Now figure out if we really want this drop...
2703            * If someone is trying funky clipboard stuff, ignore 
2704            */
2705           if (window_private
2706               && window_private->dnd_drop_enabled
2707               && event->dropenter.u.flags.sendreply
2708               && (reptype = gdk_dnd_check_types (window, xevent)))
2709             {
2710               XEvent replyev;
2711
2712               replyev.xclient.type = ClientMessage;
2713               replyev.xclient.window = xevent->xclient.data.l[0];
2714               replyev.xclient.format = 32;
2715               replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
2716               replyev.xclient.data.l[0] = window_private->xwindow;
2717
2718               event->dragrequest.u.allflags = 0;
2719               event->dragrequest.u.flags.protocol_version =
2720                 DND_PROTOCOL_VERSION;
2721               event->dragrequest.u.flags.willaccept = 1;
2722               event->dragrequest.u.flags.delete_data =
2723                 (window_private->dnd_drop_destructive_op) ? 1 : 0;
2724
2725               replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
2726               replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
2727               replyev.xclient.data.l[4] = reptype;
2728
2729               if (!gdk_send_xevent (replyev.xclient.window, False, 
2730                                     NoEventMask, &replyev))
2731                 GDK_NOTE (DND, g_print("Sending XdeRequest to %#lx failed\n",
2732                                        replyev.xclient.window));
2733
2734               event->any.type = GDK_DROP_ENTER;
2735               event->any.window = window;
2736               event->dropenter.requestor = replyev.xclient.window;
2737               event->dropenter.u.allflags = xevent->xclient.data.l[1];
2738
2739               GDK_NOTE (DND, g_print("We sent a GDK_DROP_ENTER on to Gtk\n"));
2740               return_val = TRUE;
2741             }
2742         }
2743       else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
2744         {
2745 #ifdef G_ENABLE_DEBUG     
2746           if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2747             g_print ("GDK_DROP_LEAVE\n");
2748 #endif    
2749
2750           if (window_private && window_private->dnd_drop_enabled)
2751             {
2752               event->dropleave.type = GDK_DROP_LEAVE;
2753               event->dropleave.window = window;
2754               event->dropleave.requestor = xevent->xclient.data.l[0];
2755               event->dropleave.u.allflags = xevent->xclient.data.l[1];
2756               return_val = TRUE;
2757             }
2758           else
2759             return_val = FALSE;
2760         }
2761       else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
2762         {
2763           /* 
2764            * make sure to only handle requests from the window the cursor is
2765            * over 
2766            */
2767 #ifdef G_ENABLE_DEBUG     
2768           if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2769             g_print ("GDK_DRAG_REQUEST\n");
2770 #endif    
2771           event->dragrequest.u.allflags = xevent->xclient.data.l[1];
2772           return_val = FALSE;
2773
2774           if (window && gdk_dnd.drag_really &&
2775               xevent->xclient.data.l[0] == gdk_dnd.dnd_drag_curwin &&
2776               event->dragrequest.u.flags.sendreply == 0)
2777             {
2778               /* Got request - do we need to ask user? */
2779               if (!event->dragrequest.u.flags.willaccept
2780                   && event->dragrequest.u.flags.senddata)
2781                 {
2782                   /* Yes we do :) */
2783                   event->dragrequest.type = GDK_DRAG_REQUEST;
2784                   event->dragrequest.window = window;
2785                   event->dragrequest.requestor = xevent->xclient.data.l[0];
2786                   event->dragrequest.isdrop = 0;
2787                   event->dragrequest.drop_coords.x =
2788                     event->dragrequest.drop_coords.y = 0;
2789                   return_val = TRUE;
2790                 }
2791               else if (event->dragrequest.u.flags.willaccept)
2792                 {
2793                   window_private->dnd_drag_destructive_op =
2794                     event->dragrequest.u.flags.delete_data;
2795                   window_private->dnd_drag_accepted = 1;
2796                   window_private->dnd_drag_data_type =
2797                     xevent->xclient.data.l[4];
2798
2799                   gdk_dnd.dnd_drag_target = gdk_dnd.dnd_drag_curwin;
2800                   gdk_dnd_display_drag_cursor(-1, -1, TRUE, TRUE);
2801                 }
2802               gdk_dnd.dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
2803               gdk_dnd.dnd_drag_dropzone.y =
2804                 (xevent->xclient.data.l[2] >> 16) & 65535;
2805               gdk_dnd.dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
2806               gdk_dnd.dnd_drag_dropzone.height =
2807                 (xevent->xclient.data.l[3] >> 16) & 65535;
2808             }
2809         }
2810       else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
2811           {
2812             gint tmp_int; Atom tmp_atom;
2813             gulong tmp_long;
2814             guchar *tmp_charptr;
2815
2816 #ifdef G_ENABLE_DEBUG     
2817           if (gdk_debug_flags & (GDK_DEBUG_EVENTS | GDK_DEBUG_DND))
2818             g_print("GDK_DROP_DATA_AVAIL\n");
2819 #endif    
2820             event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
2821             event->dropdataavailable.timestamp = xevent->xclient.data.l[4];
2822             event->dropdataavailable.coords.x =
2823                         xevent->xclient.data.l[3] & 0xffff;
2824             event->dropdataavailable.coords.y =
2825                         (xevent->xclient.data.l[3] >> 16) & 0xffff;
2826             if(window
2827                /* No preview of data ATM */
2828                && event->dropdataavailable.u.flags.isdrop)
2829               {
2830                 event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
2831                 event->dropdataavailable.window = window;
2832                 event->dropdataavailable.requestor = xevent->xclient.data.l[0];
2833                 event->dropdataavailable.data_type =
2834                         gdk_atom_name(xevent->xclient.data.l[2]);
2835                 if(XGetWindowProperty (gdk_display,
2836                                     event->dropdataavailable.requestor,
2837                                     xevent->xclient.data.l[2],
2838                                     0, LONG_MAX - 1,
2839                                     False, XA_PRIMARY, &tmp_atom,
2840                                     &tmp_int,
2841                                     &event->dropdataavailable.data_numbytes,
2842                                     &tmp_long,
2843                                     &tmp_charptr)
2844                    != Success)
2845                   {
2846                     g_warning("XGetWindowProperty on %#x may have failed\n",
2847                             event->dropdataavailable.requestor);
2848                             event->dropdataavailable.data = NULL;
2849                   }
2850                 else
2851                   {
2852                     GDK_NOTE (DND, g_print("XGetWindowProperty got us %ld bytes\n",
2853                             event->dropdataavailable.data_numbytes));
2854                     event->dropdataavailable.data =
2855                         g_malloc (event->dropdataavailable.data_numbytes);
2856                     memcpy (event->dropdataavailable.data,
2857                         tmp_charptr, event->dropdataavailable.data_numbytes);
2858                     XFree(tmp_charptr);
2859                     return_val = TRUE;
2860                   }
2861               return_val = TRUE;
2862             }
2863         }
2864       else
2865         {
2866           /* Send unknown ClientMessage's on to Gtk for it to use */
2867           event->client.type = GDK_CLIENT_EVENT;
2868           event->client.window = window;
2869           event->client.message_type = xevent->xclient.message_type;
2870           event->client.data_format = xevent->xclient.format;
2871           memcpy(&event->client.data, &xevent->xclient.data,
2872                  sizeof(event->client.data));
2873           if(window)
2874             return_val = TRUE;
2875           else  
2876             return_val = FALSE;
2877         }
2878       if(window_private)
2879         return_val = return_val && !window_private->destroyed;
2880       break;
2881       
2882     case MappingNotify:
2883       /* Print debugging info.
2884        */
2885       GDK_NOTE (EVENTS,
2886         g_print ("mapping notify\n"));
2887
2888       /* Let XLib know that there is a new keyboard mapping.
2889        */
2890       XRefreshKeyboardMapping (&xevent->xmapping);
2891       break;
2892
2893     default:
2894       /* something else - (e.g., a Xinput event) */
2895
2896       if (window_private &&
2897           (window_private->extension_events != 0) &&
2898           gdk_input_vtable.other_event)
2899         return_val = gdk_input_vtable.other_event(event, xevent, window);
2900       else
2901         return_val = -1;
2902
2903       if (return_val < 0)       /* not an XInput event, convert */
2904         {
2905           event->other.type = GDK_OTHER_EVENT;
2906           event->other.window = window;
2907           event->other.xevent = (GdkXEvent *)&other_xevent[other_xevent_i];
2908           memcpy (&other_xevent[other_xevent_i], xevent, sizeof (XEvent));
2909           other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
2910           return_val = TRUE;
2911         }
2912       else
2913         return_val = return_val && !window_private->destroyed;
2914
2915       break;
2916     }
2917
2918   if (return_val)
2919     {
2920       if (event->any.window)
2921         gdk_window_ref (event->any.window);
2922       if (((event->any.type == GDK_ENTER_NOTIFY) ||
2923            (event->any.type == GDK_LEAVE_NOTIFY)) &&
2924           (event->crossing.subwindow != NULL))
2925         gdk_window_ref (event->crossing.subwindow);
2926     }
2927   else
2928     {
2929       /* Mark this event as having no resources to be freed */
2930       event->any.window = NULL;
2931       event->any.type = GDK_NOTHING;
2932     }
2933
2934   if (window)
2935     gdk_window_unref (window);
2936
2937   return return_val;
2938 }
2939
2940 #if 0
2941 static Bool
2942 gdk_event_get_type (Display  *display,
2943                     XEvent   *xevent,
2944                     XPointer  arg)
2945 {
2946   GdkEvent event;
2947   GdkPredicate *pred;
2948
2949   if (gdk_event_translate (&event, xevent))
2950     {
2951       pred = (GdkPredicate*) arg;
2952       return (* pred->func) (&event, pred->data);
2953     }
2954
2955   return FALSE;
2956 }
2957 #endif
2958
2959 static void
2960 gdk_synthesize_click (GdkEvent *event,
2961                       gint      nclicks)
2962 {
2963   GdkEvent temp_event;
2964
2965   g_return_if_fail (event != NULL);
2966
2967   temp_event = *event;
2968   temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
2969
2970   gdk_event_put (&temp_event);
2971 }
2972
2973 /*
2974  *--------------------------------------------------------------
2975  * gdk_exit_func
2976  *
2977  *   This is the "atexit" function that makes sure the
2978  *   library gets a chance to cleanup.
2979  *
2980  * Arguments:
2981  *
2982  * Results:
2983  *
2984  * Side effects:
2985  *   The library is un-initialized and the program exits.
2986  *
2987  *--------------------------------------------------------------
2988  */
2989
2990 static void
2991 gdk_exit_func ()
2992 {
2993   static gboolean in_gdk_exit_func = FALSE;
2994
2995   /* This is to avoid an infinite loop if a program segfaults in
2996      an atexit() handler (and yes, it does happen, especially if a program
2997      has trounced over memory too badly for even g_print to work) */
2998   if(in_gdk_exit_func == TRUE) return;
2999   in_gdk_exit_func = TRUE;
3000
3001   if (initialized)
3002     {
3003 #ifdef USE_XIM
3004       /* cleanup IC */
3005       gdk_ic_cleanup ();
3006       /* close IM */
3007       gdk_im_close ();
3008 #endif
3009       gdk_image_exit ();
3010       gdk_input_exit ();
3011       gdk_key_repeat_restore ();
3012
3013       XCloseDisplay (gdk_display);
3014       initialized = 0;
3015     }
3016 }
3017
3018 /*
3019  *--------------------------------------------------------------
3020  * gdk_x_error
3021  *
3022  *   The X error handling routine.
3023  *
3024  * Arguments:
3025  *   "display" is the X display the error orignated from.
3026  *   "error" is the XErrorEvent that we are handling.
3027  *
3028  * Results:
3029  *   Either we were expecting some sort of error to occur,
3030  *   in which case we set the "gdk_error_code" flag, or this
3031  *   error was unexpected, in which case we will print an
3032  *   error message and exit. (Since trying to continue will
3033  *   most likely simply lead to more errors).
3034  *
3035  * Side effects:
3036  *
3037  *--------------------------------------------------------------
3038  */
3039
3040 static int
3041 gdk_x_error (Display     *display,
3042              XErrorEvent *error)
3043 {
3044   char buf[64];
3045
3046   if (gdk_error_warnings)
3047     {
3048       XGetErrorText (display, error->error_code, buf, 63);
3049       g_error ("%s", buf);
3050     }
3051
3052   gdk_error_code = -1;
3053   return 0;
3054 }
3055
3056 /*
3057  *--------------------------------------------------------------
3058  * gdk_x_io_error
3059  *
3060  *   The X I/O error handling routine.
3061  *
3062  * Arguments:
3063  *   "display" is the X display the error orignated from.
3064  *
3065  * Results:
3066  *   An X I/O error basically means we lost our connection
3067  *   to the X server. There is not much we can do to
3068  *   continue, so simply print an error message and exit.
3069  *
3070  * Side effects:
3071  *
3072  *--------------------------------------------------------------
3073  */
3074
3075 static int
3076 gdk_x_io_error (Display *display)
3077 {
3078   g_error ("an x io error occurred");
3079   return 0;
3080 }
3081
3082 /*
3083  *--------------------------------------------------------------
3084  * gdk_signal
3085  *
3086  *   The signal handler.
3087  *
3088  * Arguments:
3089  *   "sig_num" is the number of the signal we received.
3090  *
3091  * Results:
3092  *   The signals we catch are all fatal. So we simply build
3093  *   up a nice little error message and print it and exit.
3094  *   If in the process of doing so another signal is received
3095  *   we notice that we are already exiting and simply kill
3096  *   our process.
3097  *
3098  * Side effects:
3099  *
3100  *--------------------------------------------------------------
3101  */
3102
3103 static RETSIGTYPE
3104 gdk_signal (int sig_num)
3105 {
3106   static int caught_fatal_sig = 0;
3107   char *sig;
3108
3109   if (caught_fatal_sig)
3110     kill (getpid (), sig_num);
3111   caught_fatal_sig = 1;
3112
3113   switch (sig_num)
3114     {
3115     case SIGHUP:
3116       sig = "sighup";
3117       break;
3118     case SIGINT:
3119       sig = "sigint";
3120       break;
3121     case SIGQUIT:
3122       sig = "sigquit";
3123       break;
3124     case SIGBUS:
3125       sig = "sigbus";
3126       break;
3127     case SIGSEGV:
3128       sig = "sigsegv";
3129       break;
3130     case SIGPIPE:
3131       sig = "sigpipe";
3132       break;
3133     case SIGTERM:
3134       sig = "sigterm";
3135       break;
3136     default:
3137       sig = "unknown signal";
3138       break;
3139     }
3140
3141   g_print ("\n** ERROR **: %s caught\n", sig);
3142 #ifdef G_ENABLE_DEBUG
3143   abort ();
3144 #else /* !G_ENABLE_DEBUG */
3145   gdk_exit (1);
3146 #endif /* !G_ENABLE_DEBUG */
3147 }
3148
3149 static void
3150 gdk_dnd_drag_begin (GdkWindow *initial_window)
3151 {
3152   GdkEventDragBegin tev;
3153   tev.type = GDK_DRAG_BEGIN;
3154   tev.window = initial_window;
3155   tev.u.allflags = 0;
3156   tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3157
3158   gdk_event_put ((GdkEvent *) &tev);
3159 }
3160
3161 static void
3162 gdk_dnd_drag_enter (Window dest)
3163 {
3164   XEvent sev;
3165   GdkEventDropEnter tev;
3166   int i;
3167   GdkWindowPrivate *wp;
3168   
3169   sev.xclient.type = ClientMessage;
3170   sev.xclient.format = 32;
3171   sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
3172   sev.xclient.window = dest;
3173
3174   tev.u.allflags = 0;
3175   tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3176   tev.u.flags.sendreply = 1;
3177   for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3178     {
3179       wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3180       if (wp->dnd_drag_data_numtypesavail)
3181         {
3182           sev.xclient.data.l[0] = wp->xwindow;
3183           tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
3184           sev.xclient.data.l[1] = tev.u.allflags;
3185           sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
3186           if (wp->dnd_drag_data_numtypesavail > 1)
3187             {
3188               sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
3189               if (wp->dnd_drag_data_numtypesavail > 2)
3190                 {
3191                   sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
3192                 }
3193               else
3194                 sev.xclient.data.l[4] = None;
3195             }
3196           else
3197             sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
3198           if (!gdk_send_xevent (dest, False, NoEventMask, &sev))
3199                 GDK_NOTE (DND, g_print("Sending XdeEnter to %#lx failed\n",
3200                                        dest));
3201         }
3202
3203     }
3204 }
3205
3206
3207 #ifdef USE_XIM
3208
3209 /*
3210  *--------------------------------------------------------------
3211  * gdk_im_begin
3212  *
3213  *   Begin using input method with XIM Protocol(X11R6 standard)
3214  *
3215  * Arguments:
3216  *   "ic" is the "Input Context" which is created by gtk_ic_new.
3217  *   The input area is specified with "window".
3218  *
3219  * Results:
3220  *   The gdk's event handling routine is switched to XIM based routine.
3221  *   XIM based routine uses XFilterEvent to get rid of events used by IM,
3222  *   and uses XmbLookupString instead of XLookupString.
3223  *
3224  * Side effects:
3225  *
3226  *--------------------------------------------------------------
3227  */
3228
3229 void 
3230 gdk_im_begin (GdkIC ic, GdkWindow* window)
3231 {
3232   GdkICPrivate *private;
3233   Window xwin;
3234
3235   g_return_if_fail (ic != NULL);
3236   g_return_if_fail (window);
3237
3238   private = (GdkICPrivate *) ic;
3239
3240   xim_using = TRUE;
3241   xim_ic = private;
3242   xim_window = window;
3243   if (gdk_im_ready())
3244     {
3245       XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
3246       if (xwin != GDK_WINDOW_XWINDOW(window))
3247         XSetICValues (private->xic, XNFocusWindow, 
3248                       GDK_WINDOW_XWINDOW(window), NULL);
3249       if (private != xim_ic)
3250         XSetICFocus (private->xic);
3251     }
3252 }
3253
3254 /*
3255  *--------------------------------------------------------------
3256  * gdk_im_end
3257  *
3258  *   End using input method with XIM Protocol(X11R6 standard)
3259  *
3260  * Arguments:
3261  *
3262  * Results:
3263  *   The gdk's event handling routine is switched to normal routine.
3264  *   User should call this function before ic and window will be destroyed.
3265  *
3266  * Side effects:
3267  *
3268  *--------------------------------------------------------------
3269  */
3270
3271 void 
3272 gdk_im_end (void)
3273 {
3274   xim_using = FALSE;
3275   xim_ic = NULL;
3276   xim_window = NULL;
3277 }
3278
3279 static GdkIM 
3280 gdk_im_get (void)
3281 {
3282   return xim_im;
3283 }
3284
3285 static GdkIMStyle 
3286 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2) 
3287 {
3288   GdkIMStyle s1, s2, u;
3289
3290   if (style1 == 0) return style2;
3291   if (style2 == 0) return style1;
3292   if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
3293         == (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
3294     return style1;
3295
3296   s1 = style1 & GdkIMPreeditMask;
3297   s2 = style2 & GdkIMPreeditMask;
3298   u = s1 | s2;
3299   if (s1 != s2) {
3300     if (u & GdkIMPreeditCallbacks)
3301       return (s1 == GdkIMPreeditCallbacks)? style1:style2;
3302     else if (u & GdkIMPreeditPosition)
3303       return (s1 == GdkIMPreeditPosition)? style1:style2;
3304     else if (u & GdkIMPreeditArea)
3305       return (s1 == GdkIMPreeditArea)? style1:style2;
3306     else if (u & GdkIMPreeditNothing)
3307       return (s1 == GdkIMPreeditNothing)? style1:style2;
3308   } else {
3309     s1 = style1 & GdkIMStatusMask;
3310     s2 = style2 & GdkIMStatusMask;
3311     u = s1 | s2;
3312     if ( u & GdkIMStatusCallbacks)
3313       return (s1 == GdkIMStatusCallbacks)? style1:style2;
3314     else if ( u & GdkIMStatusArea)
3315       return (s1 == GdkIMStatusArea)? style1:style2;
3316     else if ( u & GdkIMStatusNothing)
3317       return (s1 == GdkIMStatusNothing)? style1:style2;
3318     else if ( u & GdkIMStatusNone)
3319       return (s1 == GdkIMStatusNone)? style1:style2;
3320   }
3321   return 0; /* Get rid of stupid warning */
3322 }
3323
3324 GdkIMStyle
3325 gdk_im_decide_style (GdkIMStyle supported_style)
3326 {
3327   gint i;
3328   GdkIMStyle style, tmp;
3329
3330   g_return_val_if_fail (xim_styles != NULL, 0);
3331
3332   style = 0;
3333   for (i=0; i<xim_styles->count_styles; i++)
3334     {
3335       tmp = xim_styles->supported_styles[i];
3336       if (tmp == (tmp & supported_style & xim_best_allowed_style))
3337         style = gdk_im_choose_better_style (style, tmp);
3338     }
3339   return style;
3340 }
3341
3342 GdkIMStyle
3343 gdk_im_set_best_style (GdkIMStyle style)
3344 {
3345   if (style & GdkIMPreeditMask)
3346     {
3347       xim_best_allowed_style &= ~GdkIMPreeditMask;
3348
3349       xim_best_allowed_style |= GdkIMPreeditNone;
3350       if (!(style & GdkIMPreeditNone))
3351         {
3352           xim_best_allowed_style |= GdkIMPreeditNothing;
3353           if (!(style & GdkIMPreeditNothing))
3354             {
3355               xim_best_allowed_style |= GdkIMPreeditArea;
3356               if (!(style & GdkIMPreeditArea))
3357                 {
3358                   xim_best_allowed_style |= GdkIMPreeditPosition;
3359                   if (!(style & GdkIMPreeditPosition))
3360                     xim_best_allowed_style |= GdkIMPreeditCallbacks;
3361                 }
3362             }
3363         }
3364     }
3365   if (style & GdkIMStatusMask)
3366     {
3367       xim_best_allowed_style &= ~GdkIMStatusMask;
3368
3369       xim_best_allowed_style |= GdkIMStatusNone;
3370       if (!(style & GdkIMStatusNone))
3371         {
3372           xim_best_allowed_style |= GdkIMStatusNothing;
3373           if (!(style & GdkIMStatusNothing))
3374             {
3375               xim_best_allowed_style |= GdkIMStatusArea;
3376               if (!(style & GdkIMStatusArea))
3377                 xim_best_allowed_style |= GdkIMStatusCallbacks;
3378             }
3379         }
3380     }
3381   
3382   return xim_best_allowed_style;
3383 }
3384
3385 static gint 
3386 gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
3387 {
3388   xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
3389   if (xim_im == NULL)
3390     {
3391       GDK_NOTE (XIM, g_warning ("Unable to open open IM."));
3392       return FALSE;
3393     }
3394   XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
3395
3396   return TRUE;
3397 }
3398
3399 static void 
3400 gdk_im_close (void)
3401 {
3402   if (xim_im)
3403     {
3404       XCloseIM (xim_im);
3405       xim_im = NULL;
3406     }
3407   if (xim_styles)
3408     {
3409       XFree (xim_styles);
3410       xim_styles = NULL;
3411     }
3412 }
3413
3414 gint 
3415 gdk_im_ready (void)
3416 {
3417   return (xim_im != NULL);
3418 }
3419
3420 GdkIC 
3421 gdk_ic_new (GdkWindow* client_window,
3422             GdkWindow* focus_window,
3423             GdkIMStyle style, ...)
3424 {
3425   va_list list;
3426   GdkICPrivate *private;
3427   XVaNestedList preedit_attr;
3428
3429   g_return_val_if_fail (client_window != NULL, NULL);
3430   g_return_val_if_fail (focus_window != NULL, NULL);
3431   g_return_val_if_fail (gdk_im_ready(), NULL);
3432
3433   private = g_new (GdkICPrivate, 1);
3434
3435   va_start (list, style);
3436   preedit_attr =  (XVaNestedList) & (va_arg (list, void *));
3437   va_end (list);
3438
3439   private->style = gdk_im_decide_style (style);
3440   if (private->style != style)
3441     {
3442       g_warning ("can not create input context with specified input style.");
3443       g_free (private);
3444       return NULL;
3445     }
3446
3447   private->xic = XCreateIC(gdk_im_get (),
3448                         XNInputStyle,   style,
3449                         XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
3450                         XNFocusWindow,  GDK_WINDOW_XWINDOW (focus_window),
3451                         preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
3452                         NULL);
3453   if (!private->xic)
3454     {
3455       g_free (private);
3456       return NULL;
3457     }
3458
3459   xim_ic_list = g_list_append (xim_ic_list, private);
3460   return private;
3461 }
3462
3463 void 
3464 gdk_ic_destroy (GdkIC ic)
3465 {
3466   GdkICPrivate *private;
3467
3468   g_return_if_fail (ic != NULL);
3469   
3470   private = (GdkICPrivate *) ic;
3471
3472   if (xim_ic == private)
3473     gdk_im_end ();
3474
3475   XDestroyIC (private->xic);
3476   xim_ic_list = g_list_remove (xim_ic_list, private);
3477   g_free (private);
3478 }
3479
3480 GdkIMStyle
3481 gdk_ic_get_style (GdkIC ic)
3482 {
3483   GdkICPrivate *private;
3484
3485   g_return_val_if_fail (ic != NULL, 0);
3486
3487   private = (GdkICPrivate *) ic;
3488
3489   return private->style;
3490 }
3491
3492 void 
3493 gdk_ic_set_values (GdkIC ic, ...)
3494 {
3495   va_list list;
3496   XVaNestedList args;
3497   GdkICPrivate *private;
3498
3499   g_return_if_fail (ic != NULL);
3500
3501   private = (GdkICPrivate *) ic;
3502
3503   va_start (list, ic);
3504   args =  (XVaNestedList) & (va_arg (list, void *));
3505   va_end (list);
3506
3507   XSetICValues (private->xic, XNVaNestedList, args, NULL);
3508 }
3509
3510 void 
3511 gdk_ic_get_values (GdkIC ic, ...)
3512 {
3513   va_list list;
3514   XVaNestedList args;
3515   GdkICPrivate *private;
3516
3517   g_return_if_fail (ic != NULL);
3518
3519   private = (GdkICPrivate *) ic;
3520
3521   va_start (list, ic);
3522   args =  (XVaNestedList) & (va_arg (list, void *));
3523   va_end (list);
3524
3525   XGetICValues (private->xic, XNVaNestedList, args, NULL);
3526 }
3527
3528 void 
3529 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3530 {
3531   va_list list;
3532   XVaNestedList attr;
3533   GdkICPrivate *private;
3534
3535   g_return_if_fail (ic != NULL);
3536   g_return_if_fail (target != NULL);
3537
3538   private = (GdkICPrivate *) ic;
3539
3540   va_start (list, target);
3541   attr =  (XVaNestedList) & (va_arg (list, void *));
3542   va_end (list);
3543
3544   XSetICValues (private->xic, target, attr, NULL);
3545 }
3546
3547 void 
3548 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3549 {
3550   va_list list;
3551   XVaNestedList attr;
3552   GdkICPrivate *private;
3553
3554   g_return_if_fail (ic != NULL);
3555   g_return_if_fail (target != NULL);
3556
3557   private = (GdkICPrivate *) ic;
3558
3559   va_start (list, target);
3560   attr =  (XVaNestedList) & (va_arg (list, void *));
3561   va_end (list);
3562
3563   XGetICValues (private->xic, target, attr, NULL);
3564 }
3565
3566 GdkEventMask 
3567 gdk_ic_get_events (GdkIC ic)
3568 {
3569   GdkEventMask mask;
3570   glong xmask;
3571   glong bit;
3572   GdkICPrivate *private;
3573   gint i;
3574
3575   /*  From gdkwindow.c  */
3576   extern int nevent_masks;
3577   extern int event_mask_table[];
3578
3579   g_return_val_if_fail (ic != NULL, 0);
3580
3581   private = (GdkICPrivate *) ic;
3582
3583   if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL)
3584     {
3585       GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents));
3586       return 0;
3587     }
3588
3589   mask = 0;
3590   for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
3591     if (xmask & event_mask_table [i])
3592       {
3593         mask |= bit;
3594         xmask &= ~ event_mask_table [i];
3595       }
3596
3597   if (xmask)
3598     g_warning ("ic requires events not supported by the application (%#04lx)", xmask);
3599   
3600   return mask;
3601 }
3602
3603 static void 
3604 gdk_ic_cleanup (void)
3605 {
3606   GList* node;
3607   gint destroyed;
3608   GdkICPrivate *private;
3609
3610   destroyed = 0;
3611   for (node = xim_ic_list; node != NULL; node = node->next)
3612     {
3613       if (node->data)
3614        {
3615          private = (GdkICPrivate *) (node->data);
3616          XDestroyIC (private->xic);
3617          g_free (private);
3618          destroyed++;
3619        }
3620     }
3621 #ifdef G_ENABLE_DEBUG
3622   if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0)
3623     {
3624       g_warning ("Cleaned up %i IC(s)\n", destroyed);
3625     }
3626 #endif /* G_ENABLE_DEBUG */
3627   g_list_free(xim_ic_list);
3628   xim_ic_list = NULL;
3629 }
3630
3631 #else /* !USE_XIM */
3632
3633 void 
3634 gdk_im_begin (GdkIC ic, GdkWindow* window)
3635 {
3636 }
3637
3638 void 
3639 gdk_im_end (void)
3640 {
3641 }
3642
3643 GdkIMStyle
3644 gdk_im_decide_style (GdkIMStyle supported_style)
3645 {
3646   return GdkIMPreeditNone | GdkIMStatusNone;
3647 }
3648
3649 GdkIMStyle
3650 gdk_im_set_best_style (GdkIMStyle style)
3651 {
3652   return GdkIMPreeditNone | GdkIMStatusNone;
3653 }
3654
3655 gint 
3656 gdk_im_ready (void)
3657 {
3658   return FALSE;
3659 }
3660
3661 GdkIC 
3662 gdk_ic_new (GdkWindow* client_window,
3663             GdkWindow* focus_window,
3664             GdkIMStyle style, ...)
3665 {
3666   return NULL;
3667 }
3668
3669 void 
3670 gdk_ic_destroy (GdkIC ic)
3671 {
3672 }
3673
3674 GdkIMStyle
3675 gdk_ic_get_style (GdkIC ic)
3676 {
3677   return GdkIMPreeditNone | GdkIMStatusNone;
3678 }
3679
3680 void 
3681 gdk_ic_set_values (GdkIC ic, ...)
3682 {
3683 }
3684
3685 void 
3686 gdk_ic_get_values (GdkIC ic, ...)
3687 {
3688 }
3689
3690 void 
3691 gdk_ic_set_attr (GdkIC ic, const char *target, ...)
3692 {
3693 }
3694
3695 void 
3696 gdk_ic_get_attr (GdkIC ic, const char *target, ...)
3697 {
3698 }
3699
3700 GdkEventMask 
3701 gdk_ic_get_events (GdkIC ic)
3702 {
3703   return 0;
3704 }
3705
3706 #endif /* USE_XIM */
3707
3708 #ifdef X_LOCALE
3709
3710 gint
3711 _g_mbtowc (wchar_t *wstr, const char *str, size_t len)
3712 {
3713   static wchar_t wcs[MB_CUR_MAX + 1];
3714   static gchar mbs[MB_CUR_MAX + 1];
3715
3716   wcs[0] = (wchar_t) NULL;
3717   mbs[0] = '\0';
3718
3719   len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
3720   if (len < 1)
3721     return len;
3722   else if (wcs[0] == (wchar_t) NULL)
3723     return -1;
3724
3725   len = _Xwctomb (mbs, wcs[0]);
3726   if (mbs[0] == '\0')
3727     return -1;
3728   if (wstr)
3729     *wstr = wcs[0];
3730
3731   return len;
3732 }
3733
3734 #endif /* X_LOCALE */
3735
3736 static void
3737 gdk_dnd_drag_leave (Window dest)
3738 {
3739   XEvent sev;
3740   GdkEventDropLeave tev;
3741   int i;
3742   GdkWindowPrivate *wp;
3743
3744   tev.u.allflags = 0;
3745
3746   tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3747   sev.xclient.type = ClientMessage;
3748   sev.xclient.window = dest;
3749   sev.xclient.format = 32;
3750   sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
3751   sev.xclient.data.l[1] = tev.u.allflags;
3752   for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3753     {
3754       wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3755       sev.xclient.data.l[0] = wp->xwindow;
3756       if (!gdk_send_xevent (dest, False, NoEventMask, &sev))
3757         GDK_NOTE (DND, g_print("Sending XdeLeave to %#lx failed\n",
3758                                dest));
3759       wp->dnd_drag_accepted = 0;
3760     }
3761 }
3762
3763 /* 
3764  * when a drop occurs, we go through the list of windows being dragged and
3765  * tell them that it has occurred, so that they can set things up and reply
3766  * to 'dest' window 
3767  */
3768 static void
3769 gdk_dnd_drag_end (Window     dest, 
3770                   GdkPoint   coords)
3771 {
3772   GdkWindowPrivate *wp;
3773   GdkEventDragRequest tev;
3774   int i;
3775
3776   tev.type = GDK_DRAG_REQUEST;
3777   tev.drop_coords = coords;
3778   tev.requestor = dest;
3779   tev.u.allflags = 0;
3780   tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
3781   tev.isdrop = 1;
3782
3783   for (i = 0; i < gdk_dnd.drag_numwindows; i++)
3784     {
3785       wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
3786       if (wp->dnd_drag_accepted)
3787         {
3788           tev.window = (GdkWindow *) wp;
3789           tev.u.flags.delete_data = wp->dnd_drag_destructive_op;
3790           tev.timestamp = gdk_dnd.last_drop_time;
3791           tev.data_type = 
3792                 gdk_atom_name(wp->dnd_drag_data_type);
3793
3794           gdk_event_put((GdkEvent *) &tev);
3795         }
3796     }
3797 }
3798
3799 static GdkAtom
3800 gdk_dnd_check_types (GdkWindow   *window, 
3801                      XEvent      *xevent)
3802 {
3803   GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
3804   int i, j;
3805   GdkEventDropEnter event;
3806
3807   g_return_val_if_fail(window != NULL, 0);
3808   g_return_val_if_fail(xevent != NULL, 0);
3809   g_return_val_if_fail(xevent->type == ClientMessage, 0);
3810   g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
3811
3812   if(wp->dnd_drop_data_numtypesavail <= 0 ||
3813      !wp->dnd_drop_data_typesavail)
3814     return 0;
3815
3816   for (i = 2; i <= 4; i++)
3817     {
3818       for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3819         {
3820           if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
3821             return xevent->xclient.data.l[i];
3822         }
3823     }
3824
3825   /* Now we get the extended type list if it's available */
3826   event.u.allflags = xevent->xclient.data.l[1];
3827   if (event.u.flags.extended_typelist)
3828     {
3829       Atom *exttypes, realtype;
3830       gulong nitems, nbar;
3831       gint realfmt;
3832
3833       if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
3834                              gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
3835                              False, AnyPropertyType, &realtype, &realfmt,
3836                              &nitems, &nbar, (unsigned char **) &exttypes)
3837          != Success)
3838         return 0;
3839
3840       if (realfmt != (sizeof(Atom) * 8))
3841         {
3842           g_warning("XdeTypelist property had format of %d instead of the expected %d, on window %#lx\n",
3843                     realfmt, sizeof(Atom) * 8, xevent->xclient.data.l[0]);
3844           return 0;
3845         }
3846
3847       for (i = 0; i <= nitems; i++)
3848         {
3849           for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
3850             {
3851               if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
3852                 {
3853                   XFree (exttypes);
3854                   return exttypes[i];
3855                 }
3856             }
3857         }
3858       XFree (exttypes);
3859     }
3860   return 0;
3861 }
3862
3863 /* 
3864  * used for debugging only 
3865  */
3866 #ifdef DEBUG_DND
3867 static void
3868 gdk_print_atom (GdkAtom anatom)
3869 {
3870   gchar *tmpstr = NULL;
3871   tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
3872   g_print("Atom %lu has name %s\n", anatom, tmpstr);
3873   if(tmpstr)
3874     g_free(tmpstr);
3875 }
3876 #endif
3877
3878 /* 
3879  * used only by below routine and itself 
3880  */
3881 static Window 
3882 getchildren (Display     *dpy, 
3883              Window       win, 
3884              Atom         WM_STATE)
3885 {
3886   Window root, parent, *children, inf = 0;
3887   Atom type = None;
3888   unsigned int nchildren, i;
3889   int format;
3890   unsigned long nitems, after;
3891   unsigned char *data;
3892
3893   if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
3894     return 0;
3895
3896   for (i = 0; !inf && (i < nchildren); i++)
3897     {
3898       XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
3899                           AnyPropertyType, &type, &format, &nitems,
3900                           &after, &data);
3901       if (type != 0)
3902         inf = children[i];
3903       XFree(data);
3904     }
3905
3906   for (i = 0; !inf && (i < nchildren); i++)
3907     inf = getchildren (dpy, children[i], WM_STATE);
3908
3909   if (children != None)
3910     XFree ((char *) children);
3911
3912   return inf;
3913 }
3914
3915 /* 
3916  * find a window with WM_STATE, else return win itself, as per ICCCM
3917  *
3918  * modification of the XmuClientWindow() routine from X11R6.3
3919  */
3920 Window
3921 gdk_get_client_window (Display  *dpy, 
3922                        Window    win)
3923 {
3924   Atom WM_STATE;
3925   Atom type = None;
3926   int format;
3927   unsigned long nitems, after;
3928   unsigned char *data;
3929   Window inf;
3930
3931   if (win == 0)
3932     return DefaultRootWindow(dpy);
3933
3934   if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
3935     return win;
3936
3937   XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
3938                       &type, &format, &nitems, &after, &data);
3939   if (type)
3940     return win;
3941
3942   inf = getchildren (dpy, win, WM_STATE);
3943
3944   if (inf == 0)
3945     return win;
3946   else
3947     return inf;
3948 }
3949
3950 #ifdef WE_HAVE_MOTIF_DROPS_DONE
3951 static GdkWindow *
3952 gdk_drop_get_real_window (GdkWindow   *w, 
3953                           guint16     *x, 
3954                           guint16     *y)
3955 {
3956   GdkWindow *retval = w;
3957   GdkWindowPrivate *awin;
3958   GList *children;
3959   gint16 myx = *x, myy = *y;
3960
3961   g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
3962
3963   myx = *x; 
3964   myy = *y;
3965
3966 descend:
3967   for (children = gdk_window_get_children(retval); 
3968        children && children->next;
3969        children = children->next)
3970     {
3971       awin = (GdkWindowPrivate *) children->data;
3972       if ((myx >= awin->x) && (myy >= awin->y)
3973           && (myx < (awin->x + awin->width))
3974           && (myy < (awin->y + awin->height)))
3975         {
3976           retval = (GdkWindow *) awin;
3977           myx -= awin->x;
3978           myy -= awin->y;
3979           goto descend;
3980         }
3981     }
3982
3983   *x = myx; 
3984   *y = myy;
3985
3986   return retval;
3987 }
3988 #endif
3989
3990 /* Sends a ClientMessage to all toplevel client windows */
3991 void
3992 gdk_event_send_clientmessage_toall(GdkEvent *event)
3993 {
3994   XEvent sev;
3995   Window *ret_children, ret_root, ret_parent, curwin;
3996   unsigned int ret_nchildren;
3997   int i;
3998
3999   g_return_if_fail(event != NULL);
4000
4001   /* Set up our event to send, with the exception of its target window */
4002   sev.xclient.type = ClientMessage;
4003   sev.xclient.display = gdk_display;
4004   sev.xclient.format = event->client.data_format;
4005   sev.xclient.serial = CurrentTime;
4006   memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
4007   sev.xclient.message_type = event->client.message_type;
4008
4009   /* OK, we're all set, now let's find some windows to send this to */
4010   if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
4011                 &ret_children, &ret_nchildren) != True)
4012     return;
4013
4014   /* foreach true child window of the root window, send an event to it */
4015   for(i = 0; i < ret_nchildren; i++) {
4016     curwin = gdk_get_client_window(gdk_display, ret_children[i]);
4017     sev.xclient.window = curwin;
4018     if (!gdk_send_xevent (curwin, False, NoEventMask, &sev))
4019       GDK_NOTE (MISC, g_print("Sending client message %ld to %#lx failed\n",
4020                              event->client.message_type, curwin));
4021   }
4022
4023   XFree(ret_children);
4024 }
4025
4026 gchar *
4027 gdk_get_display(void)
4028 {
4029   return (gchar *)XDisplayName (gdk_display_name);
4030 }
4031
4032 gint 
4033 gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
4034                  XEvent *event_send)
4035 {
4036   Status result;
4037   
4038   gdk_error_code = 0;
4039   
4040   gdk_error_warnings = 0;
4041   result = XSendEvent (gdk_display, window, propagate, event_mask, event_send);
4042   XSync (gdk_display, False);
4043   gdk_error_warnings = 1;
4044     
4045   return result && (gdk_error_code != -1);
4046 }