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