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