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