]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkevents-win32.c
Handle Control-digits specially.
[~andy/gtk] / gdk / win32 / gdkevents-win32.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, g_print ("...propagating to %#x\n",
1384                                          window_private->xwindow));
1385               goto keyup_or_down;
1386             }
1387         }
1388               
1389       switch (xevent->wParam)
1390         {
1391         case VK_LBUTTON:
1392           event->key.keyval = GDK_Pointer_Button1; break;
1393         case VK_RBUTTON:
1394           event->key.keyval = GDK_Pointer_Button3; break;
1395         case VK_MBUTTON:
1396           event->key.keyval = GDK_Pointer_Button2; break;
1397         case VK_CANCEL:
1398           event->key.keyval = GDK_Cancel; break;
1399         case VK_BACK:
1400           event->key.keyval = GDK_BackSpace; break;
1401         case VK_TAB:
1402           event->key.keyval = GDK_Tab; break;
1403         case VK_CLEAR:
1404           event->key.keyval = GDK_Clear; break;
1405         case VK_RETURN:
1406           event->key.keyval = GDK_Return; break;
1407         case VK_SHIFT:
1408           event->key.keyval = GDK_Shift_L; break;
1409         case VK_CONTROL:
1410           if (xevent->lParam & 0x01000000)
1411             event->key.keyval = GDK_Control_R;
1412           else
1413             event->key.keyval = GDK_Control_L;
1414           break;
1415         case VK_MENU:
1416           if (xevent->lParam & 0x01000000)
1417             {
1418               /* AltGr key comes in as Control+Right Alt */
1419               if (GetKeyState (VK_CONTROL) < 0)
1420                 {
1421                   ignore_WM_CHAR = FALSE;
1422                   is_AltGr_key = TRUE;
1423                 }
1424               event->key.keyval = GDK_Alt_R;
1425             }
1426           else
1427             event->key.keyval = GDK_Alt_L;
1428           break;
1429         case VK_PAUSE:
1430           event->key.keyval = GDK_Pause; break;
1431         case VK_CAPITAL:
1432           event->key.keyval = GDK_Caps_Lock; break;
1433         case VK_ESCAPE:
1434           event->key.keyval = GDK_Escape; break;
1435         case VK_PRIOR:
1436           event->key.keyval = GDK_Prior; break;
1437         case VK_NEXT:
1438           event->key.keyval = GDK_Next; break;
1439         case VK_END:
1440           event->key.keyval = GDK_End; break;
1441         case VK_HOME:
1442           event->key.keyval = GDK_Home; break;
1443         case VK_LEFT:
1444           event->key.keyval = GDK_Left; break;
1445         case VK_UP:
1446           event->key.keyval = GDK_Up; break;
1447         case VK_RIGHT:
1448           event->key.keyval = GDK_Right; break;
1449         case VK_DOWN:
1450           event->key.keyval = GDK_Down; break;
1451         case VK_SELECT:
1452           event->key.keyval = GDK_Select; break;
1453         case VK_PRINT:
1454           event->key.keyval = GDK_Print; break;
1455         case VK_EXECUTE:
1456           event->key.keyval = GDK_Execute; break;
1457         case VK_INSERT:
1458           event->key.keyval = GDK_Insert; break;
1459         case VK_DELETE:
1460           event->key.keyval = GDK_Delete; break;
1461         case VK_HELP:
1462           event->key.keyval = GDK_Help; break;
1463         case VK_NUMPAD0:
1464         case VK_NUMPAD1:
1465         case VK_NUMPAD2:
1466         case VK_NUMPAD3:
1467         case VK_NUMPAD4:
1468         case VK_NUMPAD5:
1469         case VK_NUMPAD6:
1470         case VK_NUMPAD7:
1471         case VK_NUMPAD8:
1472         case VK_NUMPAD9:
1473           /* Apparently applications work better if we just pass numpad digits
1474            * on as real digits? So wait for the WM_CHAR instead.
1475            */
1476           ignore_WM_CHAR = FALSE;
1477           break;
1478         case VK_MULTIPLY:
1479           event->key.keyval = GDK_KP_Multiply; break;
1480         case VK_ADD:
1481           event->key.keyval = GDK_KP_Add; break;
1482         case VK_SEPARATOR:
1483           event->key.keyval = GDK_KP_Separator; break;
1484         case VK_SUBTRACT:
1485           event->key.keyval = GDK_KP_Subtract; break;
1486         case VK_DECIMAL:
1487 #if 0
1488           event->key.keyval = GDK_KP_Decimal; break;
1489 #else
1490           /* The keypad decimal key should also be passed on as the decimal
1491            * sign ('.' or ',' depending on the Windows locale settings,
1492            * apparently). So wait for the WM_CHAR here, also.
1493            */
1494           ignore_WM_CHAR = FALSE;
1495           break;
1496 #endif
1497         case VK_DIVIDE:
1498           event->key.keyval = GDK_KP_Divide; break;
1499         case VK_F1:
1500           event->key.keyval = GDK_F1; break;
1501         case VK_F2:
1502           event->key.keyval = GDK_F2; break;
1503         case VK_F3:
1504           event->key.keyval = GDK_F3; break;
1505         case VK_F4:
1506           event->key.keyval = GDK_F4; break;
1507         case VK_F5:
1508           event->key.keyval = GDK_F5; break;
1509         case VK_F6:
1510           event->key.keyval = GDK_F6; break;
1511         case VK_F7:
1512           event->key.keyval = GDK_F7; break;
1513         case VK_F8:
1514           event->key.keyval = GDK_F8; break;
1515         case VK_F9:
1516           event->key.keyval = GDK_F9; break;
1517         case VK_F10:
1518           event->key.keyval = GDK_F10; break;
1519         case VK_F11:
1520           event->key.keyval = GDK_F11; break;
1521         case VK_F12:
1522           event->key.keyval = GDK_F12; break;
1523         case VK_F13:
1524           event->key.keyval = GDK_F13; break;
1525         case VK_F14:
1526           event->key.keyval = GDK_F14; break;
1527         case VK_F15:
1528           event->key.keyval = GDK_F15; break;
1529         case VK_F16:
1530           event->key.keyval = GDK_F16; break;
1531         case '0':
1532         case '1':
1533         case '2':
1534         case '3':
1535         case '4':
1536         case '5':
1537         case '6':
1538         case '7':
1539         case '8':
1540         case '9':
1541           if (GetKeyState (VK_CONTROL) < 0)
1542             /* Control-digits won't come in as a WM_CHAR */
1543             event->key.keyval = GDK_0 + (xevent->wParam - '0');
1544           else
1545             {
1546               ignore_WM_CHAR = FALSE;
1547               event->key.keyval = GDK_VoidSymbol;
1548             }
1549           break;
1550         default:
1551           if (xevent->message == WM_SYSKEYDOWN || xevent->message == WM_SYSKEYUP)
1552             {
1553               event->key.keyval = xevent->wParam;
1554             }
1555           else
1556             {
1557               ignore_WM_CHAR = FALSE;
1558               event->key.keyval = GDK_VoidSymbol;
1559             }
1560           break;
1561         }
1562
1563       if (!ignore_WM_CHAR)
1564         break;
1565
1566       is_AltGr_key = FALSE;
1567       event->key.type = ((xevent->message == WM_KEYDOWN
1568                           || xevent->message == WM_SYSKEYDOWN) ?
1569                          GDK_KEY_PRESS : GDK_KEY_RELEASE);
1570       event->key.window = window;
1571       event->key.time = xevent->time;
1572       event->key.state = 0;
1573       if (GetKeyState (VK_SHIFT) < 0)
1574         event->key.state |= GDK_SHIFT_MASK;
1575       if (GetKeyState (VK_CAPITAL) & 0x1)
1576         event->key.state |= GDK_LOCK_MASK;
1577       if (GetKeyState (VK_CONTROL) < 0)
1578         event->key.state |= GDK_CONTROL_MASK;
1579       if (xevent->wParam != VK_MENU && GetKeyState (VK_MENU) < 0)
1580         event->key.state |= GDK_MOD1_MASK;
1581       event->key.length = 0;
1582       return_val = window_private && !window_private->destroyed;
1583       event->key.string = NULL;
1584       break;
1585
1586     case WM_CHAR:
1587       GDK_NOTE (EVENTS, 
1588                 g_print ("WM_CHAR: %#x  char: %#x %#.08x  %s\n",
1589                          xevent->hwnd,
1590                          xevent->wParam,
1591                          xevent->lParam,
1592                          (ignore_WM_CHAR ? "ignored" : "")));
1593
1594       if (ignore_WM_CHAR)
1595         {
1596           ignore_WM_CHAR = FALSE;
1597           break;
1598         }
1599
1600     wm_char:
1601       /* This doesn't handle the rather theorethical case that a window
1602        * wants key presses but still wants releases to be propagated,
1603        * for instance.
1604        */
1605       if (k_grab_window != NULL
1606           && !k_grab_owner_events)
1607         {
1608           /* Keyboard is grabbed with owner_events FALSE */
1609           GDK_NOTE (EVENTS,
1610                     g_print ("...grabbed, owner_events FALSE, "
1611                              "sending to %#x\n", k_grab_window->xwindow));
1612           event->key.window = (GdkWindow *) k_grab_window;
1613         }
1614       else if (window_private
1615                && !(window_private->event_mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK)))
1616         {
1617           /* Owner window doesn't want it */
1618           if (k_grab_window != NULL
1619               && k_grab_owner_events)
1620             {
1621               /* Keyboard is grabbed with owner_events TRUE */
1622               GDK_NOTE (EVENTS,
1623                         g_print ("...grabbed, owner_events TRUE, doesn't want it, "
1624                                  "sending to %#x\n", k_grab_window->xwindow));
1625               event->key.window = (GdkWindow *) k_grab_window;
1626             }
1627           else
1628             {
1629               /* Owner doesn't want it, neither is it grabbed, so
1630                * propagate to parent.
1631                */
1632               if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1633                 g_assert_not_reached (); /* Should've been handled above */
1634
1635               gdk_window_unref (window);
1636               window = window_private->parent;
1637               gdk_window_ref (window);
1638               window_private = (GdkWindowPrivate *) window;
1639               GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
1640                                          window_private->xwindow));
1641               goto wm_char;
1642             }
1643         }
1644       
1645       return_val = window_private && !window_private->destroyed;
1646       if (return_val && (window_private->event_mask & GDK_KEY_RELEASE_MASK))
1647         {
1648           /* Return the release event, and maybe append the press
1649            * event to the queued_events list (from which it will vbe
1650            * fetched before the release event).
1651            */
1652           event->key.type = GDK_KEY_RELEASE;
1653           event->key.keyval = xevent->wParam;
1654           event->key.window = window;
1655           event->key.time = xevent->time;
1656           event->key.state = 0;
1657           if (GetKeyState (VK_SHIFT) < 0)
1658             event->key.state |= GDK_SHIFT_MASK;
1659           if (GetKeyState (VK_CAPITAL) & 0x1)
1660             event->key.state |= GDK_LOCK_MASK;
1661           if (is_AltGr_key)
1662             ;
1663           else if (GetKeyState (VK_CONTROL) < 0)
1664             {
1665               event->key.state |= GDK_CONTROL_MASK;
1666               if (event->key.keyval < ' ')
1667                 event->key.keyval += '@';
1668             }
1669           else if (event->key.keyval < ' ')
1670             {
1671               event->key.state |= GDK_CONTROL_MASK;
1672               event->key.keyval += '@';
1673             }
1674           if (!is_AltGr_key && GetKeyState (VK_MENU) < 0)
1675             event->key.state |= GDK_MOD1_MASK;
1676           event->key.string = g_strdup (" ");
1677           event->key.length = 1;
1678           event->key.string[0] = xevent->wParam; /* ??? */
1679
1680           if (window_private->event_mask & GDK_KEY_PRESS_MASK)
1681             {
1682               /* Append also a GDK_KEY_PRESS event to the pushback list.  */
1683               GdkEvent *event2 = gdk_event_copy (event);
1684               event2->key.type = GDK_KEY_PRESS;
1685               charcount = xevent->lParam & 0xFFFF;
1686               if (charcount > sizeof (buf)- 1)
1687                 charcount = sizeof (buf) - 1;
1688               g_free (event2->key.string);
1689               event2->key.string = g_malloc (charcount);
1690               for (i = 0; i < charcount; i++)
1691                 event2->key.string[i] = event->key.keyval;
1692               event2->key.length = charcount;
1693
1694               gdk_event_queue_append (event2);
1695             }
1696         }
1697       else if (return_val && (window_private->event_mask & GDK_KEY_PRESS_MASK))
1698         {
1699           /* Return just the GDK_KEY_PRESS event. */
1700           event->key.type = GDK_KEY_PRESS;
1701           charcount = xevent->lParam & 0xFFFF;
1702           if (charcount > sizeof (buf)- 1)
1703             charcount = sizeof (buf) - 1;
1704           event->key.keyval = xevent->wParam;
1705           event->key.window = window;
1706           event->key.time = xevent->time;
1707           event->key.state = 0;
1708           if (GetKeyState (VK_SHIFT) < 0)
1709             event->key.state |= GDK_SHIFT_MASK;
1710           if (GetKeyState (VK_CAPITAL) & 0x1)
1711             event->key.state |= GDK_LOCK_MASK;
1712           if (is_AltGr_key)
1713             ;
1714           else if (GetKeyState (VK_CONTROL) < 0)
1715             {
1716               event->key.state |= GDK_CONTROL_MASK;
1717               if (event->key.keyval < ' ')
1718                 event->key.keyval += '@';
1719             }
1720           else if (event->key.keyval < ' ')
1721             {
1722               event->key.state |= GDK_CONTROL_MASK;
1723               event->key.keyval += '@';
1724             }
1725           if (!is_AltGr_key && GetKeyState (VK_MENU) < 0)
1726             event->key.state |= GDK_MOD1_MASK;
1727           event->key.string = g_malloc (charcount);
1728           for (i = 0; i < charcount; i++)
1729             event->key.string[i] = event->key.keyval;
1730           event->key.length = charcount;
1731         }
1732       else
1733         return_val = FALSE;
1734       is_AltGr_key = FALSE;
1735       break;
1736
1737     case WM_LBUTTONDOWN:
1738       button = 1;
1739       goto buttondown0;
1740     case WM_MBUTTONDOWN:
1741       button = 2;
1742       goto buttondown0;
1743     case WM_RBUTTONDOWN:
1744       button = 3;
1745
1746     buttondown0:
1747       GDK_NOTE (EVENTS, 
1748                 g_print ("WM_%cBUTTONDOWN: %#x  x,y: %d %d  button: %d\n",
1749                          " LMR"[button],
1750                          xevent->hwnd,
1751                          LOWORD (xevent->lParam), HIWORD (xevent->lParam),
1752                          button));
1753
1754       if (window_private
1755           && (window_private->extension_events != 0)
1756           && gdk_input_ignore_core)
1757         {
1758           GDK_NOTE (EVENTS, g_print ("...ignored\n"));
1759           break;
1760         }
1761
1762       event->button.type = GDK_BUTTON_PRESS;
1763     buttondown:
1764       event->button.window = window;
1765       if (window_private)
1766         mask = window_private->event_mask;
1767       else
1768         mask = 0;               /* ??? */
1769
1770       if (p_grab_window != NULL
1771            && !p_grab_owner_events)
1772         {
1773           /* Pointer is grabbed with owner_events FALSE */
1774           GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE\n"));
1775           mask = p_grab_event_mask;
1776           if (!(mask & GDK_BUTTON_PRESS_MASK))
1777             /* Grabber doesn't want it */
1778             break;
1779           else
1780             event->button.window = (GdkWindow *) p_grab_window;
1781           GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
1782                                      p_grab_window->xwindow));
1783         }
1784       else if (window_private
1785                && !(mask & GDK_BUTTON_PRESS_MASK))
1786         {
1787           /* Owner window doesn't want it */
1788           if (p_grab_window != NULL
1789               && p_grab_owner_events)
1790             {
1791               /* Pointer is grabbed wíth owner_events TRUE */ 
1792               GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
1793               mask = p_grab_event_mask;
1794               if (!(mask & GDK_BUTTON_PRESS_MASK))
1795                 /* Grabber doesn't want it either */
1796                 break;
1797               else
1798                 event->button.window = (GdkWindow *) p_grab_window;
1799               GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
1800                                          p_grab_window->xwindow));
1801             }
1802           else
1803             {
1804               /* Owner doesn't want it, neither is it grabbed, so
1805                * propagate to parent.
1806                */
1807               /* Yes, this code is duplicated twice below. So shoot me. */
1808               if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1809                 break;
1810               pt.x = LOWORD (xevent->lParam);
1811               pt.y = HIWORD (xevent->lParam);
1812               ClientToScreen (window_private->xwindow, &pt);
1813               gdk_window_unref (window);
1814               window = window_private->parent;
1815               gdk_window_ref (window);
1816               window_private = (GdkWindowPrivate *) window;
1817               ScreenToClient (window_private->xwindow, &pt);
1818               xevent->lParam = MAKELPARAM (pt.x, pt.y);
1819               GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
1820                                          window_private->xwindow));
1821               goto buttondown; /* What did Dijkstra say? */
1822             }
1823         }
1824
1825       /* Emulate X11's automatic active grab */
1826       if (!p_grab_window)
1827         {
1828           /* No explicit active grab, let's start one automatically */
1829           GDK_NOTE (EVENTS, g_print ("...automatic grab started\n"));
1830           gdk_pointer_grab (window, TRUE, window_private->event_mask,
1831                             NULL, NULL, 0);
1832           p_grab_automatic = TRUE;
1833         }
1834
1835       if (window != curWnd)
1836         synthesize_crossing_events (window, xevent);
1837
1838       event->button.time = xevent->time;
1839       event->button.x = LOWORD (xevent->lParam);
1840       event->button.y = HIWORD (xevent->lParam);
1841       event->button.x_root = (gfloat)xevent->pt.x;
1842       event->button.y_root = (gfloat)xevent->pt.y;
1843       event->button.pressure = 0.5;
1844       event->button.xtilt = 0;
1845       event->button.ytilt = 0;
1846       event->button.state = 0;
1847       if (xevent->wParam & MK_CONTROL)
1848         event->button.state |= GDK_CONTROL_MASK;
1849       if (xevent->wParam & MK_LBUTTON)
1850         event->button.state |= GDK_BUTTON1_MASK;
1851       if (xevent->wParam & MK_MBUTTON)
1852         event->button.state |= GDK_BUTTON2_MASK;
1853       if (xevent->wParam & MK_RBUTTON)
1854         event->button.state |= GDK_BUTTON3_MASK;
1855       if (xevent->wParam & MK_SHIFT)
1856         event->button.state |= GDK_SHIFT_MASK;
1857       if (GetKeyState (VK_MENU) < 0)
1858         event->button.state |= GDK_MOD1_MASK;
1859       if (GetKeyState (VK_CAPITAL) & 0x1)
1860         event->button.state |= GDK_LOCK_MASK;
1861       event->button.button = button;
1862       event->button.source = GDK_SOURCE_MOUSE;
1863       event->button.deviceid = GDK_CORE_POINTER;
1864
1865       if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1866           (event->button.window == button_window[1]) &&
1867           (event->button.button == button_number[1]))
1868         {
1869           gdk_synthesize_click (event, 3);
1870
1871           button_click_time[1] = 0;
1872           button_click_time[0] = 0;
1873           button_window[1] = NULL;
1874           button_window[0] = 0;
1875           button_number[1] = -1;
1876           button_number[0] = -1;
1877         }
1878       else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1879                (event->button.window == button_window[0]) &&
1880                (event->button.button == button_number[0]))
1881         {
1882           gdk_synthesize_click (event, 2);
1883
1884           button_click_time[1] = button_click_time[0];
1885           button_click_time[0] = event->button.time;
1886           button_window[1] = button_window[0];
1887           button_window[0] = event->button.window;
1888           button_number[1] = button_number[0];
1889           button_number[0] = event->button.button;
1890         }
1891       else
1892         {
1893           button_click_time[1] = 0;
1894           button_click_time[0] = event->button.time;
1895           button_window[1] = NULL;
1896           button_window[0] = event->button.window;
1897           button_number[1] = -1;
1898           button_number[0] = event->button.button;
1899         }
1900       return_val = window_private && !window_private->destroyed;
1901       if (return_val
1902           && p_grab_window != NULL
1903           && event->any.window == (GdkWindow *) p_grab_window
1904           && p_grab_window != window_private)
1905         {
1906           /* Translate coordinates to grabber */
1907           pt.x = event->button.x;
1908           pt.y = event->button.y;
1909           ClientToScreen (window_private->xwindow, &pt);
1910           ScreenToClient (p_grab_window->xwindow, &pt);
1911           event->button.x = pt.x;
1912           event->button.y = pt.y;
1913           GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
1914         }
1915       break;
1916
1917     case WM_LBUTTONUP:
1918       button = 1;
1919       goto buttonup0;
1920     case WM_MBUTTONUP:
1921       button = 2;
1922       goto buttonup0;
1923     case WM_RBUTTONUP:
1924       button = 3;
1925
1926     buttonup0:
1927       GDK_NOTE (EVENTS, 
1928                 g_print ("WM_%cBUTTONUP: %#x  x,y: %d %d  button: %d\n",
1929                          " LMR"[button],
1930                          xevent->hwnd,
1931                          LOWORD (xevent->lParam), HIWORD (xevent->lParam),
1932                          button));
1933
1934       if (window_private
1935           && (window_private->extension_events != 0)
1936           && gdk_input_ignore_core)
1937         {
1938           GDK_NOTE (EVENTS, g_print ("...ignored\n"));
1939           break;
1940         }
1941
1942       event->button.type = GDK_BUTTON_RELEASE;
1943     buttonup:
1944       event->button.window = window;
1945       if (window_private)
1946         mask = window_private->event_mask;
1947       else
1948         mask = 0;
1949
1950       if (p_grab_window != NULL
1951            && !p_grab_owner_events)
1952         {
1953           /* Pointer is grabbed with owner_events FALSE */
1954           GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE\n"));
1955           mask = p_grab_event_mask;
1956           if (!(mask & GDK_BUTTON_RELEASE_MASK))
1957             /* Grabber doesn't want it */
1958             break;
1959           else
1960             event->button.window = (GdkWindow *) p_grab_window;
1961           GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
1962                                      p_grab_window->xwindow));
1963         }
1964       else if (window_private
1965                && !(mask & GDK_BUTTON_RELEASE_MASK))
1966         {
1967           /* Owner window doesn't want it */
1968           if (p_grab_window != NULL
1969               && p_grab_owner_events)
1970             {
1971               /* Pointer is grabbed wíth owner_events TRUE */
1972               GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
1973               mask = p_grab_event_mask;
1974               if (!(mask & GDK_BUTTON_RELEASE_MASK))
1975                 /* Grabber doesn't want it */
1976                 break;
1977               else
1978                 event->button.window = (GdkWindow *) p_grab_window;
1979               GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
1980                                          p_grab_window->xwindow));
1981             }
1982           else
1983             {
1984               /* Owner doesn't want it, neither is it grabbed, so
1985                * propagate to parent.
1986                */
1987               if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1988                 break;
1989               pt.x = LOWORD (xevent->lParam);
1990               pt.y = HIWORD (xevent->lParam);
1991               ClientToScreen (window_private->xwindow, &pt);
1992               gdk_window_unref (window);
1993               window = window_private->parent;
1994               gdk_window_ref (window);
1995               window_private = (GdkWindowPrivate *) window;
1996               ScreenToClient (window_private->xwindow, &pt);
1997               xevent->lParam = MAKELPARAM (pt.x, pt.y);
1998               GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
1999                                          window_private->xwindow));
2000               goto buttonup;
2001             }
2002         }
2003
2004       if (window != curWnd)
2005         synthesize_crossing_events (window, xevent);
2006
2007       event->button.time = xevent->time;
2008       event->button.x = LOWORD (xevent->lParam);
2009       event->button.y = HIWORD (xevent->lParam);
2010       event->button.x_root = (gfloat)xevent->pt.x;
2011       event->button.y_root = (gfloat)xevent->pt.y;
2012       event->button.pressure = 0.5;
2013       event->button.xtilt = 0;
2014       event->button.ytilt = 0;
2015       event->button.state = 0;
2016       if (xevent->wParam & MK_CONTROL)
2017         event->button.state |= GDK_CONTROL_MASK;
2018       if (xevent->wParam & MK_LBUTTON)
2019         event->button.state |= GDK_BUTTON1_MASK;
2020       if (xevent->wParam & MK_MBUTTON)
2021         event->button.state |= GDK_BUTTON2_MASK;
2022       if (xevent->wParam & MK_RBUTTON)
2023         event->button.state |= GDK_BUTTON3_MASK;
2024       if (xevent->wParam & MK_SHIFT)
2025         event->button.state |= GDK_SHIFT_MASK;
2026       event->button.button = button;
2027       event->button.source = GDK_SOURCE_MOUSE;
2028       event->button.deviceid = GDK_CORE_POINTER;
2029       return_val = window_private && !window_private->destroyed;
2030       if (return_val
2031           && p_grab_window != NULL
2032           && event->any.window == (GdkWindow *) p_grab_window
2033           && p_grab_window != window_private)
2034         {
2035           /* Translate coordinates to grabber */
2036           pt.x = event->button.x;
2037           pt.y = event->button.y;
2038           ClientToScreen (window_private->xwindow, &pt);
2039           ScreenToClient (p_grab_window->xwindow, &pt);
2040           event->button.x = pt.x;
2041           event->button.y = pt.y;
2042           GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
2043         }
2044       if (p_grab_window != NULL
2045           && p_grab_automatic
2046           && (event->button.state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) == 0)
2047         gdk_pointer_ungrab (0);
2048       break;
2049
2050     case WM_MOUSEMOVE:
2051       GDK_NOTE (EVENTS,
2052                 g_print ("WM_MOUSEMOVE: %#x  %#x +%d+%d\n",
2053                          xevent->hwnd, xevent->wParam,
2054                          LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2055
2056 #if 0
2057       /* Try hard not to generate events for windows that shouldn't
2058          get any.  This is hard because we don't want pushbuttons to
2059          highlight when the cursor moves over them if the window is
2060          inactive. We dont want tooltips windows to be active. OTOH,
2061          also menus are popup windows, but they definitely should
2062          get events. Aw shit. Skip this.
2063        */
2064       dwStyle = GetWindowLong (xevent->hwnd, GWL_STYLE);
2065       if (active == NULL ||
2066           !(active == xevent->hwnd
2067             || (dwStyle & WS_POPUP)
2068             || IsChild (active, xevent->hwnd)))
2069         break;
2070 #else
2071       { /* HB: only process mouse move messages
2072          * if we own the active window.
2073          */
2074           DWORD ProcessID_ActWin;
2075           DWORD ProcessID_this;
2076
2077           GetWindowThreadProcessId(GetActiveWindow(), &ProcessID_ActWin);
2078           GetWindowThreadProcessId(xevent->hwnd, &ProcessID_this);
2079           if (ProcessID_ActWin != ProcessID_this)
2080           break;
2081      }
2082 #endif
2083       if (window != curWnd)
2084         synthesize_crossing_events (window, xevent);
2085
2086       if (window_private
2087           && (window_private->extension_events != 0)
2088           && gdk_input_ignore_core)
2089         {
2090           GDK_NOTE (EVENTS, g_print ("...ignored\n"));
2091           break;
2092         }
2093
2094     mousemotion:
2095       event->motion.type = GDK_MOTION_NOTIFY;
2096       event->motion.window = window;
2097       if (window_private)
2098         mask = window_private->event_mask;
2099       else
2100         mask = 0;
2101
2102       if (p_grab_window
2103           && !p_grab_owner_events)
2104         {
2105           /* Pointer is grabbed with owner_events FALSE */
2106           GDK_NOTE (EVENTS,
2107                     g_print ("...grabbed, owner_events FALSE\n"));
2108           mask = p_grab_event_mask;
2109           if (!((mask & GDK_POINTER_MOTION_MASK)
2110                 || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
2111                     && (mask & GDK_BUTTON_MOTION_MASK))
2112                 || ((xevent->wParam & MK_LBUTTON)
2113                     && (mask & GDK_BUTTON1_MOTION_MASK))
2114                 || ((xevent->wParam & MK_MBUTTON)
2115                     && (mask & GDK_BUTTON2_MOTION_MASK))
2116                 || ((xevent->wParam & MK_RBUTTON)
2117                     && (mask & GDK_BUTTON3_MOTION_MASK))))
2118             break;
2119           else
2120             event->motion.window = (GdkWindow *) p_grab_window;
2121           GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
2122                                      p_grab_window->xwindow));
2123         }
2124       else if (window_private
2125                && !((mask & GDK_POINTER_MOTION_MASK)
2126                     || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
2127                         && (mask & GDK_BUTTON_MOTION_MASK))
2128                     || ((xevent->wParam & MK_LBUTTON)
2129                         && (mask & GDK_BUTTON1_MOTION_MASK))
2130                     || ((xevent->wParam & MK_MBUTTON)
2131                         && (mask & GDK_BUTTON2_MOTION_MASK))
2132                     || ((xevent->wParam & MK_RBUTTON)
2133                         && (mask & GDK_BUTTON3_MOTION_MASK))))
2134         {
2135           /* Owner window doesn't want it */
2136           if (p_grab_window != NULL
2137               && p_grab_owner_events)
2138             {
2139               /* Pointer is grabbed wíth owner_events TRUE */
2140               GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
2141               mask = p_grab_event_mask;
2142               if (!((p_grab_event_mask & GDK_POINTER_MOTION_MASK)
2143                     || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
2144                         && (mask & GDK_BUTTON_MOTION_MASK))
2145                     || ((xevent->wParam & MK_LBUTTON)
2146                         && (mask & GDK_BUTTON1_MOTION_MASK))
2147                     || ((xevent->wParam & MK_MBUTTON)
2148                         && (mask & GDK_BUTTON2_MOTION_MASK))
2149                     || ((xevent->wParam & MK_RBUTTON)
2150                         && (mask & GDK_BUTTON3_MOTION_MASK))))
2151                 /* Grabber doesn't want it either */
2152                 break;
2153               else
2154                 event->motion.window = (GdkWindow *) p_grab_window;
2155               GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
2156                                          p_grab_window->xwindow));
2157             }
2158           else
2159             {
2160               /* Owner doesn't want it, neither is it grabbed, so
2161                * propagate to parent.
2162                */
2163               if (window_private->parent == (GdkWindow *) &gdk_root_parent)
2164                 break;
2165               pt.x = LOWORD (xevent->lParam);
2166               pt.y = HIWORD (xevent->lParam);
2167               ClientToScreen (window_private->xwindow, &pt);
2168               gdk_window_unref (window);
2169               window = window_private->parent;
2170               gdk_window_ref (window);
2171               window_private = (GdkWindowPrivate *) window;
2172               ScreenToClient (window_private->xwindow, &pt);
2173               xevent->lParam = MAKELPARAM (pt.x, pt.y);
2174               GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
2175                                          window_private->xwindow));
2176               goto mousemotion;
2177             }
2178         }
2179
2180       event->motion.time = xevent->time;
2181       event->motion.x = curX = LOWORD (xevent->lParam);
2182       event->motion.y = curY = HIWORD (xevent->lParam);
2183       event->motion.x_root = xevent->pt.x;
2184       event->motion.y_root = xevent->pt.y;
2185       curXroot = event->motion.x_root;
2186       curYroot = event->motion.y_root;
2187       event->motion.pressure = 0.5;
2188       event->motion.xtilt = 0;
2189       event->motion.ytilt = 0;
2190       event->button.state = 0;
2191       if (xevent->wParam & MK_CONTROL)
2192         event->button.state |= GDK_CONTROL_MASK;
2193       if (xevent->wParam & MK_LBUTTON)
2194         event->button.state |= GDK_BUTTON1_MASK;
2195       if (xevent->wParam & MK_MBUTTON)
2196         event->button.state |= GDK_BUTTON2_MASK;
2197       if (xevent->wParam & MK_RBUTTON)
2198         event->button.state |= GDK_BUTTON3_MASK;
2199       if (xevent->wParam & MK_SHIFT)
2200         event->button.state |= GDK_SHIFT_MASK;
2201       if (mask & GDK_POINTER_MOTION_HINT_MASK)
2202         event->motion.is_hint = NotifyHint;
2203       else
2204         event->motion.is_hint = NotifyNormal;
2205       event->motion.source = GDK_SOURCE_MOUSE;
2206       event->motion.deviceid = GDK_CORE_POINTER;
2207
2208       return_val = window_private && !window_private->destroyed;
2209       if (return_val
2210           && p_grab_window != NULL
2211           && event->any.window == (GdkWindow *) p_grab_window
2212           && p_grab_window != window_private)
2213         {
2214           /* Translate coordinates to grabber */
2215           pt.x = event->motion.x;
2216           pt.y = event->motion.y;
2217           ClientToScreen (window_private->xwindow, &pt);
2218           ScreenToClient (p_grab_window->xwindow, &pt);
2219           event->motion.x = pt.x;
2220           event->motion.y = pt.y;
2221           GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
2222         }
2223       break;
2224
2225     case WM_NCMOUSEMOVE:
2226       GDK_NOTE (EVENTS,
2227                 g_print ("WM_NCMOUSEMOVE: %#x  x,y: %d %d\n",
2228                          xevent->hwnd,
2229                          LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2230 #if 0
2231       if (active == NULL || active != xevent->hwnd)
2232         break;
2233 #endif
2234       curWnd_private = (GdkWindowPrivate *) curWnd;
2235       if (curWnd != NULL
2236           && (curWnd_private->event_mask & GDK_LEAVE_NOTIFY_MASK))
2237         {
2238           GDK_NOTE (EVENTS, g_print ("...synthesizing LEAVE_NOTIFY event\n"));
2239
2240           event->crossing.type = GDK_LEAVE_NOTIFY;
2241           event->crossing.window = curWnd;
2242           event->crossing.subwindow = NULL;
2243           event->crossing.time = xevent->time;
2244           event->crossing.x = curX;
2245           event->crossing.y = curY;
2246           event->crossing.x_root = curXroot;
2247           event->crossing.y_root = curYroot;
2248           event->crossing.mode = GDK_CROSSING_NORMAL;
2249           event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2250
2251           event->crossing.focus = TRUE; /* ??? */
2252           event->crossing.state = 0; /* ??? */
2253           gdk_window_unref (curWnd);
2254           curWnd = NULL;
2255
2256           return_val = TRUE;
2257         }
2258       break;
2259
2260     case WM_SETFOCUS:
2261     case WM_KILLFOCUS:
2262       if (window_private
2263           && !(window_private->event_mask & GDK_FOCUS_CHANGE_MASK))
2264         break;
2265
2266       GDK_NOTE (EVENTS, g_print ("WM_%sFOCUS: %#x\n",
2267                                  (xevent->message == WM_SETFOCUS ? "SET" : "KILL"),
2268                                  xevent->hwnd));
2269       
2270       event->focus_change.type = GDK_FOCUS_CHANGE;
2271       event->focus_change.window = window;
2272       event->focus_change.in = (xevent->message == WM_SETFOCUS);
2273       return_val = window_private && !window_private->destroyed;
2274       break;
2275 #if 0
2276     case WM_ACTIVATE:
2277       GDK_NOTE (EVENTS, g_print ("WM_ACTIVATE: %#x  %d\n",
2278                                  xevent->hwnd, LOWORD (xevent->wParam)));
2279       if (LOWORD (xevent->wParam) == WA_INACTIVE)
2280         active = (HWND) xevent->lParam;
2281       else
2282         active = xevent->hwnd;
2283       break;
2284 #endif
2285     case WM_ERASEBKGND:
2286       GDK_NOTE (EVENTS, g_print ("WM_ERASEBKGND: %#x  dc %#x\n",
2287                                  xevent->hwnd, xevent->wParam));
2288       
2289       if (!window_private || window_private->destroyed)
2290         break;
2291       colormap_private = (GdkColormapPrivate *) window_private->colormap;
2292       hdc = (HDC) xevent->wParam;
2293       if (colormap_private
2294           && colormap_private->xcolormap->rc_palette)
2295         {
2296           int k;
2297
2298           if (SelectPalette (hdc,  colormap_private->xcolormap->palette,
2299                              FALSE) == NULL)
2300             g_warning ("WM_ERASEBKGND: SelectPalette failed");
2301           if ((k = RealizePalette (hdc)) == GDI_ERROR)
2302             g_warning ("WM_ERASEBKGND: RealizePalette failed");
2303 #if 0
2304           g_print ("WM_ERASEBKGND: selected %#x, realized %d colors\n",
2305                    colormap_private->xcolormap->palette, k);
2306 #endif
2307         }
2308       *ret_val_flagp = TRUE;
2309       *ret_valp = 1;
2310
2311       if (window_private->bg_type == GDK_WIN32_BG_TRANSPARENT)
2312         break;
2313
2314       if (window_private->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
2315         {
2316           /* If this window should have the same background as the
2317            * parent, fetch the parent. (And if the same goes for
2318            * the parent, fetch the grandparent, etc.)
2319            */
2320           while (window_private
2321                  && window_private->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
2322             window_private = (GdkWindowPrivate *) window_private->parent;
2323         }
2324
2325       if (window_private->bg_type == GDK_WIN32_BG_PIXEL)
2326         {
2327           COLORREF bg;
2328           GDK_NOTE (EVENTS, g_print ("...BG_PIXEL %s\n",
2329                                      gdk_color_to_string (&window_private->bg_pixel)));
2330           GetClipBox (hdc, &rect);
2331 #ifdef MULTIPLE_WINDOW_CLASSES
2332           bg = PALETTEINDEX (window_private->bg_pixel.pixel);
2333 #else
2334           bg = GetNearestColor (hdc, RGB (window_private->bg_pixel.red >> 8,
2335                                           window_private->bg_pixel.green >> 8,
2336                                           window_private->bg_pixel.blue >> 8));
2337 #endif
2338           hbr = CreateSolidBrush (bg);
2339 #if 0
2340           g_print ("...CreateSolidBrush (%.08x) = %.08x\n", bg, hbr);
2341 #endif
2342           if (!FillRect (hdc, &rect, hbr))
2343             g_warning ("WM_ERASEBKGND: FillRect failed");
2344           DeleteObject (hbr);
2345         }
2346       else if (window_private->bg_type == GDK_WIN32_BG_PIXMAP)
2347         {
2348           GdkPixmapPrivate *pixmap_private;
2349           HDC bgdc;
2350           HGDIOBJ oldbitmap;
2351
2352           pixmap_private = (GdkPixmapPrivate *) window_private->bg_pixmap;
2353           GetClipBox (hdc, &rect);
2354
2355           if (pixmap_private->width <= 8
2356               && pixmap_private->height <= 8)
2357             {
2358               GDK_NOTE (EVENTS, g_print ("...small pixmap, using brush\n"));
2359               hbr = CreatePatternBrush (pixmap_private->xwindow);
2360               if (!FillRect (hdc, &rect, hbr))
2361                 g_warning ("WM_ERASEBKGND: FillRect failed");
2362               DeleteObject (hbr);
2363             }
2364           else
2365             {
2366               GDK_NOTE (EVENTS,
2367                         g_print ("...blitting pixmap %#x (%dx%d) "
2368                                  "all over the place,\n"
2369                                  "...clip box = %dx%d@+%d+%d\n",
2370                                  pixmap_private->xwindow,
2371                                  pixmap_private->width, pixmap_private->height,
2372                                  rect.right - rect.left, rect.bottom - rect.top,
2373                                  rect.left, rect.top));
2374
2375               if (!(bgdc = CreateCompatibleDC (hdc)))
2376                 {
2377                   g_warning ("WM_ERASEBKGND: CreateCompatibleDC failed");
2378                   break;
2379                 }
2380               if (!(oldbitmap = SelectObject (bgdc, pixmap_private->xwindow)))
2381                 {
2382                   g_warning ("WM_ERASEBKGND: SelectObject failed");
2383                   DeleteDC (bgdc);
2384                   break;
2385                 }
2386               i = 0;
2387               while (i < rect.right)
2388                 {
2389                   j = 0;
2390                   while (j < rect.bottom)
2391                     {
2392                       if (i + pixmap_private->width >= rect.left
2393                           && j + pixmap_private->height >= rect.top)
2394                         {
2395                           if (!BitBlt (hdc, i, j,
2396                                        pixmap_private->width, pixmap_private->height,
2397                                        bgdc, 0, 0, SRCCOPY))
2398                             {
2399                               g_warning ("WM_ERASEBKGND: BitBlt failed");
2400                               goto loopexit;
2401                             }
2402                         }
2403                       j += pixmap_private->height;
2404                     }
2405                   i += pixmap_private->width;
2406                 }
2407             loopexit:
2408               SelectObject (bgdc, oldbitmap);
2409               DeleteDC (bgdc);
2410             }
2411         }
2412       else
2413         {
2414           GDK_NOTE (EVENTS, g_print ("...BLACK_BRUSH (?)\n"));
2415 #ifdef MULTIPLE_WINDOW_CLASSES
2416           hbr = (HBRUSH) GetClassLong (window_private->xwindow,
2417                                        GCL_HBRBACKGROUND);
2418 #else
2419           hbr = GetStockObject (BLACK_BRUSH);
2420 #endif
2421           GetClipBox (hdc, &rect);
2422           if (!FillRect (hdc, &rect, hbr))
2423             g_warning ("WM_ERASEBKGND: FillRect failed");
2424         }
2425       break;
2426
2427     case WM_PAINT:
2428       hdc = BeginPaint (xevent->hwnd, &paintstruct);
2429
2430       GDK_NOTE (EVENTS,
2431                 g_print ("WM_PAINT: %#x  %dx%d@+%d+%d %s dc %#x\n",
2432                          xevent->hwnd,
2433                          paintstruct.rcPaint.right - paintstruct.rcPaint.left,
2434                          paintstruct.rcPaint.bottom - paintstruct.rcPaint.top,
2435                          paintstruct.rcPaint.left, paintstruct.rcPaint.top,
2436                          (paintstruct.fErase ? "erase" : ""),
2437                          hdc));
2438
2439       EndPaint (xevent->hwnd, &paintstruct);
2440
2441       if (window_private
2442           && !(window_private->event_mask & GDK_EXPOSURE_MASK))
2443         break;
2444
2445       event->expose.type = GDK_EXPOSE;
2446       event->expose.window = window;
2447       event->expose.area.x = paintstruct.rcPaint.left;
2448       event->expose.area.y = paintstruct.rcPaint.top;
2449       event->expose.area.width = paintstruct.rcPaint.right - paintstruct.rcPaint.left;
2450       event->expose.area.height = paintstruct.rcPaint.bottom - paintstruct.rcPaint.top;
2451       event->expose.count = 1;
2452
2453       return_val = window_private && !window_private->destroyed;
2454       break;
2455
2456 #ifndef MULTIPLE_WINDOW_CLASSES
2457     case WM_SETCURSOR:
2458       GDK_NOTE (EVENTS, g_print ("WM_SETCURSOR: %#x %#x %#x\n",
2459                                  xevent->hwnd,
2460                                  LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2461
2462       return_val = FALSE;
2463       if (LOWORD (xevent->lParam) != HTCLIENT)
2464         break;
2465       if (p_grab_window != NULL && p_grab_cursor != NULL)
2466         SetCursor (p_grab_cursor);
2467       else if (window_private
2468                && !window_private->destroyed
2469                && window_private->xcursor)
2470         SetCursor (window_private->xcursor);
2471       *ret_val_flagp = TRUE;
2472       *ret_valp = FALSE;
2473       break;
2474 #endif
2475
2476 #if 0
2477     case WM_QUERYOPEN:
2478       GDK_NOTE (EVENTS, g_print ("WM_QUERYOPEN: %#x\n",
2479                                  xevent->hwnd));
2480       *ret_val_flagp = TRUE;
2481       *ret_valp = TRUE;
2482
2483       if (window_private
2484           && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2485         break;
2486
2487       event->any.type = GDK_MAP;
2488       event->any.window = window;
2489
2490       return_val = window_private && !window_private->destroyed;
2491       break;
2492 #endif
2493
2494 #if 1
2495     case WM_SHOWWINDOW:
2496       GDK_NOTE (EVENTS, g_print ("WM_SHOWWINDOW: %#x  %d\n",
2497                                  xevent->hwnd,
2498                                  xevent->wParam));
2499
2500       if (window_private
2501           && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2502         break;
2503
2504       event->any.type = (xevent->wParam ? GDK_MAP : GDK_UNMAP);
2505       event->any.window = window;
2506
2507       if (event->any.type == GDK_UNMAP
2508           && p_grab_window == window_private)
2509         gdk_pointer_ungrab (xevent->time);
2510
2511       if (event->any.type == GDK_UNMAP
2512           && k_grab_window == window_private)
2513         gdk_keyboard_ungrab (xevent->time);
2514
2515       return_val = window_private && !window_private->destroyed;
2516       break;
2517 #endif
2518     case WM_SIZE:
2519       GDK_NOTE (EVENTS,
2520                 g_print ("WM_SIZE: %#x  %s %dx%d\n",
2521                          xevent->hwnd,
2522                          (xevent->wParam == SIZE_MAXHIDE ? "MAXHIDE" :
2523                           (xevent->wParam == SIZE_MAXIMIZED ? "MAXIMIZED" :
2524                            (xevent->wParam == SIZE_MAXSHOW ? "MAXSHOW" :
2525                             (xevent->wParam == SIZE_MINIMIZED ? "MINIMIZED" :
2526                              (xevent->wParam == SIZE_RESTORED ? "RESTORED" : "?"))))),
2527                          LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2528
2529       if (window_private
2530           && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2531         break;
2532       if (window_private != NULL
2533           && xevent->wParam == SIZE_MINIMIZED)
2534         {
2535 #if 1
2536           event->any.type = GDK_UNMAP;
2537           event->any.window = window;
2538
2539           if (p_grab_window == window_private)
2540             gdk_pointer_ungrab (xevent->time);
2541
2542           if (k_grab_window == window_private)
2543             gdk_keyboard_ungrab (xevent->time);
2544
2545           return_val = !window_private->destroyed;
2546 #endif
2547         }
2548       else if (window_private != NULL
2549                && (xevent->wParam == SIZE_RESTORED
2550                    || xevent->wParam == SIZE_MAXIMIZED)
2551 #if 1
2552                && window_private->window_type != GDK_WINDOW_CHILD
2553 #endif
2554                                                                  )
2555         {
2556           if (LOWORD (xevent->lParam) == 0)
2557             break;
2558
2559           event->configure.type = GDK_CONFIGURE;
2560           event->configure.window = window;
2561           pt.x = 0;
2562           pt.y = 0;
2563           ClientToScreen (xevent->hwnd, &pt);
2564           event->configure.x = pt.x;
2565           event->configure.y = pt.y;
2566           event->configure.width = LOWORD (xevent->lParam);
2567           event->configure.height = HIWORD (xevent->lParam);
2568           window_private->x = event->configure.x;
2569           window_private->y = event->configure.y;
2570           window_private->width = event->configure.width;
2571           window_private->height = event->configure.height;
2572           if (window_private->resize_count > 1)
2573             window_private->resize_count -= 1;
2574           
2575           return_val = !window_private->destroyed;
2576           if (return_val
2577               && window_private->extension_events != 0
2578               && gdk_input_vtable.configure_event)
2579             gdk_input_vtable.configure_event (&event->configure, window);
2580         }
2581       break;
2582
2583     case WM_SIZING:
2584       GDK_NOTE (EVENTS, g_print ("WM_SIZING: %#x\n", xevent->hwnd));
2585       if (ret_val_flagp == NULL)
2586           g_warning ("ret_val_flagp is NULL but we got a WM_SIZING?");
2587       else if (window_private != NULL
2588                && window_private->hint_flags &
2589                (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE))
2590         {
2591           LPRECT lprc = (LPRECT) xevent->lParam;
2592
2593           if (window_private->hint_flags & GDK_HINT_MIN_SIZE)
2594             {
2595               gint w = lprc->right - lprc->left;
2596               gint h = lprc->bottom - lprc->top;
2597
2598               if (w < window_private->hint_min_width)
2599                 {
2600                   if (xevent->wParam == WMSZ_BOTTOMLEFT
2601                       || xevent->wParam == WMSZ_LEFT
2602                       || xevent->wParam == WMSZ_TOPLEFT)
2603                     lprc->left = lprc->right - window_private->hint_min_width;
2604                   else
2605                     lprc->right = lprc->left + window_private->hint_min_width;
2606                   *ret_val_flagp = TRUE;
2607                   *ret_valp = TRUE;
2608                 }
2609               if (h < window_private->hint_min_height)
2610                 {
2611                   if (xevent->wParam == WMSZ_BOTTOMLEFT
2612                       || xevent->wParam == WMSZ_BOTTOM
2613                       || xevent->wParam == WMSZ_BOTTOMRIGHT)
2614                     lprc->bottom = lprc->top + window_private->hint_min_height;
2615                   else
2616                     lprc->top = lprc->bottom - window_private->hint_min_height;
2617                   *ret_val_flagp = TRUE;
2618                   *ret_valp = TRUE;
2619                 }
2620             }
2621           if (window_private->hint_flags & GDK_HINT_MAX_SIZE)
2622             {
2623               gint w = lprc->right - lprc->left;
2624               gint h = lprc->bottom - lprc->top;
2625
2626               if (w > window_private->hint_max_width)
2627                 {
2628                   if (xevent->wParam == WMSZ_BOTTOMLEFT
2629                       || xevent->wParam == WMSZ_LEFT
2630                       || xevent->wParam == WMSZ_TOPLEFT)
2631                     lprc->left = lprc->right - window_private->hint_max_width;
2632                   else
2633                     lprc->right = lprc->left + window_private->hint_max_width;
2634                   *ret_val_flagp = TRUE;
2635                   *ret_valp = TRUE;
2636                 }
2637               if (h > window_private->hint_max_height)
2638                 {
2639                   if (xevent->wParam == WMSZ_BOTTOMLEFT
2640                       || xevent->wParam == WMSZ_BOTTOM
2641                       || xevent->wParam == WMSZ_BOTTOMRIGHT)
2642                     lprc->bottom = lprc->top + window_private->hint_max_height;
2643                   else
2644                     lprc->top = lprc->bottom - window_private->hint_max_height;
2645                   *ret_val_flagp = TRUE;
2646                   *ret_valp = TRUE;
2647                 }
2648             }
2649         }
2650       break;
2651
2652     case WM_MOVE:
2653       GDK_NOTE (EVENTS, g_print ("WM_MOVE: %#x  +%d+%d\n",
2654                                  xevent->hwnd,
2655                                  LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2656
2657       if (window_private
2658           && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2659         break;
2660       if (window_private != NULL
2661           && window_private->window_type != GDK_WINDOW_CHILD)
2662         {
2663           event->configure.type = GDK_CONFIGURE;
2664           event->configure.window = window;
2665           event->configure.x = LOWORD (xevent->lParam);
2666           event->configure.y = HIWORD (xevent->lParam);
2667           GetClientRect (xevent->hwnd, &rect);
2668           event->configure.width = rect.right;
2669           event->configure.height = rect.bottom;
2670           window_private->x = event->configure.x;
2671           window_private->y = event->configure.y;
2672           window_private->width = event->configure.width;
2673           window_private->height = event->configure.height;
2674           
2675           return_val = !window_private->destroyed;
2676         }
2677       break;
2678
2679     case WM_CLOSE:
2680       GDK_NOTE (EVENTS, g_print ("WM_CLOSE: %#x\n", xevent->hwnd));
2681       event->any.type = GDK_DELETE;
2682       event->any.window = window;
2683       
2684       return_val = window_private && !window_private->destroyed;
2685       break;
2686
2687 #if 0
2688     /* No, don't use delayed rendering after all. It works only if the
2689      * delayed SetClipboardData is called from the WindowProc, it
2690      * seems. (The #else part below is test code for that. It succeeds
2691      * in setting the clipboard data. But if I call SetClipboardData
2692      * in gdk_property_change (as a consequence of the
2693      * GDK_SELECTION_REQUEST event), it fails.  I deduce that this is
2694      * because delayed rendering requires that SetClipboardData is
2695      * called in the window procedure.)
2696      */
2697     case WM_RENDERFORMAT:
2698     case WM_RENDERALLFORMATS:
2699       flag = FALSE;
2700       GDK_NOTE (EVENTS, flag = TRUE);
2701       GDK_NOTE (SELECTION, flag = TRUE);
2702       if (flag)
2703         g_print ("WM_%s: %#x %#x (%s)\n",
2704                  (xevent->message == WM_RENDERFORMAT ? "RENDERFORMAT" :
2705                   "RENDERALLFORMATS"),
2706                  xevent->hwnd,
2707                  xevent->wParam,
2708                  (xevent->wParam == CF_TEXT ? "CF_TEXT" :
2709                   (xevent->wParam == CF_DIB ? "CF_DIB" :
2710                    (xevent->wParam == CF_UNICODETEXT ? "CF_UNICODETEXT" :
2711                     (GetClipboardFormatName (xevent->wParam, buf, sizeof (buf)), buf)))));
2712
2713 #if 0
2714       event->selection.type = GDK_SELECTION_REQUEST;
2715       event->selection.window = window;
2716       event->selection.selection = gdk_clipboard_atom;
2717       if (xevent->wParam == CF_TEXT)
2718         event->selection.target = GDK_TARGET_STRING;
2719       else
2720         {
2721           GetClipboardFormatName (xevent->wParam, buf, sizeof (buf));
2722           event->selection.target = gdk_atom_intern (buf, FALSE);
2723         }
2724       event->selection.property = gdk_selection_property;
2725       event->selection.requestor = (guint32) xevent->hwnd;
2726       event->selection.time = xevent->time;
2727       return_val = window_private && !window_private->destroyed;
2728 #else
2729       /* Test code, to see if SetClipboardData works when called from
2730        * the window procedure.
2731        */
2732       {
2733         HGLOBAL hdata = GlobalAlloc (GMEM_MOVEABLE|GMEM_DDESHARE, 10);
2734         char *ptr = GlobalLock (hdata);
2735         strcpy (ptr, "Huhhaa");
2736         GlobalUnlock (hdata);
2737         if (!SetClipboardData (CF_TEXT, hdata))
2738           g_print ("SetClipboardData failed: %d\n", GetLastError ());
2739       }
2740       *ret_valp = 0;
2741       *ret_val_flagp = TRUE;
2742       return_val = FALSE;
2743 #endif
2744       break;
2745 #endif /* No delayed rendering */
2746
2747     case WM_DESTROY:
2748       GDK_NOTE (EVENTS, g_print ("WM_DESTROY: %#x\n", xevent->hwnd));
2749       event->any.type = GDK_DESTROY;
2750       event->any.window = window;
2751       if (window != NULL && window == curWnd)
2752         {
2753           gdk_window_unref (curWnd);
2754           curWnd = NULL;
2755         }
2756
2757       if (p_grab_window == window_private)
2758         gdk_pointer_ungrab (xevent->time);
2759
2760       if (k_grab_window == window_private)
2761         gdk_keyboard_ungrab (xevent->time);
2762
2763       return_val = window_private && !window_private->destroyed;
2764       break;
2765
2766       /* Handle WINTAB events here, as we know that gdkinput.c will
2767        * use the fixed WT_DEFBASE as lcMsgBase, and we thus can use the
2768        * constants as case labels.
2769        */
2770     case WT_PACKET:
2771       GDK_NOTE (EVENTS, g_print ("WT_PACKET: %d %#x\n",
2772                                  xevent->wParam, xevent->lParam));
2773       goto wintab;
2774       
2775     case WT_CSRCHANGE:
2776       GDK_NOTE (EVENTS, g_print ("WT_CSRCHANGE: %d %#x\n",
2777                                  xevent->wParam, xevent->lParam));
2778       goto wintab;
2779       
2780     case WT_PROXIMITY:
2781       GDK_NOTE (EVENTS,
2782                 g_print ("WT_PROXIMITY: %#x %d %d\n",
2783                          xevent->wParam,
2784                          LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2785     wintab:
2786       return_val = gdk_input_vtable.other_event(event, xevent);
2787       break;
2788     }
2789
2790 bypass_switch:
2791
2792   if (return_val)
2793     {
2794       if (event->any.window)
2795         gdk_window_ref (event->any.window);
2796       if (((event->any.type == GDK_ENTER_NOTIFY) ||
2797            (event->any.type == GDK_LEAVE_NOTIFY)) &&
2798           (event->crossing.subwindow != NULL))
2799         gdk_window_ref (event->crossing.subwindow);
2800     }
2801   else
2802     {
2803       /* Mark this event as having no resources to be freed */
2804       event->any.window = NULL;
2805       event->any.type = GDK_NOTHING;
2806     }
2807
2808   if (window)
2809     gdk_window_unref (window);
2810   
2811   return return_val;
2812 }
2813
2814 static void
2815 gdk_events_queue (void)
2816 {
2817   GList *node;
2818   GdkEvent *event;
2819   MSG msg;
2820
2821   GDK_NOTE (EVENTS, g_print ("gdk_events_queue: %s\n",
2822                              (queued_events ? "yes" : "none")));
2823
2824   while (!gdk_event_queue_find_first()
2825          && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
2826     {
2827       GDK_NOTE (EVENTS, g_print ("gdk_events_queue: got event\n"));
2828       TranslateMessage (&msg);
2829
2830       event = gdk_event_new ();
2831       
2832       event->any.type = GDK_NOTHING;
2833       event->any.window = NULL;
2834       event->any.send_event = FALSE;
2835
2836       ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
2837
2838       gdk_event_queue_append (event);
2839       node = queued_tail;
2840
2841       if (gdk_event_translate (event, &msg, NULL, NULL))
2842           ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
2843       else
2844         {
2845           DefWindowProc (msg.hwnd, msg.message, msg.wParam, msg.lParam);
2846           gdk_event_queue_remove_link (node);
2847           g_list_free_1 (node);
2848           gdk_event_free (event);
2849         }
2850     }
2851 }
2852
2853 static gboolean  
2854 gdk_event_prepare (gpointer  source_data, 
2855                    GTimeVal *current_time,
2856                    gint     *timeout)
2857 {
2858   MSG msg;
2859   gboolean retval;
2860   
2861   GDK_THREADS_ENTER ();
2862
2863   *timeout = -1;
2864
2865   GDK_NOTE (EVENTS, g_print ("gdk_event_prepare\n"));
2866
2867   retval = (gdk_event_queue_find_first () != NULL)
2868               || PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
2869
2870   GDK_THREADS_LEAVE ();
2871
2872   return retval;
2873 }
2874
2875 static gboolean  
2876 gdk_event_check (gpointer  source_data,
2877                  GTimeVal *current_time)
2878 {
2879   MSG msg;
2880   gboolean retval;
2881   
2882   GDK_NOTE (EVENTS, g_print ("gdk_event_check\n"));
2883
2884   GDK_THREADS_ENTER ();
2885
2886   if (event_poll_fd.revents & G_IO_IN)
2887     retval = (gdk_event_queue_find_first () != NULL)
2888               || PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
2889   else
2890     retval = FALSE;
2891
2892   GDK_THREADS_LEAVE ();
2893
2894   return retval;
2895 }
2896
2897 static GdkEvent*
2898 gdk_event_unqueue (void)
2899 {
2900   GdkEvent *event = NULL;
2901   GList *tmp_list;
2902
2903   tmp_list = gdk_event_queue_find_first ();
2904
2905   if (tmp_list)
2906     {
2907       event = tmp_list->data;
2908       gdk_event_queue_remove_link (tmp_list);
2909       g_list_free_1 (tmp_list);
2910     }
2911
2912   return event;
2913 }
2914
2915 static gboolean  
2916 gdk_event_dispatch (gpointer  source_data,
2917                     GTimeVal *current_time,
2918                     gpointer  user_data)
2919 {
2920   GdkEvent *event;
2921  
2922   GDK_NOTE (EVENTS, g_print ("gdk_event_dispatch\n"));
2923
2924   GDK_THREADS_ENTER ();
2925
2926   gdk_events_queue();
2927   event = gdk_event_unqueue();
2928
2929   if (event)
2930     {
2931       if (event_func)
2932         (*event_func) (event, event_data);
2933       
2934       gdk_event_free (event);
2935     }
2936   
2937   GDK_THREADS_LEAVE ();
2938
2939   return TRUE;
2940 }
2941
2942 static void
2943 gdk_synthesize_click (GdkEvent *event,
2944                       gint      nclicks)
2945 {
2946   GdkEvent temp_event;
2947   
2948   g_return_if_fail (event != NULL);
2949   
2950   temp_event = *event;
2951   temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
2952   
2953   gdk_event_put (&temp_event);
2954 }
2955
2956 /* Sends a ClientMessage to all toplevel client windows */
2957 gboolean
2958 gdk_event_send_client_message (GdkEvent *event, guint32 xid)
2959 {
2960   /* XXX */
2961   return FALSE;
2962 }
2963
2964 void
2965 gdk_event_send_clientmessage_toall (GdkEvent *event)
2966 {
2967   /* XXX */
2968 }
2969