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
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.
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.
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.
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/.
33 #include "gdkprivate.h"
36 #include "gdkkeysyms.h"
41 #include "gdkinputprivate.h"
43 #define PING() printf("%s: %d\n",__FILE__,__LINE__),fflush(stdout)
45 typedef struct _GdkIOClosure GdkIOClosure;
46 typedef struct _GdkEventPrivate GdkEventPrivate;
48 #define DOUBLE_CLICK_TIME 250
49 #define TRIPLE_CLICK_TIME 500
50 #define DOUBLE_CLICK_DIST 5
51 #define TRIPLE_CLICK_DIST 5
53 gint gdk_event_func_from_window_proc = FALSE;
57 /* Following flag is set for events on the event queue during
58 * translation and cleared afterwards.
60 GDK_EVENT_PENDING = 1 << 0
65 GdkInputFunction function;
66 GdkInputCondition condition;
67 GdkDestroyNotify notify;
71 struct _GdkEventPrivate
78 * Private function declarations
81 static GdkEvent *gdk_event_new (void);
82 static GdkFilterReturn
83 gdk_event_apply_filters (MSG *xevent,
86 static gint gdk_event_translate (GdkEvent *event,
88 gboolean *ret_val_flagp,
90 static void gdk_events_queue (void);
91 static GdkEvent *gdk_event_unqueue (void);
92 static gboolean gdk_event_prepare (gpointer source_data,
93 GTimeVal *current_time,
95 static gboolean gdk_event_check (gpointer source_data,
96 GTimeVal *current_time);
97 static gboolean gdk_event_dispatch (gpointer source_data,
98 GTimeVal *current_time,
101 static void gdk_synthesize_click (GdkEvent *event,
104 /* Private variable declarations
107 static guint32 button_click_time[2]; /* The last 2 button click times. Used
108 * to determine if the latest button click
109 * is part of a double or triple click.
111 static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
112 * Also used to determine if the latest button
113 * click is part of a double or triple click.
115 static guint button_number[2]; /* The last 2 buttons to be pressed.
117 static GdkWindowPrivate *p_grab_window = NULL; /* Window that currently
118 * holds the pointer grab
121 static GdkWindowPrivate *k_grab_window = NULL; /* Window the holds the
125 static GList *client_filters; /* Filters for client messages */
127 static gboolean p_grab_automatic;
128 static GdkEventMask p_grab_event_mask;
129 static gboolean p_grab_owner_events, k_grab_owner_events;
130 static HCURSOR p_grab_cursor;
132 static GdkEventFunc event_func = NULL; /* Callback for events */
133 static gpointer event_data = NULL;
134 static GDestroyNotify event_notify = NULL;
136 static GList *client_filters; /* Filters for client messages */
138 /* FIFO's for event queue, and for events put back using
141 static GList *queued_events = NULL;
142 static GList *queued_tail = NULL;
144 static GSourceFuncs event_funcs = {
148 (GDestroyNotify)g_free
151 GPollFD event_poll_fd;
153 static GdkWindow *curWnd = NULL;
154 static HWND active = NULL;
155 static gint curX, curY;
156 static gdouble curXroot, curYroot;
157 static UINT gdk_ping_msg;
158 static gboolean ignore_WM_CHAR = FALSE;
159 static gboolean is_AltGr_key = FALSE;
162 gdk_WindowProc(HWND hwnd,
172 gboolean ret_val_flag;
174 GDK_NOTE (EVENTS, g_print ("gdk_WindowProc: %#x\n", message));
177 msg.message = message;
180 msg.time = GetTickCount ();
181 pos = GetMessagePos ();
182 msg.pt.x = LOWORD (pos);
183 msg.pt.y = HIWORD (pos);
185 if (gdk_event_translate (&event, &msg, &ret_val_flag, &ret_val))
188 /* Compress configure events */
189 if (event.any.type == GDK_CONFIGURE)
191 GList *list = queued_events;
194 && (((GdkEvent *)list->data)->any.type != GDK_CONFIGURE
195 || ((GdkEvent *)list->data)->any.window != event.any.window))
199 *((GdkEvent *)list->data) = event;
200 gdk_window_unref (event.any.window);
201 /* Wake up WaitMessage */
202 PostMessage (NULL, gdk_ping_msg, 0, 0);
207 eventp = gdk_event_new ();
210 /* Philippe Colantoni <colanton@aris.ss.uci.edu> suggests this
211 * in order to handle events while opaque resizing neatly. I
212 * don't want it as default. Set the
213 * GDK_EVENT_FUNC_FROM_WINDOW_PROC env var to get this
216 if (gdk_event_func_from_window_proc && event_func)
218 GDK_THREADS_ENTER ();
220 (*event_func) (eventp, event_data);
221 gdk_event_free (eventp);
223 GDK_THREADS_LEAVE ();
227 gdk_event_queue_append (eventp);
229 /* Wake up WaitMessage */
230 PostMessage (NULL, gdk_ping_msg, 0, 0);
243 return DefWindowProc (hwnd, message, wParam, lParam);
246 /*********************************************
247 * Functions for maintaining the event queue *
248 *********************************************/
250 /*************************************************************
251 * gdk_event_queue_find_first:
252 * Find the first event on the queue that is not still
257 * Pointer to the list node for that event, or NULL
258 *************************************************************/
261 gdk_event_queue_find_first (void)
263 GList *tmp_list = queued_events;
267 GdkEventPrivate *event = tmp_list->data;
268 if (!(event->flags & GDK_EVENT_PENDING))
271 tmp_list = g_list_next (tmp_list);
277 /*************************************************************
278 * gdk_event_queue_remove_link:
279 * Remove a specified list node from the event queue.
281 * node: Node to remove.
283 *************************************************************/
286 gdk_event_queue_remove_link (GList *node)
289 node->prev->next = node->next;
291 queued_events = node->next;
294 node->next->prev = node->prev;
296 queued_tail = node->prev;
300 /*************************************************************
301 * gdk_event_queue_append:
302 * Append an event onto the tail of the event queue.
304 * event: Event to append.
306 *************************************************************/
309 gdk_event_queue_append (GdkEvent *event)
311 queued_tail = g_list_append (queued_tail, event);
314 queued_events = queued_tail;
316 queued_tail = queued_tail->next;
320 gdk_events_init (void)
322 if (g_pipe_readable_msg == 0)
323 g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
325 g_source_add (GDK_PRIORITY_EVENTS, TRUE, &event_funcs, NULL, NULL, NULL);
327 event_poll_fd.fd = G_WIN32_MSG_HANDLE;
328 event_poll_fd.events = G_IO_IN;
330 g_main_add_poll (&event_poll_fd, GDK_PRIORITY_EVENTS);
332 button_click_time[0] = 0;
333 button_click_time[1] = 0;
334 button_window[0] = NULL;
335 button_window[1] = NULL;
336 button_number[0] = -1;
337 button_number[1] = -1;
339 gdk_ping_msg = RegisterWindowMessage ("gdk-ping");
343 *--------------------------------------------------------------
346 * Returns if events are pending on the queue.
351 * Returns TRUE if events are pending
355 *--------------------------------------------------------------
359 gdk_events_pending (void)
363 return (gdk_event_queue_find_first() || PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE));
367 *--------------------------------------------------------------
368 * gdk_event_get_graphics_expose
370 * Waits for a GraphicsExpose or NoExpose event
375 * For GraphicsExpose events, returns a pointer to the event
376 * converted into a GdkEvent Otherwise, returns NULL.
380 *-------------------------------------------------------------- */
383 gdk_event_get_graphics_expose (GdkWindow *window)
387 GdkWindowPrivate *private = (GdkWindowPrivate *) window;
389 g_return_val_if_fail (window != NULL, NULL);
391 GDK_NOTE (EVENTS, g_print ("gdk_event_get_graphics_expose\n"));
394 /* Some nasty bugs here, just return NULL for now. */
397 if (GetMessage (&xevent, private->xwindow, WM_PAINT, WM_PAINT))
399 event = gdk_event_new ();
401 if (gdk_event_translate (event, &xevent, NULL, NULL))
404 gdk_event_free (event);
411 /************************
412 * Exposure compression *
413 ************************/
415 /* I don't bother with exposure compression on Win32. Windows compresses
416 * WM_PAINT events by itself.
419 /*************************************************************
420 * gdk_event_handler_set:
423 * func: Callback function to be called for each event.
424 * data: Data supplied to the function
425 * notify: function called when function is no longer needed
428 *************************************************************/
431 gdk_event_handler_set (GdkEventFunc func,
433 GDestroyNotify notify)
436 (*event_notify) (event_data);
440 event_notify = notify;
444 *--------------------------------------------------------------
447 * Gets the next event.
452 * If an event is waiting that we care about, returns
453 * a pointer to that event, to be freed with gdk_event_free.
454 * Otherwise, returns NULL.
458 *--------------------------------------------------------------
466 return gdk_event_unqueue();
470 *--------------------------------------------------------------
473 * Gets the next event.
478 * If an event is waiting that we care about, returns
479 * a copy of that event, but does not remove it from
480 * the queue. The pointer is to be freed with gdk_event_free.
481 * Otherwise, returns NULL.
485 *--------------------------------------------------------------
489 gdk_event_peek (void)
493 tmp_list = gdk_event_queue_find_first ();
496 return gdk_event_copy (tmp_list->data);
502 gdk_event_put (GdkEvent *event)
507 g_return_if_fail (event != NULL);
509 new_event = gdk_event_copy (event);
511 gdk_event_queue_append (new_event);
515 *--------------------------------------------------------------
518 * Copy a event structure into new storage.
521 * "event" is the event struct to copy.
524 * A new event structure. Free it with gdk_event_free.
527 * The reference count of the window in the event is increased.
529 *--------------------------------------------------------------
532 static GMemChunk *event_chunk = NULL;
537 GdkEventPrivate *new_event;
539 if (event_chunk == NULL)
540 event_chunk = g_mem_chunk_new ("events",
541 sizeof (GdkEventPrivate),
545 new_event = g_chunk_new (GdkEventPrivate, event_chunk);
546 new_event->flags = 0;
548 return (GdkEvent *) new_event;
552 gdk_event_copy (GdkEvent *event)
557 g_return_val_if_fail (event != NULL, NULL);
559 new_event = gdk_event_new ();
562 gdk_window_ref (new_event->any.window);
564 switch (event->any.type)
567 case GDK_KEY_RELEASE:
568 if (event->key.length > 0)
570 s = event->key.string;
571 new_event->key.string = g_malloc (event->key.length + 1);
572 memcpy (new_event->key.string, s, event->key.length + 1);
576 case GDK_ENTER_NOTIFY:
577 case GDK_LEAVE_NOTIFY:
578 if (event->crossing.subwindow != NULL)
579 gdk_window_ref (event->crossing.subwindow);
584 case GDK_DRAG_MOTION:
585 case GDK_DRAG_STATUS:
587 case GDK_DROP_FINISHED:
588 gdk_drag_context_ref (event->dnd.context);
599 *--------------------------------------------------------------
602 * Free a event structure obtained from gdk_event_copy. Do not use
603 * with other event structures.
606 * "event" is the event struct to free.
611 * The reference count of the window in the event is decreased and
612 * might be freed, too.
614 *-------------------------------------------------------------- */
617 gdk_event_free (GdkEvent *event)
619 g_return_if_fail (event != NULL);
621 g_assert (event_chunk != NULL); /* paranoid */
623 if (event->any.window)
624 gdk_window_unref (event->any.window);
626 switch (event->any.type)
629 case GDK_KEY_RELEASE:
630 g_free (event->key.string);
633 case GDK_ENTER_NOTIFY:
634 case GDK_LEAVE_NOTIFY:
635 if (event->crossing.subwindow != NULL)
636 gdk_window_unref (event->crossing.subwindow);
641 case GDK_DRAG_MOTION:
642 case GDK_DRAG_STATUS:
644 case GDK_DROP_FINISHED:
645 gdk_drag_context_unref (event->dnd.context);
652 g_mem_chunk_free (event_chunk, event);
656 *--------------------------------------------------------------
657 * gdk_event_get_time:
658 * Get the timestamp from an event.
662 * The event's time stamp, if it has one, otherwise
664 *--------------------------------------------------------------
668 gdk_event_get_time (GdkEvent *event)
673 case GDK_MOTION_NOTIFY:
674 return event->motion.time;
675 case GDK_BUTTON_PRESS:
676 case GDK_2BUTTON_PRESS:
677 case GDK_3BUTTON_PRESS:
678 case GDK_BUTTON_RELEASE:
679 return event->button.time;
681 case GDK_KEY_RELEASE:
682 return event->key.time;
683 case GDK_ENTER_NOTIFY:
684 case GDK_LEAVE_NOTIFY:
685 return event->crossing.time;
686 case GDK_PROPERTY_NOTIFY:
687 return event->property.time;
688 case GDK_SELECTION_CLEAR:
689 case GDK_SELECTION_REQUEST:
690 case GDK_SELECTION_NOTIFY:
691 return event->selection.time;
692 case GDK_PROXIMITY_IN:
693 case GDK_PROXIMITY_OUT:
694 return event->proximity.time;
697 case GDK_DRAG_MOTION:
698 case GDK_DRAG_STATUS:
700 case GDK_DROP_FINISHED:
701 return event->dnd.time;
702 default: /* use current time */
706 return GDK_CURRENT_TIME;
710 *--------------------------------------------------------------
711 * gdk_set_show_events
713 * Turns on/off the showing of events.
716 * "show_events" is a boolean describing whether or
717 * not to show the events gdk receives.
722 * When "show_events" is TRUE, calls to "gdk_event_get"
723 * will output debugging informatin regarding the event
724 * received to stdout.
726 *--------------------------------------------------------------
730 gdk_set_show_events (gint show_events)
733 gdk_debug_flags |= GDK_DEBUG_EVENTS;
735 gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
739 gdk_get_show_events (void)
741 return gdk_debug_flags & GDK_DEBUG_EVENTS;
745 *--------------------------------------------------------------
748 * Grabs the pointer to a specific window
751 * "window" is the window which will receive the grab
752 * "owner_events" specifies whether events will be reported as is,
753 * or relative to "window"
754 * "event_mask" masks only interesting events
755 * "confine_to" limits the cursor movement to the specified window
756 * "cursor" changes the cursor for the duration of the grab
757 * "time" specifies the time
762 * requires a corresponding call to gdk_pointer_ungrab
764 *--------------------------------------------------------------
768 gdk_pointer_grab (GdkWindow * window,
770 GdkEventMask event_mask,
771 GdkWindow * confine_to,
775 GdkWindowPrivate *window_private;
779 GdkWindowPrivate *confine_to_private;
780 GdkCursorPrivate *cursor_private;
783 g_return_val_if_fail (window != NULL, 0);
785 window_private = (GdkWindowPrivate*) window;
786 confine_to_private = (GdkWindowPrivate*) confine_to;
787 cursor_private = (GdkCursorPrivate*) cursor;
789 xwindow = window_private->xwindow;
791 if (!confine_to || confine_to_private->destroyed)
794 xconfine_to = confine_to_private->xwindow;
799 xcursor = cursor_private->xcursor;
801 if (gdk_input_vtable.grab_pointer)
802 return_val = gdk_input_vtable.grab_pointer (window,
808 return_val = Success;
810 if (return_val == Success)
812 if (!window_private->destroyed)
814 GDK_NOTE (EVENTS, g_print ("gdk_pointer_grab: %#x %s %#x\n",
816 (owner_events ? "TRUE" : "FALSE"),
818 p_grab_event_mask = event_mask;
819 p_grab_owner_events = owner_events != 0;
820 p_grab_automatic = FALSE;
822 #if 0 /* Menus don't work if we use mouse capture. Pity, because many other
823 * things work better with mouse capture.
825 SetCapture (xwindow);
827 return_val = GrabSuccess;
830 return_val = AlreadyGrabbed;
833 if (return_val == GrabSuccess)
835 p_grab_window = window_private;
836 p_grab_cursor = xcursor;
843 *--------------------------------------------------------------
846 * Releases any pointer grab
854 *--------------------------------------------------------------
858 gdk_pointer_ungrab (guint32 time)
860 if (gdk_input_vtable.ungrab_pointer)
861 gdk_input_vtable.ungrab_pointer (time);
863 if (GetCapture () != NULL)
866 GDK_NOTE (EVENTS, g_print ("gdk_pointer_ungrab\n"));
868 p_grab_window = NULL;
872 *--------------------------------------------------------------
873 * gdk_pointer_is_grabbed
875 * Tell wether there is an active x pointer grab in effect
883 *--------------------------------------------------------------
887 gdk_pointer_is_grabbed (void)
889 return p_grab_window != NULL;
893 *--------------------------------------------------------------
896 * Grabs the keyboard to a specific window
899 * "window" is the window which will receive the grab
900 * "owner_events" specifies whether events will be reported as is,
901 * or relative to "window"
902 * "time" specifies the time
907 * requires a corresponding call to gdk_keyboard_ungrab
909 *--------------------------------------------------------------
913 gdk_keyboard_grab (GdkWindow * window,
917 GdkWindowPrivate *window_private;
920 g_return_val_if_fail (window != NULL, 0);
922 window_private = (GdkWindowPrivate*) window;
924 GDK_NOTE (EVENTS, g_print ("gdk_keyboard_grab %#x\n",
925 window_private->xwindow));
927 if (!window_private->destroyed)
929 k_grab_owner_events = owner_events != 0;
930 return_val = GrabSuccess;
933 return_val = AlreadyGrabbed;
935 if (return_val == GrabSuccess)
936 k_grab_window = window_private;
942 *--------------------------------------------------------------
943 * gdk_keyboard_ungrab
945 * Releases any keyboard grab
953 *--------------------------------------------------------------
957 gdk_keyboard_ungrab (guint32 time)
959 GDK_NOTE (EVENTS, g_print ("gdk_keyboard_ungrab\n"));
961 k_grab_window = NULL;
965 gdk_io_destroy (gpointer data)
967 GdkIOClosure *closure = data;
970 closure->notify (closure->data);
976 gdk_io_invoke (GIOChannel *source,
977 GIOCondition condition,
980 GdkIOClosure *closure = data;
981 GdkInputCondition gdk_cond = 0;
983 if (condition & (G_IO_IN | G_IO_PRI))
984 gdk_cond |= GDK_INPUT_READ;
985 if (condition & G_IO_OUT)
986 gdk_cond |= GDK_INPUT_WRITE;
987 if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
988 gdk_cond |= GDK_INPUT_EXCEPTION;
990 if (closure->condition & gdk_cond)
991 closure->function (closure->data, g_io_channel_unix_get_fd (source), gdk_cond);
997 gdk_input_add_full (gint source,
998 GdkInputCondition condition,
999 GdkInputFunction function,
1001 GdkDestroyNotify destroy)
1004 GdkIOClosure *closure = g_new (GdkIOClosure, 1);
1005 GIOChannel *channel;
1006 GIOCondition cond = 0;
1008 closure->function = function;
1009 closure->condition = condition;
1010 closure->notify = destroy;
1011 closure->data = data;
1013 if (condition & GDK_INPUT_READ)
1014 cond |= (G_IO_IN | G_IO_PRI);
1015 if (condition & GDK_INPUT_WRITE)
1017 if (condition & GDK_INPUT_EXCEPTION)
1018 cond |= G_IO_ERR|G_IO_HUP|G_IO_NVAL;
1020 channel = g_io_channel_unix_new (source);
1021 result = g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, cond,
1023 closure, gdk_io_destroy);
1024 g_io_channel_unref (channel);
1030 gdk_input_add (gint source,
1031 GdkInputCondition condition,
1032 GdkInputFunction function,
1035 return gdk_input_add_full (source, condition, function, data, NULL);
1039 gdk_input_remove (gint tag)
1041 g_source_remove (tag);
1044 static GdkFilterReturn
1045 gdk_event_apply_filters (MSG *xevent,
1049 GdkEventFilter *filter;
1051 GdkFilterReturn result;
1057 filter = (GdkEventFilter *) tmp_list->data;
1059 result = (*filter->function) (xevent, event, filter->data);
1060 if (result != GDK_FILTER_CONTINUE)
1063 tmp_list = tmp_list->next;
1066 return GDK_FILTER_CONTINUE;
1070 gdk_add_client_message_filter (GdkAtom message_type,
1074 GdkClientFilter *filter = g_new (GdkClientFilter, 1);
1076 filter->type = message_type;
1077 filter->function = func;
1078 filter->data = data;
1080 client_filters = g_list_prepend (client_filters, filter);
1084 synthesize_crossing_events (GdkWindow *window,
1088 GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
1089 GdkWindowPrivate *curWnd_private = (GdkWindowPrivate *) curWnd;
1091 if (curWnd && (curWnd_private->event_mask & GDK_LEAVE_NOTIFY_MASK))
1093 GDK_NOTE (EVENTS, g_print ("synthesizing LEAVE_NOTIFY event\n"));
1095 event = gdk_event_new ();
1096 event->crossing.type = GDK_LEAVE_NOTIFY;
1097 event->crossing.window = curWnd;
1098 gdk_window_ref (event->crossing.window);
1099 event->crossing.subwindow = NULL;
1100 event->crossing.time = xevent->time;
1101 event->crossing.x = curX;
1102 event->crossing.y = curY;
1103 event->crossing.x_root = curXroot;
1104 event->crossing.y_root = curYroot;
1105 event->crossing.mode = GDK_CROSSING_NORMAL;
1106 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
1108 event->crossing.focus = TRUE; /* ??? */
1109 event->crossing.state = 0; /* ??? */
1111 gdk_event_queue_append (event);
1114 if (window_private && (window_private->event_mask & GDK_ENTER_NOTIFY_MASK))
1116 GDK_NOTE (EVENTS, g_print ("synthesizing ENTER_NOTIFY event\n"));
1118 event = gdk_event_new ();
1119 event->crossing.type = GDK_ENTER_NOTIFY;
1120 event->crossing.window = window;
1121 gdk_window_ref (event->crossing.window);
1122 event->crossing.subwindow = NULL;
1123 event->crossing.time = xevent->time;
1124 event->crossing.x = LOWORD (xevent->lParam);
1125 event->crossing.y = HIWORD (xevent->lParam);
1126 event->crossing.x_root = (gfloat) xevent->pt.x;
1127 event->crossing.y_root = (gfloat) xevent->pt.y;
1128 event->crossing.mode = GDK_CROSSING_NORMAL;
1129 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
1131 event->crossing.focus = TRUE; /* ??? */
1132 event->crossing.state = 0; /* ??? */
1134 gdk_event_queue_append (event);
1136 if (window_private->extension_events != 0
1137 && gdk_input_vtable.enter_event)
1138 gdk_input_vtable.enter_event (&event->crossing, window);
1142 gdk_window_unref (curWnd);
1144 gdk_window_ref (curWnd);
1148 gdk_event_translate (GdkEvent *event,
1150 gboolean *ret_val_flagp,
1154 GdkWindowPrivate *window_private;
1156 GdkColormapPrivate *colormap_private;
1159 PAINTSTRUCT paintstruct;
1165 GdkWindowPrivate *curWnd_private;
1177 *ret_val_flagp = FALSE;
1179 if (xevent->message == gdk_ping_msg)
1181 /* Messages we post ourselves just to wakeup WaitMessage. */
1185 window = gdk_window_lookup (xevent->hwnd);
1186 window_private = (GdkWindowPrivate *) window;
1188 if (xevent->message == g_pipe_readable_msg)
1190 GDK_NOTE (EVENTS, g_print ("g_pipe_readable_msg: %d %d\n",
1191 xevent->wParam, xevent->lParam));
1193 g_io_channel_win32_pipe_readable (xevent->wParam, xevent->lParam);
1198 gdk_window_ref (window);
1201 /* Handle WM_QUIT here ? */
1202 if (xevent->message == WM_QUIT)
1204 GDK_NOTE (EVENTS, g_print ("WM_QUIT: %d\n", xevent->wParam));
1205 exit (xevent->wParam);
1207 else if (xevent->message == WM_MOVE
1208 || xevent->message == WM_SIZE)
1210 /* It's quite normal to get these messages before we have
1211 * had time to register the window in our lookup table, or
1212 * when the window is being destroyed and we already have
1213 * removed it. Repost the same message to our queue so that
1214 * we will get it later when we are prepared.
1216 PostMessage (xevent->hwnd, xevent->message,
1217 xevent->wParam, xevent->lParam);
1222 event->any.window = window;
1224 if (window_private && window_private->destroyed)
1229 /* Check for filters for this window */
1230 GdkFilterReturn result;
1231 result = gdk_event_apply_filters
1233 window_private ? window_private->filters : gdk_default_filters);
1235 if (result != GDK_FILTER_CONTINUE)
1237 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1241 if (xevent->message == gdk_selection_notify_msg)
1243 GDK_NOTE (SELECTION, g_print ("gdk_selection_notify_msg: %#x\n",
1246 event->selection.type = GDK_SELECTION_NOTIFY;
1247 event->selection.window = window;
1248 event->selection.selection = xevent->wParam;
1249 event->selection.target = xevent->lParam;
1250 event->selection.property = gdk_selection_property;
1251 event->selection.time = xevent->time;
1253 return_val = window_private && !window_private->destroyed;
1255 /* Will pass through switch below without match */
1257 else if (xevent->message == gdk_selection_request_msg)
1259 GDK_NOTE (SELECTION, g_print ("gdk_selection_request_msg: %#x\n",
1262 event->selection.type = GDK_SELECTION_REQUEST;
1263 event->selection.window = window;
1264 event->selection.selection = gdk_clipboard_atom;
1265 event->selection.target = GDK_TARGET_STRING;
1266 event->selection.property = gdk_selection_property;
1267 event->selection.requestor = (guint32) xevent->hwnd;
1268 event->selection.time = xevent->time;
1270 return_val = window_private && !window_private->destroyed;
1272 /* Again, will pass through switch below without match */
1274 else if (xevent->message == gdk_selection_clear_msg)
1276 GDK_NOTE (SELECTION, g_print ("gdk_selection_clear_msg: %#x\n",
1279 event->selection.type = GDK_SELECTION_CLEAR;
1280 event->selection.window = window;
1281 event->selection.selection = xevent->wParam;
1282 event->selection.time = xevent->time;
1284 return_val = window_private && !window_private->destroyed;
1286 /* Once again, we will pass through switch below without match */
1291 GdkFilterReturn result = GDK_FILTER_CONTINUE;
1293 tmp_list = client_filters;
1296 GdkClientFilter *filter = tmp_list->data;
1297 if (filter->type == xevent->message)
1299 GDK_NOTE (EVENTS, g_print ("client filter matched\n"));
1300 result = (*filter->function) (xevent, event, filter->data);
1303 case GDK_FILTER_REMOVE:
1307 case GDK_FILTER_TRANSLATE:
1311 case GDK_FILTER_CONTINUE:
1313 event->client.type = GDK_CLIENT_EVENT;
1314 event->client.window = window;
1315 event->client.message_type = xevent->message;
1316 event->client.data_format = 0;
1317 event->client.data.l[0] = xevent->wParam;
1318 event->client.data.l[1] = xevent->lParam;
1321 goto bypass_switch; /* Ouch */
1323 tmp_list = tmp_list->next;
1327 switch (xevent->message)
1332 g_print ("WM_SYSKEY%s: %#x key: %s %#x %#.08x\n",
1333 (xevent->message == WM_SYSKEYUP ? "UP" : "DOWN"),
1335 (GetKeyNameText (xevent->lParam, buf,
1341 /* Let the system handle Alt-Tab and Alt-Enter */
1342 if (xevent->wParam == VK_TAB
1343 || xevent->wParam == VK_RETURN
1344 || xevent->wParam == VK_F4)
1346 /* If posted without us having keyboard focus, ignore */
1347 if (!(xevent->lParam & 0x20000000))
1350 /* don't generate events for just the Alt key */
1351 if (xevent->wParam == VK_MENU)
1354 /* Jump to code in common with WM_KEYUP and WM_KEYDOWN */
1360 g_print ("WM_KEY%s: %#x key: %s %#x %#.08x\n",
1361 (xevent->message == WM_KEYUP ? "UP" : "DOWN"),
1363 (GetKeyNameText (xevent->lParam, buf,
1369 ignore_WM_CHAR = TRUE;
1371 if (k_grab_window != NULL
1372 && !k_grab_owner_events)
1374 /* Keyboard is grabbed with owner_events FALSE */
1376 g_print ("...grabbed, owner_events FALSE, "
1377 "sending to %#x\n", k_grab_window->xwindow));
1378 event->key.window = (GdkWindow *) k_grab_window;
1380 else if (window_private
1381 && (((xevent->message == WM_KEYUP
1382 || xevent->message == WM_SYSKEYUP)
1383 && !(window_private->event_mask & GDK_KEY_RELEASE_MASK))
1384 || ((xevent->message == WM_KEYDOWN
1385 || xevent->message == WM_SYSKEYDOWN)
1386 && !(window_private->event_mask & GDK_KEY_PRESS_MASK))))
1388 /* Owner window doesn't want it */
1389 if (k_grab_window != NULL
1390 && k_grab_owner_events)
1392 /* Keyboard is grabbed with owner_events TRUE */
1394 g_print ("...grabbed, owner_events TRUE, doesn't want it, "
1395 "sending to %#x\n", k_grab_window->xwindow));
1396 event->key.window = (GdkWindow *) k_grab_window;
1400 /* Owner doesn't want it, neither is it grabbed, so
1401 * propagate to parent.
1403 if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1405 gdk_window_unref (window);
1406 window = window_private->parent;
1407 gdk_window_ref (window);
1408 window_private = (GdkWindowPrivate *) window;
1409 GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
1410 window_private->xwindow));
1415 switch (xevent->wParam)
1418 event->key.keyval = GDK_Pointer_Button1; break;
1420 event->key.keyval = GDK_Pointer_Button3; break;
1422 event->key.keyval = GDK_Pointer_Button2; break;
1424 event->key.keyval = GDK_Cancel; break;
1426 event->key.keyval = GDK_BackSpace; break;
1428 event->key.keyval = (GetKeyState(VK_SHIFT) < 0 ?
1429 GDK_ISO_Left_Tab : GDK_Tab);
1432 event->key.keyval = GDK_Clear; break;
1434 event->key.keyval = GDK_Return; break;
1436 event->key.keyval = GDK_Shift_L; break;
1438 if (xevent->lParam & 0x01000000)
1439 event->key.keyval = GDK_Control_R;
1441 event->key.keyval = GDK_Control_L;
1444 if (xevent->lParam & 0x01000000)
1446 /* AltGr key comes in as Control+Right Alt */
1447 if (GetKeyState (VK_CONTROL) < 0)
1449 ignore_WM_CHAR = FALSE;
1450 is_AltGr_key = TRUE;
1452 event->key.keyval = GDK_Alt_R;
1455 event->key.keyval = GDK_Alt_L;
1458 event->key.keyval = GDK_Pause; break;
1460 event->key.keyval = GDK_Caps_Lock; break;
1462 event->key.keyval = GDK_Escape; break;
1464 event->key.keyval = GDK_Prior; break;
1466 event->key.keyval = GDK_Next; break;
1468 event->key.keyval = GDK_End; break;
1470 event->key.keyval = GDK_Home; break;
1472 event->key.keyval = GDK_Left; break;
1474 event->key.keyval = GDK_Up; break;
1476 event->key.keyval = GDK_Right; break;
1478 event->key.keyval = GDK_Down; break;
1480 event->key.keyval = GDK_Select; break;
1482 event->key.keyval = GDK_Print; break;
1484 event->key.keyval = GDK_Execute; break;
1486 event->key.keyval = GDK_Insert; break;
1488 event->key.keyval = GDK_Delete; break;
1490 event->key.keyval = GDK_Help; break;
1501 /* Apparently applications work better if we just pass numpad digits
1502 * on as real digits? So wait for the WM_CHAR instead.
1504 ignore_WM_CHAR = FALSE;
1507 event->key.keyval = GDK_KP_Multiply; break;
1510 event->key.keyval = GDK_KP_Add; break;
1512 /* Pass it on as an ASCII plus in WM_CHAR. */
1513 ignore_WM_CHAR = FALSE;
1517 event->key.keyval = GDK_KP_Separator; break;
1520 event->key.keyval = GDK_KP_Subtract; break;
1522 /* Pass it on as an ASCII minus in WM_CHAR. */
1523 ignore_WM_CHAR = FALSE;
1528 event->key.keyval = GDK_KP_Decimal; break;
1530 /* The keypad decimal key should also be passed on as the decimal
1531 * sign ('.' or ',' depending on the Windows locale settings,
1532 * apparently). So wait for the WM_CHAR here, also.
1534 ignore_WM_CHAR = FALSE;
1538 event->key.keyval = GDK_KP_Divide; break;
1540 event->key.keyval = GDK_F1; break;
1542 event->key.keyval = GDK_F2; break;
1544 event->key.keyval = GDK_F3; break;
1546 event->key.keyval = GDK_F4; break;
1548 event->key.keyval = GDK_F5; break;
1550 event->key.keyval = GDK_F6; break;
1552 event->key.keyval = GDK_F7; break;
1554 event->key.keyval = GDK_F8; break;
1556 event->key.keyval = GDK_F9; break;
1558 event->key.keyval = GDK_F10; break;
1560 event->key.keyval = GDK_F11; break;
1562 event->key.keyval = GDK_F12; break;
1564 event->key.keyval = GDK_F13; break;
1566 event->key.keyval = GDK_F14; break;
1568 event->key.keyval = GDK_F15; break;
1570 event->key.keyval = GDK_F16; break;
1581 if (!is_AltGr_key && (GetKeyState (VK_CONTROL) < 0
1582 || GetKeyState (VK_MENU) < 0))
1583 /* Control- or Alt-digits won't come in as a WM_CHAR */
1584 event->key.keyval = GDK_0 + (xevent->wParam - '0');
1587 ignore_WM_CHAR = FALSE;
1588 event->key.keyval = GDK_VoidSymbol;
1592 if (xevent->message == WM_SYSKEYDOWN || xevent->message == WM_SYSKEYUP)
1594 event->key.keyval = xevent->wParam;
1598 ignore_WM_CHAR = FALSE;
1599 event->key.keyval = GDK_VoidSymbol;
1604 if (!ignore_WM_CHAR)
1607 is_AltGr_key = FALSE;
1608 event->key.type = ((xevent->message == WM_KEYDOWN
1609 || xevent->message == WM_SYSKEYDOWN) ?
1610 GDK_KEY_PRESS : GDK_KEY_RELEASE);
1611 event->key.window = window;
1612 event->key.time = xevent->time;
1613 event->key.state = 0;
1614 if (GetKeyState (VK_SHIFT) < 0)
1615 event->key.state |= GDK_SHIFT_MASK;
1616 if (GetKeyState (VK_CAPITAL) & 0x1)
1617 event->key.state |= GDK_LOCK_MASK;
1618 if (GetKeyState (VK_CONTROL) < 0)
1619 event->key.state |= GDK_CONTROL_MASK;
1620 if (xevent->wParam != VK_MENU && GetKeyState (VK_MENU) < 0)
1621 event->key.state |= GDK_MOD1_MASK;
1622 return_val = window_private && !window_private->destroyed;
1623 event->key.string = NULL;
1624 event->key.length = 0;
1629 g_print ("WM_CHAR: %#x char: %#x %#.08x %s\n",
1633 (ignore_WM_CHAR ? "ignored" : "")));
1637 ignore_WM_CHAR = FALSE;
1642 /* This doesn't handle the rather theorethical case that a window
1643 * wants key presses but still wants releases to be propagated,
1646 if (k_grab_window != NULL
1647 && !k_grab_owner_events)
1649 /* Keyboard is grabbed with owner_events FALSE */
1651 g_print ("...grabbed, owner_events FALSE, "
1652 "sending to %#x\n", k_grab_window->xwindow));
1653 event->key.window = (GdkWindow *) k_grab_window;
1655 else if (window_private
1656 && !(window_private->event_mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK)))
1658 /* Owner window doesn't want it */
1659 if (k_grab_window != NULL
1660 && k_grab_owner_events)
1662 /* Keyboard is grabbed with owner_events TRUE */
1664 g_print ("...grabbed, owner_events TRUE, doesn't want it, "
1665 "sending to %#x\n", k_grab_window->xwindow));
1666 event->key.window = (GdkWindow *) k_grab_window;
1670 /* Owner doesn't want it, neither is it grabbed, so
1671 * propagate to parent.
1673 if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1674 g_assert_not_reached (); /* Should've been handled above */
1676 gdk_window_unref (window);
1677 window = window_private->parent;
1678 gdk_window_ref (window);
1679 window_private = (GdkWindowPrivate *) window;
1680 GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
1681 window_private->xwindow));
1686 return_val = window_private && !window_private->destroyed;
1687 if (return_val && (window_private->event_mask & GDK_KEY_RELEASE_MASK))
1689 /* Return the release event, and maybe append the press
1690 * event to the queued_events list (from which it will vbe
1691 * fetched before the release event).
1693 event->key.type = GDK_KEY_RELEASE;
1694 event->key.keyval = xevent->wParam;
1695 event->key.window = window;
1696 event->key.time = xevent->time;
1697 event->key.state = 0;
1698 if (GetKeyState (VK_SHIFT) < 0)
1699 event->key.state |= GDK_SHIFT_MASK;
1700 if (GetKeyState (VK_CAPITAL) & 0x1)
1701 event->key.state |= GDK_LOCK_MASK;
1704 else if (GetKeyState (VK_CONTROL) < 0)
1706 event->key.state |= GDK_CONTROL_MASK;
1707 if (event->key.keyval < ' ')
1708 event->key.keyval += '@';
1710 else if (event->key.keyval < ' ')
1712 event->key.state |= GDK_CONTROL_MASK;
1713 event->key.keyval += '@';
1715 if (!is_AltGr_key && GetKeyState (VK_MENU) < 0)
1716 event->key.state |= GDK_MOD1_MASK;
1717 event->key.string = g_malloc (2);
1718 event->key.length = 1;
1719 event->key.string[0] = xevent->wParam; /* ??? */
1720 event->key.string[1] = 0;
1722 if (window_private->event_mask & GDK_KEY_PRESS_MASK)
1724 /* Append also a GDK_KEY_PRESS event to the pushback list. */
1725 GdkEvent *event2 = gdk_event_copy (event);
1726 event2->key.type = GDK_KEY_PRESS;
1727 charcount = xevent->lParam & 0xFFFF;
1728 if (charcount > sizeof (buf)- 1)
1729 charcount = sizeof (buf) - 1;
1730 g_free (event2->key.string);
1731 event2->key.string = g_malloc (charcount + 1);
1732 for (i = 0; i < charcount; i++)
1733 event2->key.string[i] = event->key.keyval;
1734 event2->key.string[charcount] = 0;
1735 event2->key.length = charcount;
1737 gdk_event_queue_append (event2);
1740 else if (return_val && (window_private->event_mask & GDK_KEY_PRESS_MASK))
1742 /* Return just the GDK_KEY_PRESS event. */
1743 event->key.type = GDK_KEY_PRESS;
1744 charcount = xevent->lParam & 0xFFFF;
1745 if (charcount > sizeof (buf)- 1)
1746 charcount = sizeof (buf) - 1;
1747 event->key.keyval = xevent->wParam;
1748 event->key.window = window;
1749 event->key.time = xevent->time;
1750 event->key.state = 0;
1751 if (GetKeyState (VK_SHIFT) < 0)
1752 event->key.state |= GDK_SHIFT_MASK;
1753 if (GetKeyState (VK_CAPITAL) & 0x1)
1754 event->key.state |= GDK_LOCK_MASK;
1757 else if (GetKeyState (VK_CONTROL) < 0)
1759 event->key.state |= GDK_CONTROL_MASK;
1760 if (event->key.keyval < ' ')
1761 event->key.keyval += '@';
1763 else if (event->key.keyval < ' ')
1765 event->key.state |= GDK_CONTROL_MASK;
1766 event->key.keyval += '@';
1768 if (!is_AltGr_key && GetKeyState (VK_MENU) < 0)
1769 event->key.state |= GDK_MOD1_MASK;
1770 event->key.string = g_malloc (charcount + 1);
1771 for (i = 0; i < charcount; i++)
1772 event->key.string[i] = event->key.keyval;
1773 event->key.string[charcount] = 0;
1774 event->key.length = charcount;
1778 #if 0 /* Don't reset is_AltGr_key here. Othewise we can't type several
1779 * AltGr-accessed chars while keeping the AltGr pressed down
1782 is_AltGr_key = FALSE;
1786 case WM_LBUTTONDOWN:
1789 case WM_MBUTTONDOWN:
1792 case WM_RBUTTONDOWN:
1797 g_print ("WM_%cBUTTONDOWN: %#x x,y: %d %d button: %d\n",
1800 LOWORD (xevent->lParam), HIWORD (xevent->lParam),
1804 && (window_private->extension_events != 0)
1805 && gdk_input_ignore_core)
1807 GDK_NOTE (EVENTS, g_print ("...ignored\n"));
1811 if (window != curWnd)
1812 synthesize_crossing_events (window, xevent);
1814 event->button.type = GDK_BUTTON_PRESS;
1816 event->button.window = window;
1818 mask = window_private->event_mask;
1822 if (p_grab_window != NULL
1823 && !p_grab_owner_events)
1825 /* Pointer is grabbed with owner_events FALSE */
1826 GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE\n"));
1827 mask = p_grab_event_mask;
1828 if (!(mask & GDK_BUTTON_PRESS_MASK))
1829 /* Grabber doesn't want it */
1832 event->button.window = (GdkWindow *) p_grab_window;
1833 GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
1834 p_grab_window->xwindow));
1836 else if (window_private
1837 && !(mask & GDK_BUTTON_PRESS_MASK))
1839 /* Owner window doesn't want it */
1840 if (p_grab_window != NULL
1841 && p_grab_owner_events)
1843 /* Pointer is grabbed wÃth owner_events TRUE */
1844 GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
1845 mask = p_grab_event_mask;
1846 if (!(mask & GDK_BUTTON_PRESS_MASK))
1847 /* Grabber doesn't want it either */
1850 event->button.window = (GdkWindow *) p_grab_window;
1851 GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
1852 p_grab_window->xwindow));
1856 /* Owner doesn't want it, neither is it grabbed, so
1857 * propagate to parent.
1859 /* Yes, this code is duplicated twice below. So shoot me. */
1860 if (window_private->parent == (GdkWindow *) &gdk_root_parent)
1862 pt.x = LOWORD (xevent->lParam);
1863 pt.y = HIWORD (xevent->lParam);
1864 ClientToScreen (window_private->xwindow, &pt);
1865 gdk_window_unref (window);
1866 window = window_private->parent;
1867 gdk_window_ref (window);
1868 window_private = (GdkWindowPrivate *) window;
1869 ScreenToClient (window_private->xwindow, &pt);
1870 xevent->lParam = MAKELPARAM (pt.x, pt.y);
1871 GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
1872 window_private->xwindow));
1873 goto buttondown; /* What did Dijkstra say? */
1877 /* Emulate X11's automatic active grab */
1880 /* No explicit active grab, let's start one automatically */
1881 GDK_NOTE (EVENTS, g_print ("...automatic grab started\n"));
1882 gdk_pointer_grab (window, TRUE, window_private->event_mask,
1884 p_grab_automatic = TRUE;
1887 event->button.time = xevent->time;
1888 event->button.x = LOWORD (xevent->lParam);
1889 event->button.y = HIWORD (xevent->lParam);
1890 event->button.x_root = (gfloat)xevent->pt.x;
1891 event->button.y_root = (gfloat)xevent->pt.y;
1892 event->button.pressure = 0.5;
1893 event->button.xtilt = 0;
1894 event->button.ytilt = 0;
1895 event->button.state = 0;
1896 if (xevent->wParam & MK_CONTROL)
1897 event->button.state |= GDK_CONTROL_MASK;
1898 if (xevent->wParam & MK_LBUTTON)
1899 event->button.state |= GDK_BUTTON1_MASK;
1900 if (xevent->wParam & MK_MBUTTON)
1901 event->button.state |= GDK_BUTTON2_MASK;
1902 if (xevent->wParam & MK_RBUTTON)
1903 event->button.state |= GDK_BUTTON3_MASK;
1904 if (xevent->wParam & MK_SHIFT)
1905 event->button.state |= GDK_SHIFT_MASK;
1906 if (GetKeyState (VK_MENU) < 0)
1907 event->button.state |= GDK_MOD1_MASK;
1908 if (GetKeyState (VK_CAPITAL) & 0x1)
1909 event->button.state |= GDK_LOCK_MASK;
1910 event->button.button = button;
1911 event->button.source = GDK_SOURCE_MOUSE;
1912 event->button.deviceid = GDK_CORE_POINTER;
1914 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1915 (event->button.window == button_window[1]) &&
1916 (event->button.button == button_number[1]))
1918 gdk_synthesize_click (event, 3);
1920 button_click_time[1] = 0;
1921 button_click_time[0] = 0;
1922 button_window[1] = NULL;
1923 button_window[0] = 0;
1924 button_number[1] = -1;
1925 button_number[0] = -1;
1927 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1928 (event->button.window == button_window[0]) &&
1929 (event->button.button == button_number[0]))
1931 gdk_synthesize_click (event, 2);
1933 button_click_time[1] = button_click_time[0];
1934 button_click_time[0] = event->button.time;
1935 button_window[1] = button_window[0];
1936 button_window[0] = event->button.window;
1937 button_number[1] = button_number[0];
1938 button_number[0] = event->button.button;
1942 button_click_time[1] = 0;
1943 button_click_time[0] = event->button.time;
1944 button_window[1] = NULL;
1945 button_window[0] = event->button.window;
1946 button_number[1] = -1;
1947 button_number[0] = event->button.button;
1949 return_val = window_private && !window_private->destroyed;
1951 && p_grab_window != NULL
1952 && event->any.window == (GdkWindow *) p_grab_window
1953 && p_grab_window != window_private)
1955 /* Translate coordinates to grabber */
1956 pt.x = event->button.x;
1957 pt.y = event->button.y;
1958 ClientToScreen (window_private->xwindow, &pt);
1959 ScreenToClient (p_grab_window->xwindow, &pt);
1960 event->button.x = pt.x;
1961 event->button.y = pt.y;
1962 GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
1977 g_print ("WM_%cBUTTONUP: %#x x,y: %d %d button: %d\n",
1980 LOWORD (xevent->lParam), HIWORD (xevent->lParam),
1984 && (window_private->extension_events != 0)
1985 && gdk_input_ignore_core)
1987 GDK_NOTE (EVENTS, g_print ("...ignored\n"));
1991 if (window != curWnd)
1992 synthesize_crossing_events (window, xevent);
1994 event->button.type = GDK_BUTTON_RELEASE;
1996 event->button.window = window;
1998 mask = window_private->event_mask;
2002 if (p_grab_window != NULL
2003 && !p_grab_owner_events)
2005 /* Pointer is grabbed with owner_events FALSE */
2006 GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE\n"));
2007 mask = p_grab_event_mask;
2008 if (!(mask & GDK_BUTTON_RELEASE_MASK))
2009 /* Grabber doesn't want it */
2012 event->button.window = (GdkWindow *) p_grab_window;
2013 GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
2014 p_grab_window->xwindow));
2016 else if (window_private
2017 && !(mask & GDK_BUTTON_RELEASE_MASK))
2019 /* Owner window doesn't want it */
2020 if (p_grab_window != NULL
2021 && p_grab_owner_events)
2023 /* Pointer is grabbed wÃth owner_events TRUE */
2024 GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
2025 mask = p_grab_event_mask;
2026 if (!(mask & GDK_BUTTON_RELEASE_MASK))
2027 /* Grabber doesn't want it */
2030 event->button.window = (GdkWindow *) p_grab_window;
2031 GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
2032 p_grab_window->xwindow));
2036 /* Owner doesn't want it, neither is it grabbed, so
2037 * propagate to parent.
2039 if (window_private->parent == (GdkWindow *) &gdk_root_parent)
2041 pt.x = LOWORD (xevent->lParam);
2042 pt.y = HIWORD (xevent->lParam);
2043 ClientToScreen (window_private->xwindow, &pt);
2044 gdk_window_unref (window);
2045 window = window_private->parent;
2046 gdk_window_ref (window);
2047 window_private = (GdkWindowPrivate *) window;
2048 ScreenToClient (window_private->xwindow, &pt);
2049 xevent->lParam = MAKELPARAM (pt.x, pt.y);
2050 GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
2051 window_private->xwindow));
2056 event->button.time = xevent->time;
2057 event->button.x = LOWORD (xevent->lParam);
2058 event->button.y = HIWORD (xevent->lParam);
2059 event->button.x_root = (gfloat)xevent->pt.x;
2060 event->button.y_root = (gfloat)xevent->pt.y;
2061 event->button.pressure = 0.5;
2062 event->button.xtilt = 0;
2063 event->button.ytilt = 0;
2064 event->button.state = 0;
2065 if (xevent->wParam & MK_CONTROL)
2066 event->button.state |= GDK_CONTROL_MASK;
2067 if (xevent->wParam & MK_LBUTTON)
2068 event->button.state |= GDK_BUTTON1_MASK;
2069 if (xevent->wParam & MK_MBUTTON)
2070 event->button.state |= GDK_BUTTON2_MASK;
2071 if (xevent->wParam & MK_RBUTTON)
2072 event->button.state |= GDK_BUTTON3_MASK;
2073 if (xevent->wParam & MK_SHIFT)
2074 event->button.state |= GDK_SHIFT_MASK;
2075 event->button.button = button;
2076 event->button.source = GDK_SOURCE_MOUSE;
2077 event->button.deviceid = GDK_CORE_POINTER;
2078 return_val = window_private && !window_private->destroyed;
2080 && p_grab_window != NULL
2081 && event->any.window == (GdkWindow *) p_grab_window
2082 && p_grab_window != window_private)
2084 /* Translate coordinates to grabber */
2085 pt.x = event->button.x;
2086 pt.y = event->button.y;
2087 ClientToScreen (window_private->xwindow, &pt);
2088 ScreenToClient (p_grab_window->xwindow, &pt);
2089 event->button.x = pt.x;
2090 event->button.y = pt.y;
2091 GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
2093 if (p_grab_window != NULL
2095 && (event->button.state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) == 0)
2096 gdk_pointer_ungrab (0);
2101 g_print ("WM_MOUSEMOVE: %#x %#x +%d+%d\n",
2102 xevent->hwnd, xevent->wParam,
2103 LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2106 /* Try hard not to generate events for windows that shouldn't
2107 get any. This is hard because we don't want pushbuttons to
2108 highlight when the cursor moves over them if the window is
2109 inactive. We dont want tooltips windows to be active. OTOH,
2110 also menus are popup windows, but they definitely should
2111 get events. Aw shit. Skip this.
2113 dwStyle = GetWindowLong (xevent->hwnd, GWL_STYLE);
2114 if (active == NULL ||
2115 !(active == xevent->hwnd
2116 || (dwStyle & WS_POPUP)
2117 || IsChild (active, xevent->hwnd)))
2120 { /* HB: only process mouse move messages
2121 * if we own the active window.
2123 DWORD ProcessID_ActWin;
2124 DWORD ProcessID_this;
2126 GetWindowThreadProcessId(GetActiveWindow(), &ProcessID_ActWin);
2127 GetWindowThreadProcessId(xevent->hwnd, &ProcessID_this);
2128 if (ProcessID_ActWin != ProcessID_this)
2132 if (window != curWnd)
2133 synthesize_crossing_events (window, xevent);
2136 && (window_private->extension_events != 0)
2137 && gdk_input_ignore_core)
2139 GDK_NOTE (EVENTS, g_print ("...ignored\n"));
2144 event->motion.type = GDK_MOTION_NOTIFY;
2145 event->motion.window = window;
2147 mask = window_private->event_mask;
2152 && !p_grab_owner_events)
2154 /* Pointer is grabbed with owner_events FALSE */
2156 g_print ("...grabbed, owner_events FALSE\n"));
2157 mask = p_grab_event_mask;
2158 if (!((mask & GDK_POINTER_MOTION_MASK)
2159 || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
2160 && (mask & GDK_BUTTON_MOTION_MASK))
2161 || ((xevent->wParam & MK_LBUTTON)
2162 && (mask & GDK_BUTTON1_MOTION_MASK))
2163 || ((xevent->wParam & MK_MBUTTON)
2164 && (mask & GDK_BUTTON2_MOTION_MASK))
2165 || ((xevent->wParam & MK_RBUTTON)
2166 && (mask & GDK_BUTTON3_MOTION_MASK))))
2169 event->motion.window = (GdkWindow *) p_grab_window;
2170 GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
2171 p_grab_window->xwindow));
2173 else if (window_private
2174 && !((mask & GDK_POINTER_MOTION_MASK)
2175 || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
2176 && (mask & GDK_BUTTON_MOTION_MASK))
2177 || ((xevent->wParam & MK_LBUTTON)
2178 && (mask & GDK_BUTTON1_MOTION_MASK))
2179 || ((xevent->wParam & MK_MBUTTON)
2180 && (mask & GDK_BUTTON2_MOTION_MASK))
2181 || ((xevent->wParam & MK_RBUTTON)
2182 && (mask & GDK_BUTTON3_MOTION_MASK))))
2184 /* Owner window doesn't want it */
2185 if (p_grab_window != NULL
2186 && p_grab_owner_events)
2188 /* Pointer is grabbed wÃth owner_events TRUE */
2189 GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
2190 mask = p_grab_event_mask;
2191 if (!((p_grab_event_mask & GDK_POINTER_MOTION_MASK)
2192 || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
2193 && (mask & GDK_BUTTON_MOTION_MASK))
2194 || ((xevent->wParam & MK_LBUTTON)
2195 && (mask & GDK_BUTTON1_MOTION_MASK))
2196 || ((xevent->wParam & MK_MBUTTON)
2197 && (mask & GDK_BUTTON2_MOTION_MASK))
2198 || ((xevent->wParam & MK_RBUTTON)
2199 && (mask & GDK_BUTTON3_MOTION_MASK))))
2200 /* Grabber doesn't want it either */
2203 event->motion.window = (GdkWindow *) p_grab_window;
2204 GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
2205 p_grab_window->xwindow));
2209 /* Owner doesn't want it, neither is it grabbed, so
2210 * propagate to parent.
2212 if (window_private->parent == (GdkWindow *) &gdk_root_parent)
2214 pt.x = LOWORD (xevent->lParam);
2215 pt.y = HIWORD (xevent->lParam);
2216 ClientToScreen (window_private->xwindow, &pt);
2217 gdk_window_unref (window);
2218 window = window_private->parent;
2219 gdk_window_ref (window);
2220 window_private = (GdkWindowPrivate *) window;
2221 ScreenToClient (window_private->xwindow, &pt);
2222 xevent->lParam = MAKELPARAM (pt.x, pt.y);
2223 GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
2224 window_private->xwindow));
2229 event->motion.time = xevent->time;
2230 event->motion.x = curX = LOWORD (xevent->lParam);
2231 event->motion.y = curY = HIWORD (xevent->lParam);
2232 event->motion.x_root = xevent->pt.x;
2233 event->motion.y_root = xevent->pt.y;
2234 curXroot = event->motion.x_root;
2235 curYroot = event->motion.y_root;
2236 event->motion.pressure = 0.5;
2237 event->motion.xtilt = 0;
2238 event->motion.ytilt = 0;
2239 event->button.state = 0;
2240 if (xevent->wParam & MK_CONTROL)
2241 event->button.state |= GDK_CONTROL_MASK;
2242 if (xevent->wParam & MK_LBUTTON)
2243 event->button.state |= GDK_BUTTON1_MASK;
2244 if (xevent->wParam & MK_MBUTTON)
2245 event->button.state |= GDK_BUTTON2_MASK;
2246 if (xevent->wParam & MK_RBUTTON)
2247 event->button.state |= GDK_BUTTON3_MASK;
2248 if (xevent->wParam & MK_SHIFT)
2249 event->button.state |= GDK_SHIFT_MASK;
2250 if (mask & GDK_POINTER_MOTION_HINT_MASK)
2251 event->motion.is_hint = NotifyHint;
2253 event->motion.is_hint = NotifyNormal;
2254 event->motion.source = GDK_SOURCE_MOUSE;
2255 event->motion.deviceid = GDK_CORE_POINTER;
2257 return_val = window_private && !window_private->destroyed;
2259 && p_grab_window != NULL
2260 && event->any.window == (GdkWindow *) p_grab_window
2261 && p_grab_window != window_private)
2263 /* Translate coordinates to grabber */
2264 pt.x = event->motion.x;
2265 pt.y = event->motion.y;
2266 ClientToScreen (window_private->xwindow, &pt);
2267 ScreenToClient (p_grab_window->xwindow, &pt);
2268 event->motion.x = pt.x;
2269 event->motion.y = pt.y;
2270 GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
2274 case WM_NCMOUSEMOVE:
2276 g_print ("WM_NCMOUSEMOVE: %#x x,y: %d %d\n",
2278 LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2280 if (active == NULL || active != xevent->hwnd)
2283 curWnd_private = (GdkWindowPrivate *) curWnd;
2285 && (curWnd_private->event_mask & GDK_LEAVE_NOTIFY_MASK))
2287 GDK_NOTE (EVENTS, g_print ("...synthesizing LEAVE_NOTIFY event\n"));
2289 event->crossing.type = GDK_LEAVE_NOTIFY;
2290 event->crossing.window = curWnd;
2291 event->crossing.subwindow = NULL;
2292 event->crossing.time = xevent->time;
2293 event->crossing.x = curX;
2294 event->crossing.y = curY;
2295 event->crossing.x_root = curXroot;
2296 event->crossing.y_root = curYroot;
2297 event->crossing.mode = GDK_CROSSING_NORMAL;
2298 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
2300 event->crossing.focus = TRUE; /* ??? */
2301 event->crossing.state = 0; /* ??? */
2302 gdk_window_unref (curWnd);
2312 && !(window_private->event_mask & GDK_FOCUS_CHANGE_MASK))
2315 GDK_NOTE (EVENTS, g_print ("WM_%sFOCUS: %#x\n",
2316 (xevent->message == WM_SETFOCUS ? "SET" : "KILL"),
2319 event->focus_change.type = GDK_FOCUS_CHANGE;
2320 event->focus_change.window = window;
2321 event->focus_change.in = (xevent->message == WM_SETFOCUS);
2322 return_val = window_private && !window_private->destroyed;
2326 GDK_NOTE (EVENTS, g_print ("WM_ACTIVATE: %#x %d\n",
2327 xevent->hwnd, LOWORD (xevent->wParam)));
2328 if (LOWORD (xevent->wParam) == WA_INACTIVE)
2329 active = (HWND) xevent->lParam;
2331 active = xevent->hwnd;
2335 GDK_NOTE (EVENTS, g_print ("WM_ERASEBKGND: %#x dc %#x\n",
2336 xevent->hwnd, xevent->wParam));
2338 if (!window_private || window_private->destroyed)
2340 colormap_private = (GdkColormapPrivate *) window_private->colormap;
2341 hdc = (HDC) xevent->wParam;
2342 if (colormap_private
2343 && colormap_private->xcolormap->rc_palette)
2347 if (SelectPalette (hdc, colormap_private->xcolormap->palette,
2349 g_warning ("WM_ERASEBKGND: SelectPalette failed");
2350 if ((k = RealizePalette (hdc)) == GDI_ERROR)
2351 g_warning ("WM_ERASEBKGND: RealizePalette failed");
2353 g_print ("WM_ERASEBKGND: selected %#x, realized %d colors\n",
2354 colormap_private->xcolormap->palette, k);
2357 *ret_val_flagp = TRUE;
2360 if (window_private->bg_type == GDK_WIN32_BG_TRANSPARENT)
2363 if (window_private->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
2365 /* If this window should have the same background as the
2366 * parent, fetch the parent. (And if the same goes for
2367 * the parent, fetch the grandparent, etc.)
2369 while (window_private
2370 && window_private->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
2371 window_private = (GdkWindowPrivate *) window_private->parent;
2374 if (window_private->bg_type == GDK_WIN32_BG_PIXEL)
2377 GetClipBox (hdc, &rect);
2378 GDK_NOTE (EVENTS, g_print ("...%dx%d@+%d+%d BG_PIXEL %s\n",
2379 rect.right - rect.left,
2380 rect.bottom - rect.top,
2381 rect.left, rect.top,
2382 gdk_color_to_string (&window_private->bg_pixel)));
2383 bg = GetNearestColor (hdc, RGB (window_private->bg_pixel.red >> 8,
2384 window_private->bg_pixel.green >> 8,
2385 window_private->bg_pixel.blue >> 8));
2386 hbr = CreateSolidBrush (bg);
2388 g_print ("...CreateSolidBrush (%.08x) = %.08x\n", bg, hbr);
2390 if (!FillRect (hdc, &rect, hbr))
2391 g_warning ("WM_ERASEBKGND: FillRect failed");
2394 else if (window_private->bg_type == GDK_WIN32_BG_PIXMAP)
2396 GdkPixmapPrivate *pixmap_private;
2400 pixmap_private = (GdkPixmapPrivate *) window_private->bg_pixmap;
2401 GetClipBox (hdc, &rect);
2403 if (pixmap_private->width <= 8
2404 && pixmap_private->height <= 8)
2406 GDK_NOTE (EVENTS, g_print ("...small pixmap, using brush\n"));
2407 hbr = CreatePatternBrush (pixmap_private->xwindow);
2408 if (!FillRect (hdc, &rect, hbr))
2409 g_warning ("WM_ERASEBKGND: FillRect failed");
2415 g_print ("...blitting pixmap %#x (%dx%d) "
2416 "all over the place,\n"
2417 "...clip box = %dx%d@+%d+%d\n",
2418 pixmap_private->xwindow,
2419 pixmap_private->width, pixmap_private->height,
2420 rect.right - rect.left, rect.bottom - rect.top,
2421 rect.left, rect.top));
2423 if (!(bgdc = CreateCompatibleDC (hdc)))
2425 g_warning ("WM_ERASEBKGND: CreateCompatibleDC failed");
2428 if (!(oldbitmap = SelectObject (bgdc, pixmap_private->xwindow)))
2430 g_warning ("WM_ERASEBKGND: SelectObject failed");
2435 while (i < rect.right)
2438 while (j < rect.bottom)
2440 if (i + pixmap_private->width >= rect.left
2441 && j + pixmap_private->height >= rect.top)
2443 if (!BitBlt (hdc, i, j,
2444 pixmap_private->width, pixmap_private->height,
2445 bgdc, 0, 0, SRCCOPY))
2447 g_warning ("WM_ERASEBKGND: BitBlt failed");
2451 j += pixmap_private->height;
2453 i += pixmap_private->width;
2456 SelectObject (bgdc, oldbitmap);
2462 GDK_NOTE (EVENTS, g_print ("...BLACK_BRUSH (?)\n"));
2463 hbr = GetStockObject (BLACK_BRUSH);
2464 GetClipBox (hdc, &rect);
2465 if (!FillRect (hdc, &rect, hbr))
2466 g_warning ("WM_ERASEBKGND: FillRect failed");
2471 hdc = BeginPaint (xevent->hwnd, &paintstruct);
2474 g_print ("WM_PAINT: %#x %dx%d@+%d+%d %s dc %#x\n",
2476 paintstruct.rcPaint.right - paintstruct.rcPaint.left,
2477 paintstruct.rcPaint.bottom - paintstruct.rcPaint.top,
2478 paintstruct.rcPaint.left, paintstruct.rcPaint.top,
2479 (paintstruct.fErase ? "erase" : ""),
2482 EndPaint (xevent->hwnd, &paintstruct);
2485 && !(window_private->event_mask & GDK_EXPOSURE_MASK))
2488 event->expose.type = GDK_EXPOSE;
2489 event->expose.window = window;
2490 event->expose.area.x = paintstruct.rcPaint.left;
2491 event->expose.area.y = paintstruct.rcPaint.top;
2492 event->expose.area.width = paintstruct.rcPaint.right - paintstruct.rcPaint.left;
2493 event->expose.area.height = paintstruct.rcPaint.bottom - paintstruct.rcPaint.top;
2494 event->expose.count = 0;
2496 return_val = window_private && !window_private->destroyed;
2499 GList *list = queued_events;
2500 while (list != NULL )
2502 if ((((GdkEvent *)list->data)->any.type == GDK_EXPOSE) &&
2503 (((GdkEvent *)list->data)->any.window == window) &&
2504 !(((GdkEventPrivate *)list->data)->flags & GDK_EVENT_PENDING))
2505 ((GdkEvent *)list->data)->expose.count++;
2513 GDK_NOTE (EVENTS, g_print ("WM_SETCURSOR: %#x %#x %#x\n",
2515 LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2518 if (LOWORD (xevent->lParam) != HTCLIENT)
2520 if (p_grab_window != NULL && p_grab_cursor != NULL)
2522 GDK_NOTE (EVENTS, g_print ("...SetCursor(%#x)\n", p_grab_cursor));
2523 SetCursor (p_grab_cursor);
2525 else if (window_private
2526 && !window_private->destroyed
2527 && window_private->xcursor)
2529 GDK_NOTE (EVENTS, g_print ("...SetCursor(%#x)\n",
2530 window_private->xcursor));
2531 SetCursor (window_private->xcursor);
2533 *ret_val_flagp = TRUE;
2539 GDK_NOTE (EVENTS, g_print ("WM_QUERYOPEN: %#x\n",
2541 *ret_val_flagp = TRUE;
2545 && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2548 event->any.type = GDK_MAP;
2549 event->any.window = window;
2551 return_val = window_private && !window_private->destroyed;
2557 GDK_NOTE (EVENTS, g_print ("WM_SHOWWINDOW: %#x %d\n",
2562 && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2565 event->any.type = (xevent->wParam ? GDK_MAP : GDK_UNMAP);
2566 event->any.window = window;
2568 if (event->any.type == GDK_UNMAP
2569 && p_grab_window == window_private)
2570 gdk_pointer_ungrab (xevent->time);
2572 if (event->any.type == GDK_UNMAP
2573 && k_grab_window == window_private)
2574 gdk_keyboard_ungrab (xevent->time);
2576 return_val = window_private && !window_private->destroyed;
2581 g_print ("WM_SIZE: %#x %s %dx%d\n",
2583 (xevent->wParam == SIZE_MAXHIDE ? "MAXHIDE" :
2584 (xevent->wParam == SIZE_MAXIMIZED ? "MAXIMIZED" :
2585 (xevent->wParam == SIZE_MAXSHOW ? "MAXSHOW" :
2586 (xevent->wParam == SIZE_MINIMIZED ? "MINIMIZED" :
2587 (xevent->wParam == SIZE_RESTORED ? "RESTORED" : "?"))))),
2588 LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2591 && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2593 if (window_private != NULL
2594 && xevent->wParam == SIZE_MINIMIZED)
2597 event->any.type = GDK_UNMAP;
2598 event->any.window = window;
2600 if (p_grab_window == window_private)
2601 gdk_pointer_ungrab (xevent->time);
2603 if (k_grab_window == window_private)
2604 gdk_keyboard_ungrab (xevent->time);
2606 return_val = !window_private->destroyed;
2609 else if (window_private != NULL
2610 && (xevent->wParam == SIZE_RESTORED
2611 || xevent->wParam == SIZE_MAXIMIZED)
2613 && window_private->window_type != GDK_WINDOW_CHILD
2617 if (LOWORD (xevent->lParam) == 0)
2620 event->configure.type = GDK_CONFIGURE;
2621 event->configure.window = window;
2624 ClientToScreen (xevent->hwnd, &pt);
2625 event->configure.x = pt.x;
2626 event->configure.y = pt.y;
2627 event->configure.width = LOWORD (xevent->lParam);
2628 event->configure.height = HIWORD (xevent->lParam);
2629 window_private->x = event->configure.x;
2630 window_private->y = event->configure.y;
2631 window_private->width = event->configure.width;
2632 window_private->height = event->configure.height;
2633 if (window_private->resize_count > 1)
2634 window_private->resize_count -= 1;
2636 return_val = !window_private->destroyed;
2638 && window_private->extension_events != 0
2639 && gdk_input_vtable.configure_event)
2640 gdk_input_vtable.configure_event (&event->configure, window);
2643 #if 0 /* Bernd Herd suggests responding to WM_GETMINMAXINFO instead,
2644 * which indeed is much easier.
2647 GDK_NOTE (EVENTS, g_print ("WM_SIZING: %#x\n", xevent->hwnd));
2648 if (ret_val_flagp == NULL)
2649 g_warning ("ret_val_flagp is NULL but we got a WM_SIZING?");
2650 else if (window_private != NULL
2651 && window_private->hint_flags &
2652 (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE))
2654 LPRECT lprc = (LPRECT) xevent->lParam;
2656 if (window_private->hint_flags & GDK_HINT_MIN_SIZE)
2658 gint w = lprc->right - lprc->left;
2659 gint h = lprc->bottom - lprc->top;
2661 if (w < window_private->hint_min_width)
2663 if (xevent->wParam == WMSZ_BOTTOMLEFT
2664 || xevent->wParam == WMSZ_LEFT
2665 || xevent->wParam == WMSZ_TOPLEFT)
2666 lprc->left = lprc->right - window_private->hint_min_width;
2668 lprc->right = lprc->left + window_private->hint_min_width;
2669 *ret_val_flagp = TRUE;
2672 if (h < window_private->hint_min_height)
2674 if (xevent->wParam == WMSZ_BOTTOMLEFT
2675 || xevent->wParam == WMSZ_BOTTOM
2676 || xevent->wParam == WMSZ_BOTTOMRIGHT)
2677 lprc->bottom = lprc->top + window_private->hint_min_height;
2679 lprc->top = lprc->bottom - window_private->hint_min_height;
2680 *ret_val_flagp = TRUE;
2684 if (window_private->hint_flags & GDK_HINT_MAX_SIZE)
2686 gint w = lprc->right - lprc->left;
2687 gint h = lprc->bottom - lprc->top;
2689 if (w > window_private->hint_max_width)
2691 if (xevent->wParam == WMSZ_BOTTOMLEFT
2692 || xevent->wParam == WMSZ_LEFT
2693 || xevent->wParam == WMSZ_TOPLEFT)
2694 lprc->left = lprc->right - window_private->hint_max_width;
2696 lprc->right = lprc->left + window_private->hint_max_width;
2697 *ret_val_flagp = TRUE;
2700 if (h > window_private->hint_max_height)
2702 if (xevent->wParam == WMSZ_BOTTOMLEFT
2703 || xevent->wParam == WMSZ_BOTTOM
2704 || xevent->wParam == WMSZ_BOTTOMRIGHT)
2705 lprc->bottom = lprc->top + window_private->hint_max_height;
2707 lprc->top = lprc->bottom - window_private->hint_max_height;
2708 *ret_val_flagp = TRUE;
2715 case WM_GETMINMAXINFO:
2716 GDK_NOTE (EVENTS, g_print ("WM_GETMINMAXINFO: %#x\n", xevent->hwnd));
2717 lpmmi = (MINMAXINFO*) xevent->lParam;
2718 if (window_private->hint_flags & GDK_HINT_MIN_SIZE)
2720 lpmmi->ptMinTrackSize.x = window_private->hint_min_width;
2721 lpmmi->ptMinTrackSize.y = window_private->hint_min_height;
2723 if (window_private->hint_flags & GDK_HINT_MAX_SIZE)
2725 lpmmi->ptMaxTrackSize.x = window_private->hint_max_width;
2726 lpmmi->ptMaxTrackSize.y = window_private->hint_max_height;
2728 lpmmi->ptMaxSize.x = window_private->hint_max_width;
2729 lpmmi->ptMaxSize.y = window_private->hint_max_height;
2735 GDK_NOTE (EVENTS, g_print ("WM_MOVE: %#x +%d+%d\n",
2737 LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2740 && !(window_private->event_mask & GDK_STRUCTURE_MASK))
2742 if (window_private != NULL
2743 && window_private->window_type != GDK_WINDOW_CHILD)
2745 event->configure.type = GDK_CONFIGURE;
2746 event->configure.window = window;
2747 event->configure.x = LOWORD (xevent->lParam);
2748 event->configure.y = HIWORD (xevent->lParam);
2749 GetClientRect (xevent->hwnd, &rect);
2750 event->configure.width = rect.right;
2751 event->configure.height = rect.bottom;
2752 window_private->x = event->configure.x;
2753 window_private->y = event->configure.y;
2754 window_private->width = event->configure.width;
2755 window_private->height = event->configure.height;
2757 return_val = !window_private->destroyed;
2762 GDK_NOTE (EVENTS, g_print ("WM_CLOSE: %#x\n", xevent->hwnd));
2763 event->any.type = GDK_DELETE;
2764 event->any.window = window;
2766 return_val = window_private && !window_private->destroyed;
2770 /* No, don't use delayed rendering after all. It works only if the
2771 * delayed SetClipboardData is called from the WindowProc, it
2772 * seems. (The #else part below is test code for that. It succeeds
2773 * in setting the clipboard data. But if I call SetClipboardData
2774 * in gdk_property_change (as a consequence of the
2775 * GDK_SELECTION_REQUEST event), it fails. I deduce that this is
2776 * because delayed rendering requires that SetClipboardData is
2777 * called in the window procedure.)
2779 case WM_RENDERFORMAT:
2780 case WM_RENDERALLFORMATS:
2782 GDK_NOTE (EVENTS, flag = TRUE);
2783 GDK_NOTE (SELECTION, flag = TRUE);
2785 g_print ("WM_%s: %#x %#x (%s)\n",
2786 (xevent->message == WM_RENDERFORMAT ? "RENDERFORMAT" :
2787 "RENDERALLFORMATS"),
2790 (xevent->wParam == CF_TEXT ? "CF_TEXT" :
2791 (xevent->wParam == CF_DIB ? "CF_DIB" :
2792 (xevent->wParam == CF_UNICODETEXT ? "CF_UNICODETEXT" :
2793 (GetClipboardFormatName (xevent->wParam, buf, sizeof (buf)), buf)))));
2796 event->selection.type = GDK_SELECTION_REQUEST;
2797 event->selection.window = window;
2798 event->selection.selection = gdk_clipboard_atom;
2799 if (xevent->wParam == CF_TEXT)
2800 event->selection.target = GDK_TARGET_STRING;
2803 GetClipboardFormatName (xevent->wParam, buf, sizeof (buf));
2804 event->selection.target = gdk_atom_intern (buf, FALSE);
2806 event->selection.property = gdk_selection_property;
2807 event->selection.requestor = (guint32) xevent->hwnd;
2808 event->selection.time = xevent->time;
2809 return_val = window_private && !window_private->destroyed;
2811 /* Test code, to see if SetClipboardData works when called from
2812 * the window procedure.
2815 HGLOBAL hdata = GlobalAlloc (GMEM_MOVEABLE|GMEM_DDESHARE, 10);
2816 char *ptr = GlobalLock (hdata);
2817 strcpy (ptr, "Huhhaa");
2818 GlobalUnlock (hdata);
2819 if (!SetClipboardData (CF_TEXT, hdata))
2820 g_print ("SetClipboardData failed: %d\n", GetLastError ());
2823 *ret_val_flagp = TRUE;
2827 #endif /* No delayed rendering */
2830 GDK_NOTE (EVENTS, g_print ("WM_DESTROY: %#x\n", xevent->hwnd));
2831 event->any.type = GDK_DESTROY;
2832 event->any.window = window;
2833 if (window != NULL && window == curWnd)
2835 gdk_window_unref (curWnd);
2839 if (p_grab_window == window_private)
2840 gdk_pointer_ungrab (xevent->time);
2842 if (k_grab_window == window_private)
2843 gdk_keyboard_ungrab (xevent->time);
2845 return_val = window_private && !window_private->destroyed;
2849 /* Handle WINTAB events here, as we know that gdkinput.c will
2850 * use the fixed WT_DEFBASE as lcMsgBase, and we thus can use the
2851 * constants as case labels.
2854 GDK_NOTE (EVENTS, g_print ("WT_PACKET: %d %#x\n",
2855 xevent->wParam, xevent->lParam));
2859 GDK_NOTE (EVENTS, g_print ("WT_CSRCHANGE: %d %#x\n",
2860 xevent->wParam, xevent->lParam));
2865 g_print ("WT_PROXIMITY: %#x %d %d\n",
2867 LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
2870 return_val = gdk_input_vtable.other_event(event, xevent);
2879 if (event->any.window)
2880 gdk_window_ref (event->any.window);
2881 if (((event->any.type == GDK_ENTER_NOTIFY) ||
2882 (event->any.type == GDK_LEAVE_NOTIFY)) &&
2883 (event->crossing.subwindow != NULL))
2884 gdk_window_ref (event->crossing.subwindow);
2888 /* Mark this event as having no resources to be freed */
2889 event->any.window = NULL;
2890 event->any.type = GDK_NOTHING;
2894 gdk_window_unref (window);
2900 gdk_events_queue (void)
2906 GDK_NOTE (EVENTS, g_print ("gdk_events_queue: %s\n",
2907 (queued_events ? "yes" : "none")));
2909 while (!gdk_event_queue_find_first()
2910 && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
2912 GDK_NOTE (EVENTS, g_print ("gdk_events_queue: got event\n"));
2913 TranslateMessage (&msg);
2915 event = gdk_event_new ();
2917 event->any.type = GDK_NOTHING;
2918 event->any.window = NULL;
2919 event->any.send_event = FALSE;
2921 ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
2923 gdk_event_queue_append (event);
2926 if (gdk_event_translate (event, &msg, NULL, NULL))
2927 ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
2930 DefWindowProc (msg.hwnd, msg.message, msg.wParam, msg.lParam);
2931 gdk_event_queue_remove_link (node);
2932 g_list_free_1 (node);
2933 gdk_event_free (event);
2939 gdk_event_prepare (gpointer source_data,
2940 GTimeVal *current_time,
2946 GDK_THREADS_ENTER ();
2950 GDK_NOTE (EVENTS, g_print ("gdk_event_prepare\n"));
2952 retval = (gdk_event_queue_find_first () != NULL)
2953 || PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
2955 GDK_THREADS_LEAVE ();
2961 gdk_event_check (gpointer source_data,
2962 GTimeVal *current_time)
2967 GDK_NOTE (EVENTS, g_print ("gdk_event_check\n"));
2969 GDK_THREADS_ENTER ();
2971 if (event_poll_fd.revents & G_IO_IN)
2972 retval = (gdk_event_queue_find_first () != NULL)
2973 || PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
2977 GDK_THREADS_LEAVE ();
2983 gdk_event_unqueue (void)
2985 GdkEvent *event = NULL;
2988 tmp_list = gdk_event_queue_find_first ();
2992 event = tmp_list->data;
2993 gdk_event_queue_remove_link (tmp_list);
2994 g_list_free_1 (tmp_list);
3001 gdk_event_dispatch (gpointer source_data,
3002 GTimeVal *current_time,
3007 GDK_NOTE (EVENTS, g_print ("gdk_event_dispatch\n"));
3009 GDK_THREADS_ENTER ();
3012 event = gdk_event_unqueue();
3017 (*event_func) (event, event_data);
3019 gdk_event_free (event);
3022 GDK_THREADS_LEAVE ();
3028 gdk_synthesize_click (GdkEvent *event,
3031 GdkEvent temp_event;
3033 g_return_if_fail (event != NULL);
3035 temp_event = *event;
3036 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
3038 gdk_event_put (&temp_event);
3041 /* Sends a ClientMessage to all toplevel client windows */
3043 gdk_event_send_client_message (GdkEvent *event, guint32 xid)
3050 gdk_event_send_clientmessage_toall (GdkEvent *event)