]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkevents.c
fa839fe898b18c70d2b7fa5b62ffe0f4ff6e749d
[~andy/gtk] / gdk / win32 / gdkevents.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * Copyright (C) 1998-1999 Tor Lillqvist
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "config.h"
29
30 #include <stdio.h>
31 #include <gdk/gdk.h>
32 #include <gdk/gdkkeysyms.h>
33 #include "gdkx.h"
34 #include "gdkinput.h"
35
36 #define PING() printf("%s: %d\n",__FILE__,__LINE__),fflush(stdout)
37
38 typedef struct _GdkIOClosure GdkIOClosure;
39 typedef struct _GdkEventPrivate GdkEventPrivate;
40
41 #define DOUBLE_CLICK_TIME      250
42 #define TRIPLE_CLICK_TIME      500
43 #define DOUBLE_CLICK_DIST      5
44 #define TRIPLE_CLICK_DIST      5
45
46 typedef enum
47 {
48   /* Following flag is set for events on the event queue during
49    * translation and cleared afterwards.
50    */
51   GDK_EVENT_PENDING = 1 << 0
52 } GdkEventFlags;
53
54 struct _GdkIOClosure
55 {
56   GdkInputFunction function;
57   GdkInputCondition condition;
58   GdkDestroyNotify notify;
59   gpointer data;
60 };
61
62 struct _GdkEventPrivate
63 {
64   GdkEvent event;
65   guint    flags;
66 };
67
68 /* 
69  * Private function declarations
70  */
71
72 static GdkEvent *gdk_event_new          (void);
73 static gint      gdk_event_apply_filters(MSG      *xevent,
74                                          GdkEvent *event,
75                                          GList    *filters);
76 static gint      gdk_event_translate    (GdkEvent *event, 
77                                          MSG      *xevent,
78                                          gboolean *ret_val_flagp,
79                                          gint     *ret_valp);
80 static void      gdk_events_queue       (void);
81 static GdkEvent *gdk_event_unqueue      (void);
82 static gboolean  gdk_event_prepare      (gpointer  source_data, 
83                                          GTimeVal *current_time,
84                                          gint     *timeout);
85 static gboolean  gdk_event_check        (gpointer  source_data,
86                                          GTimeVal *current_time);
87 static gboolean  gdk_event_dispatch     (gpointer  source_data,
88                                          GTimeVal *current_time,
89                                          gpointer  user_data);
90
91 static void      gdk_synthesize_click   (GdkEvent     *event, 
92                                          gint          nclicks);
93
94 /* Private variable declarations
95  */
96
97 static guint32 button_click_time[2];        /* The last 2 button click times. Used
98                                              *  to determine if the latest button click
99                                              *  is part of a double or triple click.
100                                              */
101 static GdkWindow *button_window[2];         /* The last 2 windows to receive button presses.
102                                              *  Also used to determine if the latest button
103                                              *  click is part of a double or triple click.
104                                              */
105 static guint button_number[2];              /* The last 2 buttons to be pressed.
106                                              */
107 static GdkWindowPrivate *p_grab_window = NULL; /* Window that currently
108                                                 * holds the pointer grab
109                                                 */
110
111 static GdkWindowPrivate *k_grab_window = NULL; /* Window the holds the
112                                                 * keyboard grab
113                                                 */
114
115 static GList *client_filters;   /* Filters for client messages */
116
117 static gboolean p_grab_automatic;
118 static GdkEventMask p_grab_event_mask;
119 static gboolean p_grab_owner_events, k_grab_owner_events;
120 static HCURSOR p_grab_cursor;
121
122 static GdkEventFunc   event_func = NULL;    /* Callback for events */
123 static gpointer       event_data = NULL;
124 static GDestroyNotify event_notify = NULL;
125
126 static GList *client_filters;               /* Filters for client messages */
127
128 /* FIFO's for event queue, and for events put back using
129  * gdk_event_put().
130  */
131 static GList *queued_events = NULL;
132 static GList *queued_tail = NULL;
133
134 static GSourceFuncs event_funcs = {
135   gdk_event_prepare,
136   gdk_event_check,
137   gdk_event_dispatch,
138   (GDestroyNotify)g_free
139 };
140
141 GPollFD event_poll_fd;
142
143 static GdkWindow *curWnd = NULL;
144 static HWND active = NULL;
145 static gint curX, curY;
146 static gdouble curXroot, curYroot;
147 static UINT gdk_ping_msg;
148 static gboolean ignore_WM_CHAR = FALSE;
149 static gboolean is_AltGr_key = FALSE;
150
151 LRESULT CALLBACK 
152 gdk_WindowProc(HWND hwnd,
153                UINT message,
154                WPARAM wParam,
155                LPARAM lParam)
156 {
157   GdkEvent event;
158   GdkEvent *eventp;
159   MSG msg;
160   DWORD pos;
161   gint ret_val;
162   gboolean ret_val_flag;
163
164   GDK_NOTE (EVENTS, g_print ("gdk_WindowProc: %#x\n", message));
165
166   msg.hwnd = hwnd;
167   msg.message = message;
168   msg.wParam = wParam;
169   msg.lParam = lParam;
170   msg.time = GetTickCount ();
171   pos = GetMessagePos ();
172   msg.pt.x = LOWORD (pos);
173   msg.pt.y = HIWORD (pos);
174
175   if (gdk_event_translate (&event, &msg, &ret_val_flag, &ret_val))
176     {
177 #if 1
178       /* Compress configure events */
179       if (event.any.type == GDK_CONFIGURE)
180         {
181           GList *list = queued_events;
182
183           while (list != NULL
184                  && (((GdkEvent *)list->data)->any.type != GDK_CONFIGURE
185                      || ((GdkEvent *)list->data)->any.window != event.any.window))
186             list = list->next;
187           if (list != NULL)
188             {
189               *((GdkEvent *)list->data) = event;
190               gdk_window_unref (event.any.window);
191               /* Wake up WaitMessage */
192               PostMessage (NULL, gdk_ping_msg, 0, 0);
193               return FALSE;
194             }
195         }
196 #endif
197       eventp = gdk_event_new ();
198       *eventp = event;
199
200       gdk_event_queue_append (eventp);
201 #if 1
202       /* Wake up WaitMessage */
203       PostMessage (NULL, gdk_ping_msg, 0, 0);
204 #endif
205       if (ret_val_flag)
206         return ret_val;
207       else
208         return FALSE;
209     }
210
211   if (ret_val_flag)
212     return ret_val;
213   else
214     return DefWindowProc (hwnd, message, wParam, lParam);
215 }
216
217 /*********************************************
218  * Functions for maintaining the event queue *
219  *********************************************/
220
221 /*************************************************************
222  * gdk_event_queue_find_first:
223  *     Find the first event on the queue that is not still
224  *     being filled in.
225  *   arguments:
226  *     
227  *   results:
228  *     Pointer to the list node for that event, or NULL
229  *************************************************************/
230
231 static GList*
232 gdk_event_queue_find_first (void)
233 {
234   GList *tmp_list = queued_events;
235
236   while (tmp_list)
237     {
238       GdkEventPrivate *event = tmp_list->data;
239       if (!(event->flags & GDK_EVENT_PENDING))
240         return tmp_list;
241
242       tmp_list = g_list_next (tmp_list);
243     }
244
245   return NULL;
246 }
247
248 /*************************************************************
249  * gdk_event_queue_remove_link:
250  *     Remove a specified list node from the event queue.
251  *   arguments:
252  *     node: Node to remove.
253  *   results:
254  *************************************************************/
255
256 static void
257 gdk_event_queue_remove_link (GList *node)
258 {
259   if (node->prev)
260     node->prev->next = node->next;
261   else
262     queued_events = node->next;
263   
264   if (node->next)
265     node->next->prev = node->prev;
266   else
267     queued_tail = node->prev;
268   
269 }
270
271 /*************************************************************
272  * gdk_event_queue_append:
273  *     Append an event onto the tail of the event queue.
274  *   arguments:
275  *     event: Event to append.
276  *   results:
277  *************************************************************/
278
279 void
280 gdk_event_queue_append (GdkEvent *event)
281 {
282   queued_tail = g_list_append (queued_tail, event);
283   
284   if (!queued_events)
285     queued_events = queued_tail;
286   else
287     queued_tail = queued_tail->next;
288 }
289
290 void 
291 gdk_events_init (void)
292 {
293   if (g_pipe_readable_msg == 0)
294     g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
295
296   g_source_add (GDK_PRIORITY_EVENTS, TRUE, &event_funcs, NULL, NULL, NULL);
297
298   event_poll_fd.fd = G_WIN32_MSG_HANDLE;
299   event_poll_fd.events = G_IO_IN;
300   
301   g_main_add_poll (&event_poll_fd, GDK_PRIORITY_EVENTS);
302
303   button_click_time[0] = 0;
304   button_click_time[1] = 0;
305   button_window[0] = NULL;
306   button_window[1] = NULL;
307   button_number[0] = -1;
308   button_number[1] = -1;
309
310   gdk_ping_msg = RegisterWindowMessage ("gdk-ping");
311 }
312
313 /*
314  *--------------------------------------------------------------
315  * gdk_events_pending
316  *
317  *   Returns if events are pending on the queue.
318  *
319  * Arguments:
320  *
321  * Results:
322  *   Returns TRUE if events are pending
323  *
324  * Side effects:
325  *
326  *--------------------------------------------------------------
327  */
328
329 gboolean
330 gdk_events_pending (void)
331 {
332   MSG msg;
333
334   return (gdk_event_queue_find_first() || PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE));
335 }
336
337 /*
338  *--------------------------------------------------------------
339  * gdk_event_get_graphics_expose
340  *
341  *   Waits for a GraphicsExpose or NoExpose event
342  *
343  * Arguments:
344  *
345  * Results: 
346  *   For GraphicsExpose events, returns a pointer to the event
347  *   converted into a GdkEvent Otherwise, returns NULL.
348  *
349  * Side effects:
350  *
351  *-------------------------------------------------------------- */
352
353 GdkEvent*
354 gdk_event_get_graphics_expose (GdkWindow *window)
355 {
356   MSG xevent;
357   GdkEvent *event;
358   GdkWindowPrivate *private = (GdkWindowPrivate *) window;
359
360   g_return_val_if_fail (window != NULL, NULL);
361   
362   GDK_NOTE (EVENTS, g_print ("gdk_event_get_graphics_expose\n"));
363
364 #if 1
365   /* Some nasty bugs here, just return NULL for now. */
366   return NULL;
367 #else
368   if (GetMessage (&xevent, private->xwindow, WM_PAINT, WM_PAINT))
369     {
370       event = gdk_event_new ();
371       
372       if (gdk_event_translate (event, &xevent, NULL, NULL))
373         return event;
374       else
375         gdk_event_free (event);
376     }
377   
378   return NULL;  
379 #endif
380 }
381
382 /************************
383  * Exposure compression *
384  ************************/
385
386 /* I don't bother with exposure compression on Win32. Windows compresses
387  * WM_PAINT events by itself.
388  */
389
390 /*************************************************************
391  * gdk_event_handler_set:
392  *     
393  *   arguments:
394  *     func: Callback function to be called for each event.
395  *     data: Data supplied to the function
396  *     notify: function called when function is no longer needed
397  * 
398  *   results:
399  *************************************************************/
400
401 void 
402 gdk_event_handler_set (GdkEventFunc   func,
403                        gpointer       data,
404                        GDestroyNotify notify)
405 {
406   if (event_notify)
407     (*event_notify) (event_data);
408
409   event_func = func;
410   event_data = data;
411   event_notify = notify;
412 }
413
414 /*
415  *--------------------------------------------------------------
416  * gdk_event_get
417  *
418  *   Gets the next event.
419  *
420  * Arguments:
421  *
422  * Results:
423  *   If an event is waiting that we care about, returns 
424  *   a pointer to that event, to be freed with gdk_event_free.
425  *   Otherwise, returns NULL.
426  *
427  * Side effects:
428  *
429  *--------------------------------------------------------------
430  */
431
432 GdkEvent*
433 gdk_event_get (void)
434 {
435   gdk_events_queue();
436
437   return gdk_event_unqueue();
438 }
439
440 /*
441  *--------------------------------------------------------------
442  * gdk_event_peek
443  *
444  *   Gets the next event.
445  *
446  * Arguments:
447  *
448  * Results:
449  *   If an event is waiting that we care about, returns 
450  *   a copy of that event, but does not remove it from
451  *   the queue. The pointer is to be freed with gdk_event_free.
452  *   Otherwise, returns NULL.
453  *
454  * Side effects:
455  *
456  *--------------------------------------------------------------
457  */
458
459 GdkEvent*
460 gdk_event_peek (void)
461 {
462   GList *tmp_list;
463
464   tmp_list = gdk_event_queue_find_first ();
465   
466   if (tmp_list)
467     return gdk_event_copy (tmp_list->data);
468   else
469     return NULL;
470 }
471
472 void
473 gdk_event_put (GdkEvent *event)
474 {
475   GdkEvent *new_event;
476   GList *tmp_list;
477   
478   g_return_if_fail (event != NULL);
479   
480   new_event = gdk_event_copy (event);
481
482   gdk_event_queue_append (new_event);
483 }
484
485 /*
486  *--------------------------------------------------------------
487  * gdk_event_copy
488  *
489  *   Copy a event structure into new storage.
490  *
491  * Arguments:
492  *   "event" is the event struct to copy.
493  *
494  * Results:
495  *   A new event structure.  Free it with gdk_event_free.
496  *
497  * Side effects:
498  *   The reference count of the window in the event is increased.
499  *
500  *--------------------------------------------------------------
501  */
502
503 static GMemChunk *event_chunk = NULL;
504
505 static GdkEvent*
506 gdk_event_new (void)
507 {
508   GdkEventPrivate *new_event;
509   
510   if (event_chunk == NULL)
511     event_chunk = g_mem_chunk_new ("events",
512                                    sizeof (GdkEventPrivate),
513                                    4096,
514                                    G_ALLOC_AND_FREE);
515   
516   new_event = g_chunk_new (GdkEventPrivate, event_chunk);
517   new_event->flags = 0;
518   
519   return (GdkEvent *) new_event;
520 }
521
522 GdkEvent*
523 gdk_event_copy (GdkEvent *event)
524 {
525   GdkEvent *new_event;
526   
527   g_return_val_if_fail (event != NULL, NULL);
528   
529   new_event = gdk_event_new ();
530   
531   *new_event = *event;
532   gdk_window_ref (new_event->any.window);
533   
534   switch (event->any.type)
535     {
536     case GDK_KEY_PRESS:
537     case GDK_KEY_RELEASE:
538       new_event->key.string = g_strdup (event->key.string);
539       break;
540       
541     case GDK_ENTER_NOTIFY:
542     case GDK_LEAVE_NOTIFY:
543       if (event->crossing.subwindow != NULL)
544         gdk_window_ref (event->crossing.subwindow);
545       break;
546       
547     case GDK_DRAG_ENTER:
548     case GDK_DRAG_LEAVE:
549     case GDK_DRAG_MOTION:
550     case GDK_DRAG_STATUS:
551     case GDK_DROP_START:
552     case GDK_DROP_FINISHED:
553       gdk_drag_context_ref (event->dnd.context);
554       break;
555       
556     default:
557       break;
558     }
559   
560   return new_event;
561 }
562
563 /*
564  *--------------------------------------------------------------
565  * gdk_event_free
566  *
567  *   Free a event structure obtained from gdk_event_copy.  Do not use
568  *   with other event structures.
569  *
570  * Arguments:
571  *   "event" is the event struct to free.
572  *
573  * Results:
574  *
575  * Side effects:
576  *   The reference count of the window in the event is decreased and
577  *   might be freed, too.
578  *
579  *-------------------------------------------------------------- */
580
581 void
582 gdk_event_free (GdkEvent *event)
583 {
584   g_return_if_fail (event != NULL);
585
586   g_assert (event_chunk != NULL); /* paranoid */
587   
588   if (event->any.window)
589     gdk_window_unref (event->any.window);
590   
591   switch (event->any.type)
592     {
593     case GDK_KEY_PRESS:
594     case GDK_KEY_RELEASE:
595       g_free (event->key.string);
596       break;
597       
598     case GDK_ENTER_NOTIFY:
599     case GDK_LEAVE_NOTIFY:
600       if (event->crossing.subwindow != NULL)
601         gdk_window_unref (event->crossing.subwindow);
602       break;
603       
604     case GDK_DRAG_ENTER:
605     case GDK_DRAG_LEAVE:
606     case GDK_DRAG_MOTION:
607     case GDK_DRAG_STATUS:
608     case GDK_DROP_START:
609     case GDK_DROP_FINISHED:
610       gdk_drag_context_unref (event->dnd.context);
611       break;
612       
613     default:
614       break;
615     }
616   
617   g_mem_chunk_free (event_chunk, event);
618 }
619
620 /*
621  *--------------------------------------------------------------
622  * gdk_event_get_time:
623  *    Get the timestamp from an event.
624  *   arguments:
625  *     event:
626  *   results:
627  *    The event's time stamp, if it has one, otherwise
628  *    GDK_CURRENT_TIME.
629  *--------------------------------------------------------------
630  */
631
632 guint32
633 gdk_event_get_time (GdkEvent *event)
634 {
635   if (event)
636     switch (event->type)
637       {
638       case GDK_MOTION_NOTIFY:
639         return event->motion.time;
640       case GDK_BUTTON_PRESS:
641       case GDK_2BUTTON_PRESS:
642       case GDK_3BUTTON_PRESS:
643       case GDK_BUTTON_RELEASE:
644         return event->button.time;
645       case GDK_KEY_PRESS:
646       case GDK_KEY_RELEASE:
647         return event->key.time;
648       case GDK_ENTER_NOTIFY:
649       case GDK_LEAVE_NOTIFY:
650         return event->crossing.time;
651       case GDK_PROPERTY_NOTIFY:
652         return event->property.time;
653       case GDK_SELECTION_CLEAR:
654       case GDK_SELECTION_REQUEST:
655       case GDK_SELECTION_NOTIFY:
656         return event->selection.time;
657       case GDK_PROXIMITY_IN:
658       case GDK_PROXIMITY_OUT:
659         return event->proximity.time;
660       case GDK_DRAG_ENTER:
661       case GDK_DRAG_LEAVE:
662       case GDK_DRAG_MOTION:
663       case GDK_DRAG_STATUS:
664       case GDK_DROP_START:
665       case GDK_DROP_FINISHED:
666         return event->dnd.time;
667       default:                  /* use current time */
668         break;
669       }
670   
671   return GDK_CURRENT_TIME;
672 }
673
674 /*
675  *--------------------------------------------------------------
676  * gdk_set_show_events
677  *
678  *   Turns on/off the showing of events.
679  *
680  * Arguments:
681  *   "show_events" is a boolean describing whether or
682  *   not to show the events gdk receives.
683  *
684  * Results:
685  *
686  * Side effects:
687  *   When "show_events" is TRUE, calls to "gdk_event_get"
688  *   will output debugging informatin regarding the event
689  *   received to stdout.
690  *
691  *--------------------------------------------------------------
692  */
693
694 void
695 gdk_set_show_events (gint show_events)
696 {
697   if (show_events)
698     gdk_debug_flags |= GDK_DEBUG_EVENTS;
699   else
700     gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
701 }
702
703 gint
704 gdk_get_show_events (void)
705 {
706   return gdk_debug_flags & GDK_DEBUG_EVENTS;
707 }
708
709 /*
710  *--------------------------------------------------------------
711  * gdk_pointer_grab
712  *
713  *   Grabs the pointer to a specific window
714  *
715  * Arguments:
716  *   "window" is the window which will receive the grab
717  *   "owner_events" specifies whether events will be reported as is,
718  *     or relative to "window"
719  *   "event_mask" masks only interesting events
720  *   "confine_to" limits the cursor movement to the specified window
721  *   "cursor" changes the cursor for the duration of the grab
722  *   "time" specifies the time
723  *
724  * Results:
725  *
726  * Side effects:
727  *   requires a corresponding call to gdk_pointer_ungrab
728  *
729  *--------------------------------------------------------------
730  */
731
732 gint
733 gdk_pointer_grab (GdkWindow *     window,
734                   gint            owner_events,
735                   GdkEventMask    event_mask,
736                   GdkWindow *     confine_to,
737                   GdkCursor *     cursor,
738                   guint32         time)
739 {
740   GdkWindowPrivate *window_private;
741   HWND xwindow;
742   HWND xconfine_to;
743   HCURSOR xcursor;
744   GdkWindowPrivate *confine_to_private;
745   GdkCursorPrivate *cursor_private;
746   gint return_val;
747
748   g_return_val_if_fail (window != NULL, 0);
749   
750   window_private = (GdkWindowPrivate*) window;
751   confine_to_private = (GdkWindowPrivate*) confine_to;
752   cursor_private = (GdkCursorPrivate*) cursor;
753   
754   xwindow = window_private->xwindow;
755   
756   if (!confine_to || confine_to_private->destroyed)
757     xconfine_to = NULL;
758   else
759     xconfine_to = confine_to_private->xwindow;
760   
761   if (!cursor)
762     xcursor = NULL;
763   else
764     xcursor = cursor_private->xcursor;
765   
766   if (gdk_input_vtable.grab_pointer)
767     return_val = gdk_input_vtable.grab_pointer (window,
768                                                 owner_events,
769                                                 event_mask,
770                                                 confine_to,
771                                                 time);
772   else
773     return_val = Success;
774   
775   if (return_val == Success)
776     {
777       if (!window_private->destroyed)
778       {
779         GDK_NOTE (EVENTS, g_print ("gdk_pointer_grab: %#x %s %#x\n",
780                                    xwindow,
781                                    (owner_events ? "TRUE" : "FALSE"),
782                                    xcursor));
783         p_grab_event_mask = event_mask;
784         p_grab_owner_events = owner_events != 0;
785         p_grab_automatic = FALSE;
786
787 #if 0 /* Menus don't work if we use mouse capture. Pity, because many other
788        * things work better with mouse capture.
789        */
790         SetCapture (xwindow);
791 #endif
792         return_val = GrabSuccess;
793       }
794       else
795         return_val = AlreadyGrabbed;
796     }
797   
798   if (return_val == GrabSuccess)
799     {
800       p_grab_window = window_private;
801       p_grab_cursor = xcursor;
802     }
803   
804   return return_val;
805 }
806
807 /*
808  *--------------------------------------------------------------
809  * gdk_pointer_ungrab
810  *
811  *   Releases any pointer grab
812  *
813  * Arguments:
814  *
815  * Results:
816  *
817  * Side effects:
818  *
819  *--------------------------------------------------------------
820  */
821
822 void
823 gdk_pointer_ungrab (guint32 time)
824 {
825   if (gdk_input_vtable.ungrab_pointer)
826     gdk_input_vtable.ungrab_pointer (time);
827 #if 0
828   if (GetCapture () != NULL)
829     ReleaseCapture ();
830 #endif
831   GDK_NOTE (EVENTS, g_print ("gdk_pointer_ungrab\n"));
832
833   p_grab_window = NULL;
834 }
835
836 /*
837  *--------------------------------------------------------------
838  * gdk_pointer_is_grabbed
839  *
840  *   Tell wether there is an active x pointer grab in effect
841  *
842  * Arguments:
843  *
844  * Results:
845  *
846  * Side effects:
847  *
848  *--------------------------------------------------------------
849  */
850
851 gint
852 gdk_pointer_is_grabbed (void)
853 {
854   return p_grab_window != NULL;
855 }
856
857 /*
858  *--------------------------------------------------------------
859  * gdk_keyboard_grab
860  *
861  *   Grabs the keyboard to a specific window
862  *
863  * Arguments:
864  *   "window" is the window which will receive the grab
865  *   "owner_events" specifies whether events will be reported as is,
866  *     or relative to "window"
867  *   "time" specifies the time
868  *
869  * Results:
870  *
871  * Side effects:
872  *   requires a corresponding call to gdk_keyboard_ungrab
873  *
874  *--------------------------------------------------------------
875  */
876
877 gint
878 gdk_keyboard_grab (GdkWindow *     window,
879                    gint            owner_events,
880                    guint32         time)
881 {
882   GdkWindowPrivate *window_private;
883   gint return_val;
884   
885   g_return_val_if_fail (window != NULL, 0);
886   
887   window_private = (GdkWindowPrivate*) window;
888   
889   GDK_NOTE (EVENTS, g_print ("gdk_keyboard_grab %#x\n",
890                              window_private->xwindow));
891
892   if (!window_private->destroyed)
893     {
894       k_grab_owner_events = owner_events != 0;
895       return_val = GrabSuccess;
896     }
897   else
898     return_val = AlreadyGrabbed;
899
900   if (return_val == GrabSuccess)
901     k_grab_window = window_private;
902   
903   return return_val;
904 }
905
906 /*
907  *--------------------------------------------------------------
908  * gdk_keyboard_ungrab
909  *
910  *   Releases any keyboard grab
911  *
912  * Arguments:
913  *
914  * Results:
915  *
916  * Side effects:
917  *
918  *--------------------------------------------------------------
919  */
920
921 void
922 gdk_keyboard_ungrab (guint32 time)
923 {
924   GDK_NOTE (EVENTS, g_print ("gdk_keyboard_ungrab\n"));
925
926   k_grab_window = NULL;
927 }
928
929 static void
930 gdk_io_destroy (gpointer data)
931 {
932   GdkIOClosure *closure = data;
933
934   if (closure->notify)
935     closure->notify (closure->data);
936
937   g_free (closure);
938 }
939
940 static gboolean  
941 gdk_io_invoke (GIOChannel   *source,
942                GIOCondition  condition,
943                gpointer      data)
944 {
945   GdkIOClosure *closure = data;
946   GdkInputCondition gdk_cond = 0;
947
948   if (condition & (G_IO_IN | G_IO_PRI))
949     gdk_cond |= GDK_INPUT_READ;
950   if (condition & G_IO_OUT)
951     gdk_cond |= GDK_INPUT_WRITE;
952   if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
953     gdk_cond |= GDK_INPUT_EXCEPTION;
954
955   if (closure->condition & gdk_cond)
956     closure->function (closure->data, g_io_channel_unix_get_fd (source), gdk_cond);
957
958   return TRUE;
959 }
960
961 gint
962 gdk_input_add_full (gint              source,
963                     GdkInputCondition condition,
964                     GdkInputFunction  function,
965                     gpointer          data,
966                     GdkDestroyNotify  destroy)
967 {
968   guint result;
969   GdkIOClosure *closure = g_new (GdkIOClosure, 1);
970   GIOChannel *channel;
971   GIOCondition cond = 0;
972
973   closure->function = function;
974   closure->condition = condition;
975   closure->notify = destroy;
976   closure->data = data;
977
978   if (condition & GDK_INPUT_READ)
979     cond |= (G_IO_IN | G_IO_PRI);
980   if (condition & GDK_INPUT_WRITE)
981     cond |= G_IO_OUT;
982   if (condition & GDK_INPUT_EXCEPTION)
983     cond |= G_IO_ERR|G_IO_HUP|G_IO_NVAL;
984
985   channel = g_io_channel_unix_new (source);
986   result = g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, cond,
987                                 gdk_io_invoke,
988                                 closure, gdk_io_destroy);
989   g_io_channel_unref (channel);
990
991   return result;
992 }
993
994 gint
995 gdk_input_add (gint              source,
996                GdkInputCondition condition,
997                GdkInputFunction  function,
998                gpointer          data)
999 {
1000   return gdk_input_add_full (source, condition, function, data, NULL);
1001 }
1002
1003 void
1004 gdk_input_remove (gint tag)
1005 {
1006   g_source_remove (tag);
1007 }
1008
1009 static gint
1010 gdk_event_apply_filters (MSG      *xevent,
1011                          GdkEvent *event,
1012                          GList    *filters)
1013 {
1014   GdkEventFilter *filter;
1015   GList *tmp_list;
1016   GdkFilterReturn result;
1017   
1018   tmp_list = filters;
1019   
1020   while (tmp_list)
1021     {
1022       filter = (GdkEventFilter *) tmp_list->data;
1023       
1024       result = (*filter->function) (xevent, event, filter->data);
1025       if (result !=  GDK_FILTER_CONTINUE)
1026         return result;
1027       
1028       tmp_list = tmp_list->next;
1029     }
1030   
1031   return GDK_FILTER_CONTINUE;
1032 }
1033
1034 void 
1035 gdk_add_client_message_filter (GdkAtom       message_type,
1036                                GdkFilterFunc func,
1037                                gpointer      data)
1038 {
1039   GdkClientFilter *filter = g_new (GdkClientFilter, 1);
1040
1041   filter->type = message_type;
1042   filter->function = func;
1043   filter->data = data;
1044   
1045   client_filters = g_list_prepend (client_filters, filter);
1046 }
1047
1048 static void
1049 synthesize_crossing_events (GdkWindow *window,
1050                             MSG       *xevent)
1051 {
1052   GdkEvent *event;
1053   GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
1054   GdkWindowPrivate *curWnd_private = (GdkWindowPrivate *) curWnd;
1055   
1056   if (curWnd && (curWnd_private->event_mask & GDK_LEAVE_NOTIFY_MASK))
1057     {
1058       GDK_NOTE (EVENTS, g_print ("synthesizing LEAVE_NOTIFY event\n"));
1059
1060       event = gdk_event_new ();
1061       event->crossing.type = GDK_LEAVE_NOTIFY;
1062       event->crossing.window = curWnd;
1063       gdk_window_ref (event->crossing.window);
1064       event->crossing.subwindow = NULL;
1065       event->crossing.time = xevent->time;
1066       event->crossing.x = curX;
1067       event->crossing.y = curY;
1068       event->crossing.x_root = curXroot;
1069       event->crossing.y_root = curYroot;
1070       event->crossing.mode = GDK_CROSSING_NORMAL;
1071       event->crossing.detail = GDK_NOTIFY_UNKNOWN;
1072
1073       event->crossing.focus = TRUE; /* ??? */
1074       event->crossing.state = 0; /* ??? */
1075
1076       gdk_event_queue_append (event);
1077     }
1078
1079   if (window_private && (window_private->event_mask & GDK_ENTER_NOTIFY_MASK))
1080     {
1081       GDK_NOTE (EVENTS, g_print ("synthesizing ENTER_NOTIFY event\n"));
1082       
1083       event = gdk_event_new ();
1084       event->crossing.type = GDK_ENTER_NOTIFY;
1085       event->crossing.window = window;
1086       gdk_window_ref (event->crossing.window);
1087       event->crossing.subwindow = NULL;
1088       event->crossing.time = xevent->time;
1089       event->crossing.x = LOWORD (xevent->lParam);
1090       event->crossing.y = HIWORD (xevent->lParam);
1091       event->crossing.x_root = (gfloat) xevent->pt.x;
1092       event->crossing.y_root = (gfloat) xevent->pt.y;
1093       event->crossing.mode = GDK_CROSSING_NORMAL;
1094       event->crossing.detail = GDK_NOTIFY_UNKNOWN;
1095       
1096       event->crossing.focus = TRUE; /* ??? */
1097       event->crossing.state = 0; /* ??? */
1098       
1099       gdk_event_queue_append (event);
1100
1101       if (window_private->extension_events != 0
1102           && gdk_input_vtable.enter_event)
1103         gdk_input_vtable.enter_event (&event->crossing, window);
1104     }
1105   
1106   if (curWnd)
1107     gdk_window_unref (curWnd);
1108   curWnd = window;
1109   gdk_window_ref (curWnd);
1110 }
1111
1112 static gint
1113 gdk_event_translate (GdkEvent *event,
1114                      MSG      *xevent,
1115                      gboolean *ret_val_flagp,
1116                      gint     *ret_valp)
1117 {
1118   GdkWindow *window;
1119   GdkWindowPrivate *window_private;
1120
1121   GdkColormapPrivate *colormap_private;
1122   HWND owner;
1123   DWORD dwStyle;
1124   PAINTSTRUCT paintstruct;
1125   HDC hdc;
1126   HBRUSH hbr;
1127   RECT rect;
1128   POINT pt;
1129   GdkWindowPrivate *curWnd_private;
1130   GdkEventMask mask;
1131   int button;
1132   int i, j;
1133   gchar buf[256];
1134   gint charcount;
1135   gint return_val;
1136   gboolean flag;
1137   
1138   return_val = FALSE;
1139   
1140   if (ret_val_flagp)
1141     *ret_val_flagp = FALSE;
1142
1143   if (xevent->message == gdk_ping_msg)
1144     {
1145       /* Messages we post ourselves just to wakeup WaitMessage.  */
1146       return FALSE;
1147     }
1148
1149   window = gdk_window_lookup (xevent->hwnd);
1150   window_private = (GdkWindowPrivate *) window;
1151   
1152   if (xevent->message == g_pipe_readable_msg)
1153     {
1154       GDK_NOTE (EVENTS, g_print ("g_pipe_readable_msg: %d %d\n",
1155                                  xevent->wParam, xevent->lParam));
1156
1157       g_io_channel_win32_pipe_readable (xevent->wParam, xevent->lParam);
1158       return FALSE;
1159     }
1160
1161   if (window != NULL)
1162     gdk_window_ref (window);
1163   else
1164     {
1165       /* Handle WM_QUIT here ? */
1166       if (xevent->message == WM_QUIT)
1167         {
1168           GDK_NOTE (EVENTS, g_print ("WM_QUIT: %d\n", xevent->wParam));
1169           exit (xevent->wParam);
1170         }
1171       else if (xevent->message == WM_MOVE
1172                || xevent->message == WM_SIZE)
1173         {
1174           /* It's quite normal to get these messages before we have
1175            * had time to register the window in our lookup table, or
1176            * when the window is being destroyed and we already have
1177            * removed it. Repost the same message to our queue so that
1178            * we will get it later when we are prepared.
1179            */
1180           PostMessage (xevent->hwnd, xevent->message,
1181                        xevent->wParam, xevent->lParam);
1182         }
1183       else if (xevent->message == WM_NCCREATE
1184                || xevent->message == WM_CREATE
1185                || xevent->message == WM_GETMINMAXINFO
1186                || xevent->message == WM_NCCALCSIZE
1187                || xevent->message == WM_NCDESTROY
1188                || xevent->message == WM_DESTROY)
1189         {
1190           /* Nothing */
1191         }
1192       return FALSE;
1193     }
1194   
1195   event->any.window = window;
1196
1197   if (window_private && window_private->destroyed)
1198     {
1199     }
1200   else
1201     {
1202       /* Check for filters for this window */
1203       GdkFilterReturn result;
1204       result = gdk_event_apply_filters (xevent, event,
1205                                         window_private
1206                                         ?window_private->filters
1207                                         :gdk_default_filters);
1208       
1209       if (result != GDK_FILTER_CONTINUE)
1210         {
1211           return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1212         }
1213     }
1214
1215   if (xevent->message == gdk_selection_notify_msg)
1216     {
1217       GDK_NOTE (SELECTION, g_print ("gdk_selection_notify_msg: %#x\n",
1218                                     xevent->hwnd));
1219
1220       event->selection.type = GDK_SELECTION_NOTIFY;
1221       event->selection.window = window;
1222       event->selection.selection = xevent->wParam;
1223       event->selection.target = xevent->lParam;
1224       event->selection.property = gdk_selection_property;
1225       event->selection.time = xevent->time;
1226
1227       return_val = window_private && !window_private->destroyed;
1228
1229       /* Will pass through switch below without match */
1230     }
1231   else if (xevent->message == gdk_selection_request_msg)
1232     {
1233       GDK_NOTE (SELECTION, g_print ("gdk_selection_request_msg: %#x\n",
1234                                     xevent->hwnd));
1235
1236       event->selection.type = GDK_SELECTION_REQUEST;
1237       event->selection.window = window;
1238       event->selection.selection = gdk_clipboard_atom;
1239       event->selection.target = GDK_TARGET_STRING;
1240       event->selection.property = gdk_selection_property;
1241       event->selection.requestor = (guint32) xevent->hwnd;
1242       event->selection.time = xevent->time;
1243
1244       return_val = window_private && !window_private->destroyed;
1245
1246       /* Again, will pass through switch below without match */
1247     }
1248   else if (xevent->message == gdk_selection_clear_msg)
1249     {
1250       GDK_NOTE (SELECTION, g_print ("gdk_selection_clear_msg: %#x\n",
1251                                     xevent->hwnd));
1252
1253       event->selection.type = GDK_SELECTION_CLEAR;
1254       event->selection.window = window;
1255       event->selection.selection = xevent->wParam;
1256       event->selection.time = xevent->time;
1257
1258       return_val = window_private && !window_private->destroyed;
1259
1260       /* Once again, we will pass through switch below without match */
1261     }
1262   else
1263     {
1264       GList *tmp_list;
1265       GdkFilterReturn result = GDK_FILTER_CONTINUE;
1266
1267       tmp_list = client_filters;
1268       while (tmp_list)
1269         {
1270           GdkClientFilter *filter = tmp_list->data;
1271           if (filter->type == xevent->message)
1272             {
1273               GDK_NOTE (EVENTS, g_print ("client filter matched\n"));
1274               result = (*filter->function) (xevent, event, filter->data);
1275               switch (result)
1276                 {
1277                 case GDK_FILTER_REMOVE:
1278                   return_val = FALSE;
1279                   break;
1280
1281                 case GDK_FILTER_TRANSLATE:
1282                   return_val = TRUE;
1283                   break;
1284
1285                 case GDK_FILTER_CONTINUE:
1286                   return_val = TRUE;
1287                   event->client.type = GDK_CLIENT_EVENT;
1288                   event->client.window = window;
1289                   event->client.message_type = xevent->message;
1290                   event->client.data_format = 0;
1291                   event->client.data.l[0] = xevent->wParam;
1292                   event->client.data.l[1] = xevent->lParam;
1293                   break;
1294                 }
1295               goto bypass_switch; /* Ouch */
1296             }
1297           tmp_list = tmp_list->next;
1298         }
1299     }
1300
1301   switch (xevent->message)
1302     {
1303     case WM_SYSKEYUP:
1304     case WM_SYSKEYDOWN:
1305       GDK_NOTE (EVENTS,
1306                 g_print ("WM_SYSKEY%s: %#x  key: %s  %#x %#.08x\n",
1307                          (xevent->message == WM_SYSKEYUP ? "UP" : "DOWN"),
1308                          xevent->hwnd,
1309                          (GetKeyNameText (xevent->lParam, buf,
1310                                           sizeof (buf)) > 0 ?
1311                           buf : ""),
1312                          xevent->wParam,
1313                          xevent->lParam));
1314
1315       /* Let the system handle Alt-Tab and Alt-Enter */
1316       if (xevent->wParam == VK_TAB
1317           || xevent->wParam == VK_RETURN
1318           || xevent->wParam == VK_F4)
1319         break;
1320       /* If posted without us having keyboard focus, ignore */
1321       if (!(xevent->lParam & 0x20000000))
1322         break;
1323 #if 0
1324       /* don't generate events for just the Alt key */
1325       if (xevent->wParam == VK_MENU)
1326         break;
1327 #endif
1328       /* Jump to code in common with WM_KEYUP and WM_KEYDOWN */
1329       goto keyup_or_down;
1330
1331     case WM_KEYUP:
1332     case WM_KEYDOWN:
1333       GDK_NOTE (EVENTS, 
1334                 g_print ("WM_KEY%s: %#x  key: %s  %#x %#.08x\n",
1335                          (xevent->message == WM_KEYUP ? "UP" : "DOWN"),
1336                          xevent->hwnd,
1337                          (GetKeyNameText (xevent->lParam, buf,
1338                                           sizeof (buf)) > 0 ?
1339                           buf : ""),
1340                          xevent->wParam,
1341                          xevent->lParam));
1342
1343       ignore_WM_CHAR = TRUE;
1344     keyup_or_down:
1345       if (k_grab_window != NULL
1346           && !k_grab_owner_events)
1347         {
1348           /* Keyboard is grabbed with owner_events FALSE */
1349           GDK_NOTE (EVENTS,
1350                     g_print ("grabbed, owner_events FALSE, "
1351                              "sending to %#x\n", k_grab_window->xwindow));
1352           event->key.window = (GdkWindow *) k_grab_window;
1353         }
1354       else if (window_private
1355                && (((xevent->message == WM_KEYUP
1356                      || xevent->message == WM_SYSKEYUP)
1357                     && !(window_private->event_mask & GDK_KEY_RELEASE_MASK))
1358                    || ((xevent->message == WM_KEYDOWN
1359                         || xevent->message == WM_SYSKEYDOWN)
1360                        && !(window_private->event_mask & GDK_KEY_PRESS_MASK))))
1361         {
1362           /* Owner window doesn't want it */
1363           if (k_grab_window != NULL
1364               && k_grab_owner_events)
1365             {
1366               /* Keyboard is grabbed with owner_events TRUE */
1367               GDK_NOTE (EVENTS,
1368                         g_print ("grabbed, owner_events TRUE, doesn't want it, "
1369                                  "sending to %#x\n", k_grab_window->xwindow));
1370               event->key.window = (GdkWindow *) k_grab_window;
1371             }
1372           else
1373             {
1374               /* Owner doesn't want it, neither is it grabbed, so
1375                * propagate to parent.
1376                */
1377               if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1378                 break;
1379               gdk_window_unref (window);
1380               window = window_private->parent;
1381               gdk_window_ref (window);
1382               window_private = (GdkWindowPrivate *) window;
1383               GDK_NOTE (EVENTS,
1384                         g_print ("not wanted, not grabbed, "
1385                                  "sending to %#x\n", window_private->xwindow));
1386               goto keyup_or_down;
1387             }
1388         }
1389               
1390       switch (xevent->wParam)
1391         {
1392         case VK_LBUTTON:
1393           event->key.keyval = GDK_Pointer_Button1; break;
1394         case VK_RBUTTON:
1395           event->key.keyval = GDK_Pointer_Button3; break;
1396         case VK_MBUTTON:
1397           event->key.keyval = GDK_Pointer_Button2; break;
1398         case VK_CANCEL:
1399           event->key.keyval = GDK_Cancel; break;
1400         case VK_BACK:
1401           event->key.keyval = GDK_BackSpace; break;
1402         case VK_TAB:
1403           event->key.keyval = GDK_Tab; break;
1404         case VK_CLEAR:
1405           event->key.keyval = GDK_Clear; break;
1406         case VK_RETURN:
1407           event->key.keyval = GDK_Return; break;
1408         case VK_SHIFT:
1409           event->key.keyval = GDK_Shift_L; break;
1410         case VK_CONTROL:
1411           if (xevent->lParam & 0x01000000)
1412             event->key.keyval = GDK_Control_R;
1413           else
1414             event->key.keyval = GDK_Control_L;
1415           break;
1416         case VK_MENU:
1417           if (xevent->lParam & 0x01000000)
1418             {
1419               /* AltGr key comes in as Control+Right Alt */
1420               if (GetKeyState (VK_CONTROL) < 0)
1421                 {
1422                   ignore_WM_CHAR = FALSE;
1423                   is_AltGr_key = TRUE;
1424                 }
1425               event->key.keyval = GDK_Alt_R;
1426             }
1427           else
1428             event->key.keyval = GDK_Alt_L;
1429           break;
1430         case VK_PAUSE:
1431           event->key.keyval = GDK_Pause; break;
1432         case VK_CAPITAL:
1433           event->key.keyval = GDK_Caps_Lock; break;
1434         case VK_ESCAPE:
1435           event->key.keyval = GDK_Escape; break;
1436         case VK_PRIOR:
1437           event->key.keyval = GDK_Prior; break;
1438         case VK_NEXT:
1439           event->key.keyval = GDK_Next; break;
1440         case VK_END:
1441           event->key.keyval = GDK_End; break;
1442         case VK_HOME:
1443           event->key.keyval = GDK_Home; break;
1444         case VK_LEFT:
1445           event->key.keyval = GDK_Left; break;
1446         case VK_UP:
1447           event->key.keyval = GDK_Up; break;
1448         case VK_RIGHT:
1449           event->key.keyval = GDK_Right; break;
1450         case VK_DOWN:
1451           event->key.keyval = GDK_Down; break;
1452         case VK_SELECT:
1453           event->key.keyval = GDK_Select; break;
1454         case VK_PRINT:
1455           event->key.keyval = GDK_Print; break;
1456         case VK_EXECUTE:
1457           event->key.keyval = GDK_Execute; break;
1458         case VK_INSERT:
1459           event->key.keyval = GDK_Insert; break;
1460         case VK_DELETE:
1461           event->key.keyval = GDK_Delete; break;
1462         case VK_HELP:
1463           event->key.keyval = GDK_Help; break;
1464         case VK_NUMPAD0:
1465         case VK_NUMPAD1:
1466         case VK_NUMPAD2:
1467         case VK_NUMPAD3:
1468         case VK_NUMPAD4:
1469         case VK_NUMPAD5:
1470         case VK_NUMPAD6:
1471         case VK_NUMPAD7:
1472         case VK_NUMPAD8:
1473         case VK_NUMPAD9:
1474           /* Apparently applications work better if we just pass numpad digits
1475            * on as real digits? So wait for the WM_CHAR instead.
1476            */
1477           ignore_WM_CHAR = FALSE;
1478           break;
1479         case VK_MULTIPLY:
1480           event->key.keyval = GDK_KP_Multiply; break;
1481         case VK_ADD:
1482           event->key.keyval = GDK_KP_Add; break;
1483         case VK_SEPARATOR:
1484           event->key.keyval = GDK_KP_Separator; break;
1485         case VK_SUBTRACT:
1486           event->key.keyval = GDK_KP_Subtract; break;
1487         case VK_DECIMAL:
1488 #if 0
1489           event->key.keyval = GDK_KP_Decimal; break;
1490 #else
1491           /* The keypad decimal key should also be passed on as the decimal
1492            * sign ('.' or ',' depending on the Windows locale settings,
1493            * apparently). So wait for the WM_CHAR here, also.
1494            */
1495           ignore_WM_CHAR = FALSE;
1496           break;
1497 #endif
1498         case VK_DIVIDE:
1499           event->key.keyval = GDK_KP_Divide; break;
1500         case VK_F1:
1501           event->key.keyval = GDK_F1; break;
1502         case VK_F2:
1503           event->key.keyval = GDK_F2; break;
1504         case VK_F3:
1505           event->key.keyval = GDK_F3; break;
1506         case VK_F4:
1507           event->key.keyval = GDK_F4; break;
1508         case VK_F5:
1509           event->key.keyval = GDK_F5; break;
1510         case VK_F6:
1511           event->key.keyval = GDK_F6; break;
1512         case VK_F7:
1513           event->key.keyval = GDK_F7; break;
1514         case VK_F8:
1515           event->key.keyval = GDK_F8; break;
1516         case VK_F9:
1517           event->key.keyval = GDK_F9; break;
1518         case VK_F10:
1519           event->key.keyval = GDK_F10; break;
1520         case VK_F11:
1521           event->key.keyval = GDK_F11; break;
1522         case VK_F12:
1523           event->key.keyval = GDK_F12; break;
1524         case VK_F13:
1525           event->key.keyval = GDK_F13; break;
1526         case VK_F14:
1527           event->key.keyval = GDK_F14; break;
1528         case VK_F15:
1529           event->key.keyval = GDK_F15; break;
1530         case VK_F16:
1531           event->key.keyval = GDK_F16; break;
1532         default:
1533           if (xevent->message == WM_SYSKEYDOWN || xevent->message == WM_SYSKEYUP)
1534             {
1535               event->key.keyval = xevent->wParam;
1536             }
1537           else
1538             {
1539               ignore_WM_CHAR = FALSE;
1540               event->key.keyval = GDK_VoidSymbol;
1541             }
1542           break;
1543         }
1544
1545       if (!ignore_WM_CHAR)
1546         break;
1547
1548       is_AltGr_key = FALSE;
1549       event->key.type = ((xevent->message == WM_KEYDOWN
1550                           || xevent->message == WM_SYSKEYDOWN) ?
1551                          GDK_KEY_PRESS : GDK_KEY_RELEASE);
1552       event->key.window = window;
1553       event->key.time = xevent->time;
1554       event->key.state = 0;
1555       if (GetKeyState (VK_SHIFT) < 0)
1556         event->key.state |= GDK_SHIFT_MASK;
1557       if (GetKeyState (VK_CAPITAL) & 0x1)
1558         event->key.state |= GDK_LOCK_MASK;
1559       if (GetKeyState (VK_CONTROL) < 0)
1560         event->key.state |= GDK_CONTROL_MASK;
1561       if (xevent->wParam != VK_MENU && GetKeyState (VK_MENU) < 0)
1562         event->key.state |= GDK_MOD1_MASK;
1563       event->key.length = 0;
1564       return_val = window_private && !window_private->destroyed;
1565       event->key.string = NULL;
1566       break;
1567
1568     case WM_CHAR:
1569       GDK_NOTE (EVENTS, 
1570                 g_print ("WM_CHAR: %#x  char: %#x %#.08x  %s\n",
1571                          xevent->hwnd,
1572                          xevent->wParam,
1573                          xevent->lParam,
1574                          (ignore_WM_CHAR ? "ignored" : "")));
1575
1576       if (ignore_WM_CHAR)
1577         {
1578           ignore_WM_CHAR = FALSE;
1579           break;
1580         }
1581
1582     wm_char:
1583       /* This doesn't handle the rather theorethical case that a window
1584        * wants key presses but still wants releases to be propagated,
1585        * for instance.
1586        */
1587       if (k_grab_window != NULL
1588           && !k_grab_owner_events)
1589         {
1590           /* Keyboard is grabbed with owner_events FALSE */
1591           GDK_NOTE (EVENTS,
1592                     g_print ("grabbed, owner_events FALSE, "
1593                              "sending to %#x\n", k_grab_window->xwindow));
1594           event->key.window = (GdkWindow *) k_grab_window;
1595         }
1596       else if (window_private
1597                && !(window_private->event_mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK)))
1598         {
1599           /* Owner window doesn't want it */
1600           if (k_grab_window != NULL
1601               && k_grab_owner_events)
1602             {
1603               /* Keyboard is grabbed with owner_events TRUE */
1604               GDK_NOTE (EVENTS,
1605                         g_print ("grabbed, owner_events TRUE, doesn't want it, "
1606                                  "sending to %#x\n", k_grab_window->xwindow));
1607               event->key.window = (GdkWindow *) k_grab_window;
1608             }
1609           else
1610             {
1611               /* Owner doesn't want it, neither is it grabbed, so
1612                * propagate to parent.
1613                */
1614               if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1615                 g_assert_not_reached (); /* Should've been handled above */
1616
1617               gdk_window_unref (window);
1618               window = window_private->parent;
1619               gdk_window_ref (window);
1620               window_private = (GdkWindowPrivate *) window;
1621               GDK_NOTE (EVENTS,
1622                         g_print ("not wanted, not grabbed, sending to %#x\n",
1623                                  window_private->xwindow));
1624               goto wm_char;
1625             }
1626         }
1627       
1628       return_val = window_private && !window_private->destroyed;
1629       if (return_val && (window_private->event_mask & GDK_KEY_RELEASE_MASK))
1630         {
1631           /* Return the release event, and maybe append the press
1632            * event to the queued_events list (from which it will vbe
1633            * fetched before the release event).
1634            */
1635           event->key.type = GDK_KEY_RELEASE;
1636           event->key.keyval = xevent->wParam;
1637           event->key.window = window;
1638           event->key.time = xevent->time;
1639           event->key.state = 0;
1640           if (GetKeyState (VK_SHIFT) < 0)
1641             event->key.state |= GDK_SHIFT_MASK;
1642           if (GetKeyState (VK_CAPITAL) & 0x1)
1643             event->key.state |= GDK_LOCK_MASK;
1644           if (is_AltGr_key)
1645             ;
1646           else if (GetKeyState (VK_CONTROL) < 0)
1647             {
1648               event->key.state |= GDK_CONTROL_MASK;
1649               if (event->key.keyval < ' ')
1650                 event->key.keyval += '@';
1651             }
1652           else if (event->key.keyval < ' ')
1653             {
1654               event->key.state |= GDK_CONTROL_MASK;
1655               event->key.keyval += '@';
1656             }
1657           if (!is_AltGr_key && GetKeyState (VK_MENU) < 0)
1658             event->key.state |= GDK_MOD1_MASK;
1659           event->key.string = g_strdup (" ");
1660           event->key.length = 1;
1661           event->key.string[0] = xevent->wParam; /* ??? */
1662
1663           if (window_private->event_mask & GDK_KEY_PRESS_MASK)
1664             {
1665               /* Append also a GDK_KEY_PRESS event to the pushback list.  */
1666               GdkEvent *event2 = gdk_event_copy (event);
1667               event2->key.type = GDK_KEY_PRESS;
1668               charcount = xevent->lParam & 0xFFFF;
1669               if (charcount > sizeof (buf)- 1)
1670                 charcount = sizeof (buf) - 1;
1671               g_free (event2->key.string);
1672               event2->key.string = g_malloc (charcount);
1673               for (i = 0; i < charcount; i++)
1674                 event2->key.string[i] = event->key.keyval;
1675               event2->key.length = charcount;
1676
1677               gdk_event_queue_append (event2);
1678             }
1679         }
1680       else if (return_val && (window_private->event_mask & GDK_KEY_PRESS_MASK))
1681         {
1682           /* Return just the GDK_KEY_PRESS event. */
1683           event->key.type = GDK_KEY_PRESS;
1684           charcount = xevent->lParam & 0xFFFF;
1685           if (charcount > sizeof (buf)- 1)
1686             charcount = sizeof (buf) - 1;
1687           event->key.keyval = xevent->wParam;
1688           event->key.window = window;
1689           event->key.time = xevent->time;
1690           event->key.state = 0;
1691           if (GetKeyState (VK_SHIFT) < 0)
1692             event->key.state |= GDK_SHIFT_MASK;
1693           if (GetKeyState (VK_CAPITAL) & 0x1)
1694             event->key.state |= GDK_LOCK_MASK;
1695           if (is_AltGr_key)
1696             ;
1697           else if (GetKeyState (VK_CONTROL) < 0)
1698             {
1699               event->key.state |= GDK_CONTROL_MASK;
1700               if (event->key.keyval < ' ')
1701                 event->key.keyval += '@';
1702             }
1703           else if (event->key.keyval < ' ')
1704             {
1705               event->key.state |= GDK_CONTROL_MASK;
1706               event->key.keyval += '@';
1707             }
1708           if (!is_AltGr_key && GetKeyState (VK_MENU) < 0)
1709             event->key.state |= GDK_MOD1_MASK;
1710           event->key.string = g_malloc (charcount);
1711           for (i = 0; i < charcount; i++)
1712             event->key.string[i] = event->key.keyval;
1713           event->key.length = charcount;
1714         }
1715       else
1716         return_val = FALSE;
1717       is_AltGr_key = FALSE;
1718       break;
1719
1720     case WM_LBUTTONDOWN:
1721       button = 1;
1722       goto buttondown0;
1723     case WM_MBUTTONDOWN:
1724       button = 2;
1725       goto buttondown0;
1726     case WM_RBUTTONDOWN:
1727       button = 3;
1728
1729       /* Print debugging info.
1730        */
1731     buttondown0:
1732       GDK_NOTE (EVENTS, 
1733                 g_print ("WM_%cBUTTONDOWN: %#x  x,y: %d %d  button: %d\n",
1734                          " LMR"[button],
1735                          xevent->hwnd,
1736                          LOWORD (xevent->lParam), HIWORD (xevent->lParam),
1737                          button));
1738
1739       if (window_private
1740           && (window_private->extension_events != 0)
1741           && gdk_input_ignore_core)
1742         {
1743           GDK_NOTE (EVENTS, g_print ("... ignored\n"));
1744           break;
1745         }
1746
1747     buttondown:
1748       event->button.type = GDK_BUTTON_PRESS;
1749       event->button.window = window;
1750       if (window_private)
1751         mask = window_private->event_mask;
1752       else
1753         mask = 0;               /* ??? */
1754
1755       if (p_grab_window != NULL
1756            && !p_grab_owner_events)
1757         {
1758           /* Pointer is grabbed with owner_events FALSE */
1759           GDK_NOTE (EVENTS, g_print ("grabbed, owner_events FALSE\n"));
1760           mask = p_grab_event_mask;
1761           if (!(mask & GDK_BUTTON_PRESS_MASK))
1762             /* Grabber doesn't want it */
1763             break;
1764           else
1765             event->button.window = (GdkWindow *) p_grab_window;
1766           GDK_NOTE (EVENTS, g_print ("sending to %#x\n",
1767                                      p_grab_window->xwindow));
1768         }
1769       else if (window_private
1770                && !(mask & GDK_BUTTON_PRESS_MASK))
1771         {
1772           /* Owner window doesn't want it */
1773           if (p_grab_window != NULL
1774               && p_grab_owner_events)
1775             {
1776               /* Pointer is grabbed wíth owner_events TRUE */ 
1777               GDK_NOTE (EVENTS, g_print ("grabbed, owner_events TRUE, doesn't want it\n"));
1778               mask = p_grab_event_mask;
1779               if (!(mask & GDK_BUTTON_PRESS_MASK))
1780                 /* Grabber doesn't want it either */
1781                 break;
1782               else
1783                 event->button.window = (GdkWindow *) p_grab_window;
1784               GDK_NOTE (EVENTS, g_print ("sending to %#x\n",
1785                                          p_grab_window->xwindow));
1786             }
1787           else
1788             {
1789               /* Owner doesn't want it, neither is it grabbed, so
1790                * propagate to parent.
1791                */
1792               /* Yes, this code is duplicated twice below. So shoot me. */
1793               if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1794                 break;
1795               pt.x = LOWORD (xevent->lParam);
1796               pt.y = HIWORD (xevent->lParam);
1797               ClientToScreen (window_private->xwindow, &pt);
1798               gdk_window_unref (window);
1799               window = window_private->parent;
1800               gdk_window_ref (window);
1801               window_private = (GdkWindowPrivate *) window;
1802               ScreenToClient (window_private->xwindow, &pt);
1803               xevent->lParam = MAKELPARAM (pt.x, pt.y);
1804               goto buttondown; /* What did Dijkstra say? */
1805             }
1806         }
1807
1808       /* Emulate X11's automatic active grab */
1809       if (!p_grab_window)
1810         {
1811           /* No explicit active grab, let's start one automatically */
1812           GDK_NOTE (EVENTS, g_print ("automatic grab started\n"));
1813           gdk_pointer_grab (window, TRUE, window_private->event_mask,
1814                             NULL, NULL, 0);
1815           p_grab_automatic = TRUE;
1816         }
1817
1818       if (window != curWnd)
1819         synthesize_crossing_events (window, xevent);
1820
1821       event->button.time = xevent->time;
1822       event->button.x = LOWORD (xevent->lParam);
1823       event->button.y = HIWORD (xevent->lParam);
1824       event->button.x_root = (gfloat)xevent->pt.x;
1825       event->button.y_root = (gfloat)xevent->pt.y;
1826       event->button.pressure = 0.5;
1827       event->button.xtilt = 0;
1828       event->button.ytilt = 0;
1829       event->button.state = 0;
1830       if (xevent->wParam & MK_CONTROL)
1831         event->button.state |= GDK_CONTROL_MASK;
1832       if (xevent->wParam & MK_LBUTTON)
1833         event->button.state |= GDK_BUTTON1_MASK;
1834       if (xevent->wParam & MK_MBUTTON)
1835         event->button.state |= GDK_BUTTON2_MASK;
1836       if (xevent->wParam & MK_RBUTTON)
1837         event->button.state |= GDK_BUTTON3_MASK;
1838       if (xevent->wParam & MK_SHIFT)
1839         event->button.state |= GDK_SHIFT_MASK;
1840       if (GetKeyState (VK_MENU) < 0)
1841         event->button.state |= GDK_MOD1_MASK;
1842       if (GetKeyState (VK_CAPITAL) & 0x1)
1843         event->button.state |= GDK_LOCK_MASK;
1844       event->button.button = button;
1845       event->button.source = GDK_SOURCE_MOUSE;
1846       event->button.deviceid = GDK_CORE_POINTER;
1847
1848       if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1849           (event->button.window == button_window[1]) &&
1850           (event->button.button == button_number[1]))
1851         {
1852           gdk_synthesize_click (event, 3);
1853
1854           button_click_time[1] = 0;
1855           button_click_time[0] = 0;
1856           button_window[1] = NULL;
1857           button_window[0] = 0;
1858           button_number[1] = -1;
1859           button_number[0] = -1;
1860         }
1861       else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1862                (event->button.window == button_window[0]) &&
1863                (event->button.button == button_number[0]))
1864         {
1865           gdk_synthesize_click (event, 2);
1866
1867           button_click_time[1] = button_click_time[0];
1868           button_click_time[0] = event->button.time;
1869           button_window[1] = button_window[0];
1870           button_window[0] = event->button.window;
1871           button_number[1] = button_number[0];
1872           button_number[0] = event->button.button;
1873         }
1874       else
1875         {
1876           button_click_time[1] = 0;
1877           button_click_time[0] = event->button.time;
1878           button_window[1] = NULL;
1879           button_window[0] = event->button.window;
1880           button_number[1] = -1;
1881           button_number[0] = event->button.button;
1882         }
1883       return_val = window_private && !window_private->destroyed;
1884       if (return_val
1885           && p_grab_window != NULL
1886           && event->any.window == (GdkWindow *) p_grab_window
1887           && p_grab_window != window_private)
1888         {
1889           /* Translate coordinates to grabber */
1890           pt.x = event->button.x;
1891           pt.y = event->button.y;
1892           ClientToScreen (window_private->xwindow, &pt);
1893           ScreenToClient (p_grab_window->xwindow, &pt);
1894           event->button.x = pt.x;
1895           event->button.y = pt.y;
1896           GDK_NOTE (EVENTS, g_print ("New coords are +%d+%d\n", pt.x, pt.y));
1897         }
1898       break;
1899
1900     case WM_LBUTTONUP:
1901       button = 1;
1902       goto buttonup0;
1903     case WM_MBUTTONUP:
1904       button = 2;
1905       goto buttonup0;
1906     case WM_RBUTTONUP:
1907       button = 3;
1908
1909       /* Print debugging info.
1910        */
1911     buttonup0:
1912       GDK_NOTE (EVENTS, 
1913                 g_print ("WM_%cBUTTONUP: %#x  x,y: %d %d  button: %d\n",
1914                          " LMR"[button],
1915                          xevent->hwnd,
1916                          LOWORD (xevent->lParam), HIWORD (xevent->lParam),
1917                          button));
1918
1919       if (window_private
1920           && (window_private->extension_events != 0)
1921           && gdk_input_ignore_core)
1922         {
1923           GDK_NOTE (EVENTS, g_print ("... ignored\n"));
1924           break;
1925         }
1926
1927     buttonup:
1928       event->button.type = GDK_BUTTON_RELEASE;
1929       event->button.window = window;
1930       if (window_private)
1931         mask = window_private->event_mask;
1932       else
1933         mask = 0;
1934
1935       if (p_grab_window != NULL
1936            && !p_grab_owner_events)
1937         {
1938           /* Pointer is grabbed with owner_events FALSE */
1939           GDK_NOTE (EVENTS, g_print ("grabbed, owner_events FALSE\n"));
1940           mask = p_grab_event_mask;
1941           if (!(mask & GDK_BUTTON_RELEASE_MASK))
1942             /* Grabber doesn't want it */
1943             break;
1944           else
1945             event->button.window = (GdkWindow *) p_grab_window;
1946           GDK_NOTE (EVENTS, g_print ("sending to %#x\n",
1947                                      p_grab_window->xwindow));
1948         }
1949       else if (window_private
1950                && !(mask & GDK_BUTTON_RELEASE_MASK))
1951         {
1952           /* Owner window doesn't want it */
1953           if (p_grab_window != NULL
1954               && p_grab_owner_events)
1955             {
1956               /* Pointer is grabbed wíth owner_events TRUE */
1957               GDK_NOTE (EVENTS, g_print ("grabbed, owner_events TRUE, doesn't want it\n"));
1958               mask = p_grab_event_mask;
1959               if (!(mask & GDK_BUTTON_RELEASE_MASK))
1960                 /* Grabber doesn't want it */
1961                 break;
1962               else
1963                 event->button.window = (GdkWindow *) p_grab_window;
1964               GDK_NOTE (EVENTS, g_print ("sending to %#x\n",
1965                                          p_grab_window->xwindow));
1966             }
1967           else
1968             {
1969               /* Owner doesn't want it, neither is it grabbed, so
1970                * propagate to parent.
1971                */
1972               if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1973                 break;
1974               pt.x = LOWORD (xevent->lParam);
1975               pt.y = HIWORD (xevent->lParam);
1976               ClientToScreen (window_private->xwindow, &pt);
1977               gdk_window_unref (window);
1978               window = window_private->parent;
1979               gdk_window_ref (window);
1980               window_private = (GdkWindowPrivate *) window;
1981               ScreenToClient (window_private->xwindow, &pt);
1982               xevent->lParam = MAKELPARAM (pt.x, pt.y);
1983               goto buttonup;
1984             }
1985         }
1986
1987       if (window != curWnd)
1988         synthesize_crossing_events (window, xevent);
1989
1990       event->button.time = xevent->time;
1991       event->button.x = LOWORD (xevent->lParam);
1992       event->button.y = HIWORD (xevent->lParam);
1993       event->button.x_root = (gfloat)xevent->pt.x;
1994       event->button.y_root = (gfloat)xevent->pt.y;
1995       event->button.pressure = 0.5;
1996       event->button.xtilt = 0;
1997       event->button.ytilt = 0;
1998       event->button.state = 0;
1999       if (xevent->wParam & MK_CONTROL)
2000         event->button.state |= GDK_CONTROL_MASK;
2001       if (xevent->wParam & MK_LBUTTON)
2002         event->button.state |= GDK_BUTTON1_MASK;
2003       if (xevent->wParam & MK_MBUTTON)
2004         event->button.state |= GDK_BUTTON2_MASK;
2005       if (xevent->wParam & MK_RBUTTON)
2006         event->button.state |= GDK_BUTTON3_MASK;
2007       if (xevent->wParam & MK_SHIFT)
2008         event->button.state |= GDK_SHIFT_MASK;
2009       event->button.button = button;
2010       event->button.source = GDK_SOURCE_MOUSE;
2011       event->button.deviceid = GDK_CORE_POINTER;
2012       return_val = window_private && !window_private->destroyed;
2013       if (return_val
2014           && p_grab_window != NULL
2015           && event->any.window == (GdkWindow *) p_grab_window
2016           && p_grab_window != window_private)
2017         {
2018           /* Translate coordinates to grabber */
2019           pt.x = event->button.x;
2020           pt.y = event->button.y;
2021           ClientToScreen (window_private->xwindow, &pt);
2022           ScreenToClient (p_grab_window->xwindow, &pt);
2023           event->button.x = pt.x;
2024           event->button.y = pt.y;
2025           GDK_NOTE (EVENTS, g_print ("New coords are +%d+%d\n", pt.x, pt.y));
2026         }
2027       if (p_grab_window != NULL
2028           && p_grab_automatic
2029           && (event->button.state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) == 0)
2030         gdk_pointer_ungrab (0);
2031       break;
2032
2033     case WM_MOUSEMOVE:
2034       /* Print debugging info.
2035        */
2036       GDK_NOTE (EVENTS,
2037                 g_print ("WM_MOUSEMOVE: %#x  %#x +%d+%d\n",
2038                          xevent->hwnd, xevent->wParam,
2039                          LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2040
2041 #if 0
2042       /* Try hard not to generate events for windows that shouldn't
2043          get any.  This is hard because we don't want pushbuttons to
2044          highlight when the cursor moves over them if the window is
2045          inactive. We dont want tooltips windows to be active. OTOH,
2046          also menus are popup windows, but they definitely should
2047          get events. Aw shit. Skip this.
2048        */
2049       dwStyle = GetWindowLong (xevent->hwnd, GWL_STYLE);
2050       if (active == NULL ||
2051           !(active == xevent->hwnd
2052             || (dwStyle & WS_POPUP)
2053             || IsChild (active, xevent->hwnd)))
2054         break;
2055 #else
2056       { /* HB: only process mouse move messages
2057          * if we own the active window.
2058          */
2059           DWORD ProcessID_ActWin;
2060           DWORD ProcessID_this;
2061
2062           GetWindowThreadProcessId(GetActiveWindow(), &ProcessID_ActWin);
2063           GetWindowThreadProcessId(xevent->hwnd, &ProcessID_this);
2064           if (ProcessID_ActWin != ProcessID_this)
2065           break;
2066      }
2067 #endif
2068       if (window != curWnd)
2069         synthesize_crossing_events (window, xevent);
2070
2071       if (window_private
2072           && (window_private->extension_events != 0)
2073           && gdk_input_ignore_core)
2074         {
2075           GDK_NOTE (EVENTS, g_print ("... ignored\n"));
2076           break;
2077         }
2078
2079     mousemotion:
2080       event->motion.type = GDK_MOTION_NOTIFY;
2081       event->motion.window = window;
2082       if (window_private)
2083         mask = window_private->event_mask;
2084       else
2085         mask = 0;
2086
2087       if (p_grab_window
2088           && !p_grab_owner_events)
2089         {
2090           /* Pointer is grabbed with owner_events FALSE */
2091           GDK_NOTE (EVENTS,
2092                     g_print ("grabbed, owner_events FALSE\n"));
2093           mask = p_grab_event_mask;
2094           if (!((mask & GDK_POINTER_MOTION_MASK)
2095                 || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
2096                     && (mask & GDK_BUTTON_MOTION_MASK))
2097                 || ((xevent->wParam & MK_LBUTTON)
2098                     && (mask & GDK_BUTTON1_MOTION_MASK))
2099                 || ((xevent->wParam & MK_MBUTTON)
2100                     && (mask & GDK_BUTTON2_MOTION_MASK))
2101                 || ((xevent->wParam & MK_RBUTTON)
2102                     && (mask & GDK_BUTTON3_MOTION_MASK))))
2103             break;
2104           else
2105             event->motion.window = (GdkWindow *) p_grab_window;
2106           GDK_NOTE (EVENTS, g_print ("sending to %#x\n",
2107                                      p_grab_window->xwindow));
2108         }
2109       else if (window_private
2110                && !((mask & GDK_POINTER_MOTION_MASK)
2111                     || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
2112                         && (mask & GDK_BUTTON_MOTION_MASK))
2113                     || ((xevent->wParam & MK_LBUTTON)
2114                         && (mask & GDK_BUTTON1_MOTION_MASK))
2115                     || ((xevent->wParam & MK_MBUTTON)
2116                         && (mask & GDK_BUTTON2_MOTION_MASK))
2117                     || ((xevent->wParam & MK_RBUTTON)
2118                         && (mask & GDK_BUTTON3_MOTION_MASK))))
2119         {
2120           /* Owner window doesn't want it */
2121           if (p_grab_window != NULL
2122               && p_grab_owner_events)
2123             {
2124               /* Pointer is grabbed wíth owner_events TRUE */
2125               GDK_NOTE (EVENTS, g_print ("grabbed, owner_events TRUE, doesn't want it\n"));
2126               mask = p_grab_event_mask;
2127               if (!((p_grab_event_mask & GDK_POINTER_MOTION_MASK)
2128                     || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
2129                         && (mask & GDK_BUTTON_MOTION_MASK))
2130                     || ((xevent->wParam & MK_LBUTTON)
2131                         && (mask & GDK_BUTTON1_MOTION_MASK))
2132                     || ((xevent->wParam & MK_MBUTTON)
2133                         && (mask & GDK_BUTTON2_MOTION_MASK))
2134                     || ((xevent->wParam & MK_RBUTTON)
2135                         && (mask & GDK_BUTTON3_MOTION_MASK))))
2136                 /* Grabber doesn't want it either */
2137                 break;
2138               else
2139                 event->motion.window = (GdkWindow *) p_grab_window;
2140               GDK_NOTE (EVENTS, g_print ("sending to %#x\n",
2141                                          p_grab_window->xwindow));
2142             }
2143           else
2144             {
2145               /* Owner doesn't want it, neither is it grabbed, so
2146                * propagate to parent.
2147                */
2148               if (window_private->parent == (GdkWindow *) &gdk_root_parent)
2149                 break;
2150               pt.x = LOWORD (xevent->lParam);
2151               pt.y = HIWORD (xevent->lParam);
2152               ClientToScreen (window_private->xwindow, &pt);
2153               gdk_window_unref (window);
2154               window = window_private->parent;
2155               gdk_window_ref (window);
2156               window_private = (GdkWindowPrivate *) window;
2157               ScreenToClient (window_private->xwindow, &pt);
2158               xevent->lParam = MAKELPARAM (pt.x, pt.y);
2159               GDK_NOTE (EVENTS, g_print ("propagating to %#x\n",
2160                                          window_private->xwindow));
2161               goto mousemotion;
2162             }
2163         }
2164
2165       event->motion.time = xevent->time;
2166       event->motion.x = curX = LOWORD (xevent->lParam);
2167       event->motion.y = curY = HIWORD (xevent->lParam);
2168       event->motion.x_root = xevent->pt.x;
2169       event->motion.y_root = xevent->pt.y;
2170       curXroot = event->motion.x_root;
2171       curYroot = event->motion.y_root;
2172       event->motion.pressure = 0.5;
2173       event->motion.xtilt = 0;
2174       event->motion.ytilt = 0;
2175       event->button.state = 0;
2176       if (xevent->wParam & MK_CONTROL)
2177         event->button.state |= GDK_CONTROL_MASK;
2178       if (xevent->wParam & MK_LBUTTON)
2179         event->button.state |= GDK_BUTTON1_MASK;
2180       if (xevent->wParam & MK_MBUTTON)
2181         event->button.state |= GDK_BUTTON2_MASK;
2182       if (xevent->wParam & MK_RBUTTON)
2183         event->button.state |= GDK_BUTTON3_MASK;
2184       if (xevent->wParam & MK_SHIFT)
2185         event->button.state |= GDK_SHIFT_MASK;
2186       if (mask & GDK_POINTER_MOTION_HINT_MASK)
2187         event->motion.is_hint = NotifyHint;
2188       else
2189         event->motion.is_hint = NotifyNormal;
2190       event->motion.source = GDK_SOURCE_MOUSE;
2191       event->motion.deviceid = GDK_CORE_POINTER;
2192
2193       return_val = window_private && !window_private->destroyed;
2194       if (return_val
2195           && p_grab_window != NULL
2196           && event->any.window == (GdkWindow *) p_grab_window
2197           && p_grab_window != window_private)
2198         {
2199           /* Translate coordinates to grabber */
2200           pt.x = event->motion.x;
2201           pt.y = event->motion.y;
2202           ClientToScreen (window_private->xwindow, &pt);
2203           ScreenToClient (p_grab_window->xwindow, &pt);
2204           event->motion.x = pt.x;
2205           event->motion.y = pt.y;
2206           GDK_NOTE (EVENTS, g_print ("New coords are +%d+%d\n", pt.x, pt.y));
2207         }
2208       break;
2209
2210     case WM_NCMOUSEMOVE:
2211       /* Print debugging info.  */
2212       GDK_NOTE (EVENTS,
2213                 g_print ("WM_NCMOUSEMOVE: %#x  x,y: %d %d\n",
2214                          xevent->hwnd,
2215                          LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2216 #if 0
2217       if (active == NULL || active != xevent->hwnd)
2218         break;
2219 #endif
2220       curWnd_private = (GdkWindowPrivate *) curWnd;
2221       if (curWnd != NULL
2222           && (curWnd_private->event_mask & GDK_LEAVE_NOTIFY_MASK))
2223         {
2224           GDK_NOTE (EVENTS, g_print ("synthesizing LEAVE_NOTIFY event\n"));
2225
2226           event->crossing.type = GDK_LEAVE_NOTIFY;
2227           event->crossing.window = curWnd;
2228           event->crossing.subwindow = NULL;
2229           event->crossing.time = xevent->time;
2230           event->crossing.x = curX;
2231           event->crossing.y = curY;
2232           event->crossing.x_root = curXroot;
2233           event->crossing.y_root = curYroot;
2234           event->crossing.mode = GDK_CROSSING_NORMAL;
2235           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2236
2237           event->crossing.focus = TRUE; /* ??? */
2238           event->crossing.state = 0; /* ??? */
2239           gdk_window_unref (curWnd);
2240           curWnd = NULL;
2241
2242           return_val = TRUE;
2243         }
2244       break;
2245
2246     case WM_SETFOCUS:
2247     case WM_KILLFOCUS:
2248       if (window_private
2249           && !(window_private->event_mask & GDK_FOCUS_CHANGE_MASK))
2250         break;
2251
2252       GDK_NOTE (EVENTS, g_print ("WM_%sFOCUS: %#x\n",
2253                                  (xevent->message == WM_SETFOCUS ? "SET" : "KILL"),
2254                                  xevent->hwnd));
2255       
2256       event->focus_change.type = GDK_FOCUS_CHANGE;
2257       event->focus_change.window = window;
2258       event->focus_change.in = (xevent->message == WM_SETFOCUS);
2259       return_val = window_private && !window_private->destroyed;
2260       break;
2261 #if 0
2262     case WM_ACTIVATE:
2263       GDK_NOTE (EVENTS, g_print ("WM_ACTIVATE: %#x  %d\n",
2264                                  xevent->hwnd, LOWORD (xevent->wParam)));
2265       if (LOWORD (xevent->wParam) == WA_INACTIVE)
2266         active = (HWND) xevent->lParam;
2267       else
2268         active = xevent->hwnd;
2269       break;
2270 #endif
2271     case WM_ERASEBKGND:
2272       GDK_NOTE (EVENTS, g_print ("WM_ERASEBKGND: %#x  dc %#x\n",
2273                                  xevent->hwnd, xevent->wParam));
2274       
2275       if (!window_private || window_private->destroyed)
2276         break;
2277       colormap_private = (GdkColormapPrivate *) window_private->colormap;
2278       hdc = (HDC) xevent->wParam;
2279       if (colormap_private
2280           && colormap_private->xcolormap->rc_palette)
2281         {
2282           int k;
2283
2284           if (SelectPalette (hdc,  colormap_private->xcolormap->palette,
2285                              FALSE) == NULL)
2286             g_warning ("WM_ERASEBKGND: SelectPalette failed");
2287           if ((k = RealizePalette (hdc)) == GDI_ERROR)
2288             g_warning ("WM_ERASEBKGND: RealizePalette failed");
2289 #if 0
2290           g_print ("WM_ERASEBKGND: selected %#x, realized %d colors\n",
2291                    colormap_private->xcolormap->palette, k);
2292 #endif
2293         }
2294       *ret_val_flagp = TRUE;
2295       *ret_valp = 1;
2296
2297       if (window_private->bg_type == GDK_WIN32_BG_TRANSPARENT)
2298         break;
2299
2300       if (window_private->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
2301         {
2302           /* If this window should have the same background as the
2303            * parent, fetch the parent. (And if the same goes for
2304            * the parent, fetch the grandparent, etc.)
2305            */
2306           while (window_private
2307                  && window_private->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
2308             window_private = (GdkWindowPrivate *) window_private->parent;
2309         }
2310
2311       if (window_private->bg_type == GDK_WIN32_BG_PIXEL)
2312         {
2313           COLORREF bg;
2314           GDK_NOTE (EVENTS, g_print ("... BG_PIXEL %s\n",
2315                                      gdk_color_to_string (&window_private->bg_pixel)));
2316           GetClipBox (hdc, &rect);
2317 #ifdef MULTIPLE_WINDOW_CLASSES
2318           bg = PALETTEINDEX (window_private->bg_pixel.pixel);
2319 #else
2320           bg = GetNearestColor (hdc, RGB (window_private->bg_pixel.red >> 8,
2321                                           window_private->bg_pixel.green >> 8,
2322                                           window_private->bg_pixel.blue >> 8));
2323 #endif
2324           hbr = CreateSolidBrush (bg);
2325 #if 0
2326           g_print ("... CreateSolidBrush (%.08x) = %.08x\n", bg, hbr);
2327 #endif
2328           if (!FillRect (hdc, &rect, hbr))
2329             g_warning ("WM_ERASEBKGND: FillRect failed");
2330           DeleteObject (hbr);
2331         }
2332       else if (window_private->bg_type == GDK_WIN32_BG_PIXMAP)
2333         {
2334           GdkPixmapPrivate *pixmap_private;
2335           HDC bgdc;
2336           HGDIOBJ oldbitmap;
2337
2338           pixmap_private = (GdkPixmapPrivate *) window_private->bg_pixmap;
2339           GetClipBox (hdc, &rect);
2340
2341           if (pixmap_private->width <= 8
2342               && pixmap_private->height <= 8)
2343             {
2344               GDK_NOTE (EVENTS, g_print ("...small pixmap, using brush\n"));
2345               hbr = CreatePatternBrush (pixmap_private->xwindow);
2346               if (!FillRect (hdc, &rect, hbr))
2347                 g_warning ("WM_ERASEBKGND: FillRect failed");
2348               DeleteObject (hbr);
2349             }
2350           else
2351             {
2352               GDK_NOTE (EVENTS,
2353                         g_print ("...blitting pixmap %#x (%dx%d) "
2354                                  "all over the place,\n"
2355                                  "...clip box = %dx%d@+%d+%d\n",
2356                                  pixmap_private->xwindow,
2357                                  pixmap_private->width, pixmap_private->height,
2358                                  rect.right - rect.left, rect.bottom - rect.top,
2359                                  rect.left, rect.top));
2360
2361               if (!(bgdc = CreateCompatibleDC (hdc)))
2362                 {
2363                   g_warning ("WM_ERASEBKGND: CreateCompatibleDC failed");
2364                   break;
2365                 }
2366               if (!(oldbitmap = SelectObject (bgdc, pixmap_private->xwindow)))
2367                 {
2368                   g_warning ("WM_ERASEBKGND: SelectObject failed");
2369                   DeleteDC (bgdc);
2370                   break;
2371                 }
2372               i = 0;
2373               while (i < rect.right)
2374                 {
2375                   j = 0;
2376                   while (j < rect.bottom)
2377                     {
2378                       if (i + pixmap_private->width >= rect.left
2379                           && j + pixmap_private->height >= rect.top)
2380                         {
2381                           if (!BitBlt (hdc, i, j,
2382                                        pixmap_private->width, pixmap_private->height,
2383                                        bgdc, 0, 0, SRCCOPY))
2384                             {
2385                               g_warning ("WM_ERASEBKGND: BitBlt failed");
2386                               goto loopexit;
2387                             }
2388                         }
2389                       j += pixmap_private->height;
2390                     }
2391                   i += pixmap_private->width;
2392                 }
2393             loopexit:
2394               SelectObject (bgdc, oldbitmap);
2395               DeleteDC (bgdc);
2396             }
2397         }
2398       else
2399         {
2400           GDK_NOTE (EVENTS, g_print ("... BLACK_BRUSH (?)\n"));
2401 #ifdef MULTIPLE_WINDOW_CLASSES
2402           hbr = (HBRUSH) GetClassLong (window_private->xwindow,
2403                                        GCL_HBRBACKGROUND);
2404 #else
2405           hbr = GetStockObject (BLACK_BRUSH);
2406 #endif
2407           GetClipBox (hdc, &rect);
2408           if (!FillRect (hdc, &rect, hbr))
2409             g_warning ("WM_ERASEBKGND: FillRect failed");
2410         }
2411       break;
2412
2413     case WM_PAINT:
2414       GDK_NOTE (EVENTS, g_print ("WM_PAINT: %#x\n", xevent->hwnd));
2415       hdc = BeginPaint (xevent->hwnd, &paintstruct);
2416
2417       /* Print debugging info.
2418        */
2419       GDK_NOTE (EVENTS,
2420                 g_print ("...WM_PAINT: %#x  %dx%d@+%d+%d %s dc %#x\n",
2421                          xevent->hwnd,
2422                          paintstruct.rcPaint.right - paintstruct.rcPaint.left,
2423                          paintstruct.rcPaint.bottom - paintstruct.rcPaint.top,
2424                          paintstruct.rcPaint.left, paintstruct.rcPaint.top,
2425                          (paintstruct.fErase ? "erase" : ""),
2426                          hdc));
2427
2428       EndPaint (xevent->hwnd, &paintstruct);
2429
2430       if (window_private
2431           && !(window_private->event_mask & GDK_EXPOSURE_MASK))
2432         break;
2433
2434       event->expose.type = GDK_EXPOSE;
2435       event->expose.window = window;
2436       event->expose.area.x = paintstruct.rcPaint.left;
2437       event->expose.area.y = paintstruct.rcPaint.top;
2438       event->expose.area.width = paintstruct.rcPaint.right - paintstruct.rcPaint.left;
2439       event->expose.area.height = paintstruct.rcPaint.bottom - paintstruct.rcPaint.top;
2440       event->expose.count = 1;
2441
2442       return_val = window_private && !window_private->destroyed;
2443       break;
2444
2445 #ifndef MULTIPLE_WINDOW_CLASSES
2446     case WM_SETCURSOR:
2447       GDK_NOTE (EVENTS, g_print ("WM_SETCURSOR: %#x %#x %#x\n",
2448                                  xevent->hwnd,
2449                                  LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2450
2451       return_val = FALSE;
2452       if (LOWORD (xevent->lParam) != HTCLIENT)
2453         break;
2454       if (p_grab_window != NULL && p_grab_cursor != NULL)
2455         SetCursor (p_grab_cursor);
2456       else if (window_private
2457                && !window_private->destroyed
2458                && window_private->xcursor)
2459         SetCursor (window_private->xcursor);
2460       *ret_val_flagp = TRUE;
2461       *ret_valp = FALSE;
2462       break;
2463 #endif
2464
2465 #if 0
2466     case WM_QUERYOPEN:
2467       GDK_NOTE (EVENTS, g_print ("WM_QUERYOPEN: %#x\n",
2468                                  xevent->hwnd));
2469       *ret_val_flagp = TRUE;
2470       *ret_valp = TRUE;
2471
2472       if (window_private
2473           && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2474         break;
2475
2476       event->any.type = GDK_MAP;
2477       event->any.window = window;
2478
2479       return_val = window_private && !window_private->destroyed;
2480       break;
2481 #endif
2482
2483 #if 1
2484     case WM_SHOWWINDOW:
2485       /* Print debugging info.
2486        */
2487       GDK_NOTE (EVENTS, g_print ("WM_SHOWWINDOW: %#x  %d\n",
2488                                  xevent->hwnd,
2489                                  xevent->wParam));
2490
2491       if (window_private
2492           && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2493         break;
2494
2495       event->any.type = (xevent->wParam ? GDK_MAP : GDK_UNMAP);
2496       event->any.window = window;
2497
2498       if (event->any.type == GDK_UNMAP
2499           && p_grab_window == window_private)
2500         gdk_pointer_ungrab (xevent->time);
2501
2502       if (event->any.type == GDK_UNMAP
2503           && k_grab_window == window_private)
2504         gdk_keyboard_ungrab (xevent->time);
2505
2506       return_val = window_private && !window_private->destroyed;
2507       break;
2508 #endif
2509     case WM_SIZE:
2510       /* Print debugging info.
2511        */
2512       GDK_NOTE (EVENTS,
2513                 g_print ("WM_SIZE: %#x  %s %dx%d\n",
2514                          xevent->hwnd,
2515                          (xevent->wParam == SIZE_MAXHIDE ? "MAXHIDE" :
2516                           (xevent->wParam == SIZE_MAXIMIZED ? "MAXIMIZED" :
2517                            (xevent->wParam == SIZE_MAXSHOW ? "MAXSHOW" :
2518                             (xevent->wParam == SIZE_MINIMIZED ? "MINIMIZED" :
2519                              (xevent->wParam == SIZE_RESTORED ? "RESTORED" : "?"))))),
2520                          LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2521
2522       if (window_private
2523           && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2524         break;
2525       if (window_private != NULL
2526           && xevent->wParam == SIZE_MINIMIZED)
2527         {
2528 #if 1
2529           event->any.type = GDK_UNMAP;
2530           event->any.window = window;
2531
2532           if (p_grab_window == window_private)
2533             gdk_pointer_ungrab (xevent->time);
2534
2535           if (k_grab_window == window_private)
2536             gdk_keyboard_ungrab (xevent->time);
2537
2538           return_val = !window_private->destroyed;
2539 #endif
2540         }
2541       else if (window_private != NULL
2542                && (xevent->wParam == SIZE_RESTORED
2543                    || xevent->wParam == SIZE_MAXIMIZED)
2544 #if 1
2545                && window_private->window_type != GDK_WINDOW_CHILD
2546 #endif
2547                                                                  )
2548         {
2549           if (LOWORD (xevent->lParam) == 0)
2550             break;
2551
2552           event->configure.type = GDK_CONFIGURE;
2553           event->configure.window = window;
2554           pt.x = 0;
2555           pt.y = 0;
2556           ClientToScreen (xevent->hwnd, &pt);
2557           event->configure.x = pt.x;
2558           event->configure.y = pt.y;
2559           event->configure.width = LOWORD (xevent->lParam);
2560           event->configure.height = HIWORD (xevent->lParam);
2561           window_private->x = event->configure.x;
2562           window_private->y = event->configure.y;
2563           window_private->width = event->configure.width;
2564           window_private->height = event->configure.height;
2565           if (window_private->resize_count > 1)
2566             window_private->resize_count -= 1;
2567           
2568           return_val = !window_private->destroyed;
2569           if (return_val
2570               && window_private->extension_events != 0
2571               && gdk_input_vtable.configure_event)
2572             gdk_input_vtable.configure_event (&event->configure, window);
2573         }
2574       break;
2575
2576     case WM_SIZING:
2577       GDK_NOTE (EVENTS, g_print ("WM_SIZING: %#x\n", xevent->hwnd));
2578       if (ret_val_flagp == NULL)
2579           g_warning ("ret_val_flagp is NULL but we got a WM_SIZING?");
2580       else if (window_private != NULL
2581                && window_private->hint_flags &
2582                (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE))
2583         {
2584           LPRECT lprc = (LPRECT) xevent->lParam;
2585
2586           if (window_private->hint_flags & GDK_HINT_MIN_SIZE)
2587             {
2588               gint w = lprc->right - lprc->left;
2589               gint h = lprc->bottom - lprc->top;
2590
2591               if (w < window_private->hint_min_width)
2592                 {
2593                   if (xevent->wParam == WMSZ_BOTTOMLEFT
2594                       || xevent->wParam == WMSZ_LEFT
2595                       || xevent->wParam == WMSZ_TOPLEFT)
2596                     lprc->left = lprc->right - window_private->hint_min_width;
2597                   else
2598                     lprc->right = lprc->left + window_private->hint_min_width;
2599                   *ret_val_flagp = TRUE;
2600                   *ret_valp = TRUE;
2601                 }
2602               if (h < window_private->hint_min_height)
2603                 {
2604                   if (xevent->wParam == WMSZ_BOTTOMLEFT
2605                       || xevent->wParam == WMSZ_BOTTOM
2606                       || xevent->wParam == WMSZ_BOTTOMRIGHT)
2607                     lprc->bottom = lprc->top + window_private->hint_min_height;
2608                   else
2609                     lprc->top = lprc->bottom - window_private->hint_min_height;
2610                   *ret_val_flagp = TRUE;
2611                   *ret_valp = TRUE;
2612                 }
2613             }
2614           if (window_private->hint_flags & GDK_HINT_MAX_SIZE)
2615             {
2616               gint w = lprc->right - lprc->left;
2617               gint h = lprc->bottom - lprc->top;
2618
2619               if (w > window_private->hint_max_width)
2620                 {
2621                   if (xevent->wParam == WMSZ_BOTTOMLEFT
2622                       || xevent->wParam == WMSZ_LEFT
2623                       || xevent->wParam == WMSZ_TOPLEFT)
2624                     lprc->left = lprc->right - window_private->hint_max_width;
2625                   else
2626                     lprc->right = lprc->left + window_private->hint_max_width;
2627                   *ret_val_flagp = TRUE;
2628                   *ret_valp = TRUE;
2629                 }
2630               if (h > window_private->hint_max_height)
2631                 {
2632                   if (xevent->wParam == WMSZ_BOTTOMLEFT
2633                       || xevent->wParam == WMSZ_BOTTOM
2634                       || xevent->wParam == WMSZ_BOTTOMRIGHT)
2635                     lprc->bottom = lprc->top + window_private->hint_max_height;
2636                   else
2637                     lprc->top = lprc->bottom - window_private->hint_max_height;
2638                   *ret_val_flagp = TRUE;
2639                   *ret_valp = TRUE;
2640                 }
2641             }
2642         }
2643       break;
2644
2645     case WM_MOVE:
2646       GDK_NOTE (EVENTS, g_print ("WM_MOVE: %#x  +%d+%d\n",
2647                                  xevent->hwnd,
2648                                  LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2649
2650       if (window_private
2651           && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2652         break;
2653       if (window_private != NULL
2654           && window_private->window_type != GDK_WINDOW_CHILD)
2655         {
2656           event->configure.type = GDK_CONFIGURE;
2657           event->configure.window = window;
2658           event->configure.x = LOWORD (xevent->lParam);
2659           event->configure.y = HIWORD (xevent->lParam);
2660           GetClientRect (xevent->hwnd, &rect);
2661           event->configure.width = rect.right;
2662           event->configure.height = rect.bottom;
2663           window_private->x = event->configure.x;
2664           window_private->y = event->configure.y;
2665           window_private->width = event->configure.width;
2666           window_private->height = event->configure.height;
2667           
2668           return_val = !window_private->destroyed;
2669         }
2670       break;
2671
2672     case WM_CLOSE:
2673       GDK_NOTE (EVENTS, g_print ("WM_CLOSE: %#x\n", xevent->hwnd));
2674       event->any.type = GDK_DELETE;
2675       event->any.window = window;
2676       
2677       return_val = window_private && !window_private->destroyed;
2678       break;
2679
2680 #if 0
2681     /* No, don't use delayed rendering after all. It works only if the
2682      * delayed SetClipboardData is called from the WindowProc, it
2683      * seems. (The #else part below is test code for that. It succeeds
2684      * in setting the clipboard data. But if I call SetClipboardData
2685      * in gdk_property_change (as a consequence of the
2686      * GDK_SELECTION_REQUEST event), it fails.  I deduce that this is
2687      * because delayed rendering requires that SetClipboardData is
2688      * called in the window procedure.)
2689      */
2690     case WM_RENDERFORMAT:
2691     case WM_RENDERALLFORMATS:
2692       flag = FALSE;
2693       GDK_NOTE (EVENTS, flag = TRUE);
2694       GDK_NOTE (SELECTION, flag = TRUE);
2695       if (flag)
2696         g_print ("WM_%s: %#x %#x (%s)\n",
2697                  (xevent->message == WM_RENDERFORMAT ? "RENDERFORMAT" :
2698                   "RENDERALLFORMATS"),
2699                  xevent->hwnd,
2700                  xevent->wParam,
2701                  (xevent->wParam == CF_TEXT ? "CF_TEXT" :
2702                   (xevent->wParam == CF_DIB ? "CF_DIB" :
2703                    (xevent->wParam == CF_UNICODETEXT ? "CF_UNICODETEXT" :
2704                     (GetClipboardFormatName (xevent->wParam, buf, sizeof (buf)), buf)))));
2705
2706 #if 0
2707       event->selection.type = GDK_SELECTION_REQUEST;
2708       event->selection.window = window;
2709       event->selection.selection = gdk_clipboard_atom;
2710       if (xevent->wParam == CF_TEXT)
2711         event->selection.target = GDK_TARGET_STRING;
2712       else
2713         {
2714           GetClipboardFormatName (xevent->wParam, buf, sizeof (buf));
2715           event->selection.target = gdk_atom_intern (buf, FALSE);
2716         }
2717       event->selection.property = gdk_selection_property;
2718       event->selection.requestor = (guint32) xevent->hwnd;
2719       event->selection.time = xevent->time;
2720       return_val = window_private && !window_private->destroyed;
2721 #else
2722       /* Test code, to see if SetClipboardData works when called from
2723        * the window procedure.
2724        */
2725       {
2726         HGLOBAL hdata = GlobalAlloc (GMEM_MOVEABLE|GMEM_DDESHARE, 10);
2727         char *ptr = GlobalLock (hdata);
2728         strcpy (ptr, "Huhhaa");
2729         GlobalUnlock (hdata);
2730         if (!SetClipboardData (CF_TEXT, hdata))
2731           g_print ("SetClipboardData failed: %d\n", GetLastError ());
2732       }
2733       *ret_valp = 0;
2734       *ret_val_flagp = TRUE;
2735       return_val = FALSE;
2736 #endif
2737       break;
2738 #endif /* No delayed rendering */
2739
2740     case WM_DESTROY:
2741       GDK_NOTE (EVENTS, g_print ("WM_DESTROY: %#x\n", xevent->hwnd));
2742       event->any.type = GDK_DESTROY;
2743       event->any.window = window;
2744       if (window != NULL && window == curWnd)
2745         {
2746           gdk_window_unref (curWnd);
2747           curWnd = NULL;
2748         }
2749
2750       if (p_grab_window == window_private)
2751         gdk_pointer_ungrab (xevent->time);
2752
2753       if (k_grab_window == window_private)
2754         gdk_keyboard_ungrab (xevent->time);
2755
2756       return_val = window_private && !window_private->destroyed;
2757       break;
2758
2759       /* Handle WINTAB events here, as we know that gdkinput.c will
2760        * use the fixed WT_DEFBASE as lcMsgBase, and we thus can use the
2761        * constants as case labels.
2762        */
2763     case WT_PACKET:
2764       GDK_NOTE (EVENTS, g_print ("WT_PACKET: %d %#x\n",
2765                                  xevent->wParam, xevent->lParam));
2766       goto wintab;
2767       
2768     case WT_CSRCHANGE:
2769       GDK_NOTE (EVENTS, g_print ("WT_CSRCHANGE: %d %#x\n",
2770                                  xevent->wParam, xevent->lParam));
2771       goto wintab;
2772       
2773     case WT_PROXIMITY:
2774       GDK_NOTE (EVENTS,
2775                 g_print ("WT_PROXIMITY: %#x %d %d\n",
2776                          xevent->wParam,
2777                          LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2778     wintab:
2779       return_val = gdk_input_vtable.other_event(event, xevent);
2780       break;
2781     }
2782
2783 bypass_switch:
2784
2785   if (return_val)
2786     {
2787       if (event->any.window)
2788         gdk_window_ref (event->any.window);
2789       if (((event->any.type == GDK_ENTER_NOTIFY) ||
2790            (event->any.type == GDK_LEAVE_NOTIFY)) &&
2791           (event->crossing.subwindow != NULL))
2792         gdk_window_ref (event->crossing.subwindow);
2793     }
2794   else
2795     {
2796       /* Mark this event as having no resources to be freed */
2797       event->any.window = NULL;
2798       event->any.type = GDK_NOTHING;
2799     }
2800
2801   if (window)
2802     gdk_window_unref (window);
2803   
2804   return return_val;
2805 }
2806
2807 static void
2808 gdk_events_queue (void)
2809 {
2810   GList *node;
2811   GdkEvent *event;
2812   MSG msg;
2813
2814   GDK_NOTE (EVENTS, g_print ("gdk_events_queue: %s\n",
2815                              (queued_events ? "yes" : "none")));
2816
2817   while (!gdk_event_queue_find_first()
2818          && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
2819     {
2820       GDK_NOTE (EVENTS, g_print ("gdk_events_queue: got event\n"));
2821       TranslateMessage (&msg);
2822
2823       event = gdk_event_new ();
2824       
2825       event->any.type = GDK_NOTHING;
2826       event->any.window = NULL;
2827       event->any.send_event = FALSE;
2828
2829       ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
2830
2831       gdk_event_queue_append (event);
2832       node = queued_tail;
2833
2834       if (gdk_event_translate (event, &msg, NULL, NULL))
2835           ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
2836       else
2837         {
2838           DefWindowProc (msg.hwnd, msg.message, msg.wParam, msg.lParam);
2839           gdk_event_queue_remove_link (node);
2840           g_list_free_1 (node);
2841           gdk_event_free (event);
2842         }
2843     }
2844 }
2845
2846 static gboolean  
2847 gdk_event_prepare (gpointer  source_data, 
2848                    GTimeVal *current_time,
2849                    gint     *timeout)
2850 {
2851   MSG msg;
2852   gboolean retval;
2853   
2854   GDK_THREADS_ENTER ();
2855
2856   *timeout = -1;
2857
2858   GDK_NOTE (EVENTS, g_print ("gdk_event_prepare\n"));
2859
2860   retval = (gdk_event_queue_find_first () != NULL)
2861               || PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
2862
2863   GDK_THREADS_LEAVE ();
2864
2865   return retval;
2866 }
2867
2868 static gboolean  
2869 gdk_event_check (gpointer  source_data,
2870                  GTimeVal *current_time)
2871 {
2872   MSG msg;
2873   gboolean retval;
2874   
2875   GDK_NOTE (EVENTS, g_print ("gdk_event_check\n"));
2876
2877   GDK_THREADS_ENTER ();
2878
2879   if (event_poll_fd.revents & G_IO_IN)
2880     retval = (gdk_event_queue_find_first () != NULL)
2881               || PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
2882   else
2883     retval = FALSE;
2884
2885   GDK_THREADS_LEAVE ();
2886
2887   return retval;
2888 }
2889
2890 static GdkEvent*
2891 gdk_event_unqueue (void)
2892 {
2893   GdkEvent *event = NULL;
2894   GList *tmp_list;
2895
2896   tmp_list = gdk_event_queue_find_first ();
2897
2898   if (tmp_list)
2899     {
2900       event = tmp_list->data;
2901       gdk_event_queue_remove_link (tmp_list);
2902       g_list_free_1 (tmp_list);
2903     }
2904
2905   return event;
2906 }
2907
2908 static gboolean  
2909 gdk_event_dispatch (gpointer  source_data,
2910                     GTimeVal *current_time,
2911                     gpointer  user_data)
2912 {
2913   GdkEvent *event;
2914  
2915   GDK_NOTE (EVENTS, g_print ("gdk_event_dispatch\n"));
2916
2917   GDK_THREADS_ENTER ();
2918
2919   gdk_events_queue();
2920   event = gdk_event_unqueue();
2921
2922   if (event)
2923     {
2924       if (event_func)
2925         (*event_func) (event, event_data);
2926       
2927       gdk_event_free (event);
2928     }
2929   
2930   GDK_THREADS_LEAVE ();
2931
2932   return TRUE;
2933 }
2934
2935 static void
2936 gdk_synthesize_click (GdkEvent *event,
2937                       gint      nclicks)
2938 {
2939   GdkEvent temp_event;
2940   
2941   g_return_if_fail (event != NULL);
2942   
2943   temp_event = *event;
2944   temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
2945   
2946   gdk_event_put (&temp_event);
2947 }
2948
2949 /* Sends a ClientMessage to all toplevel client windows */
2950 gboolean
2951 gdk_event_send_client_message (GdkEvent *event, guint32 xid)
2952 {
2953   /* XXX */
2954   return FALSE;
2955 }
2956
2957 void
2958 gdk_event_send_clientmessage_toall (GdkEvent *event)
2959 {
2960   /* XXX */
2961 }
2962