]> Pileus Git - ~andy/gtk/blobdiff - gdk/win32/gdkevents-win32.c
If we don't know where we went, and have generated a leave event, set
[~andy/gtk] / gdk / win32 / gdkevents-win32.c
index b6b42a81e7d69e96a255a9530f1999de1057ac69..f241943cb94cae2fab2a59192ce4aedc7bf0a378 100644 (file)
@@ -39,7 +39,7 @@
  * not have TrackMouseEvent at all (?) --hb
  */
 
-#include "config.h"
+#include <config.h>
 
 #include <glib/gprintf.h>
 
 #define XBUTTON2 2
 #endif
 
+#ifndef VK_XBUTTON1
+#define VK_XBUTTON1 5
+#define VK_XBUTTON2 6
+#endif
+
 #ifndef MK_XBUTTON1
 #define MK_XBUTTON1 32
 #define MK_XBUTTON2 64
  * Private function declarations
  */
 
-static GdkFilterReturn
-                gdk_event_apply_filters(MSG      *msg,
-                                        GdkEvent *event,
-                                        GList    *filters);
-static gboolean  gdk_event_translate   (GdkDisplay *display,
-                                        MSG        *msg,
-                                        gint       *ret_valp);
-static void      handle_wm_paint        (MSG        *msg,
-                                        GdkWindow  *window,
-                                        gboolean    return_exposes,
-                                        GdkEvent  **event);
+static gboolean gdk_event_translate (MSG        *msg,
+                                    gint       *ret_valp);
+static void     handle_wm_paint     (MSG        *msg,
+                                    GdkWindow  *window,
+                                    gboolean    return_exposes,
+                                    GdkEvent  **event);
 
 static gboolean gdk_event_prepare  (GSource     *source,
                                    gint        *timeout);
@@ -107,6 +107,8 @@ static gboolean gdk_event_dispatch (GSource     *source,
                                    GSourceFunc  callback,
                                    gpointer     user_data);
 
+static void append_event (GdkEvent *event);
+
 /* Private variable declarations
  */
 
@@ -138,9 +140,7 @@ GPollFD event_poll_fd;
 
 static GdkWindow *current_window = NULL;
 static gint current_x, current_y;
-#if 0
-static UINT gdk_ping_msg;
-#endif
+static gint current_root_x, current_root_y;
 static UINT msh_mousewheel;
 static UINT client_message;
 
@@ -154,7 +154,6 @@ static HKL latin_locale = NULL;
 #endif
 
 static gboolean in_ime_composition = FALSE;
-static gboolean resizing = FALSE;
 static UINT     resize_timer;
 
 static int debug_indent = 0;
@@ -221,18 +220,46 @@ _gdk_win32_get_next_tick (gulong suggested_tick)
   if (suggested_tick == 0)
     suggested_tick = GetTickCount ();
   if (suggested_tick <= cur_tick)
-    return ++cur_tick;
+    return cur_tick;
   else
     return cur_tick = suggested_tick;
 }
 
+static void
+generate_focus_event (GdkWindow *window,
+                     gboolean   in)
+{
+  GdkEvent *event;
+
+  event = gdk_event_new (GDK_FOCUS_CHANGE);
+  event->focus_change.window = window;
+  event->focus_change.in = in;
+
+  append_event (event);
+}
+
+static void
+generate_grab_broken_event (GdkWindow *window,
+                           gboolean   keyboard,
+                           GdkWindow *grab_window)
+{
+  GdkEvent *event = gdk_event_new (GDK_GRAB_BROKEN);
+
+  event->grab_broken.window = window;
+  event->grab_broken.send_event = 0;
+  event->grab_broken.keyboard = keyboard;
+  event->grab_broken.implicit = FALSE;
+  event->grab_broken.grab_window = grab_window;
+         
+  append_event (event);
+}
+
 static LRESULT 
 inner_window_procedure (HWND   hwnd,
                        UINT   message,
                        WPARAM wparam,
                        LPARAM lparam)
 {
-  GdkDisplay *display = gdk_display_get_default ();
   MSG msg;
   DWORD pos;
 #ifdef HAVE_DIMM_H
@@ -249,7 +276,7 @@ inner_window_procedure (HWND   hwnd,
   msg.pt.x = GET_X_LPARAM (pos);
   msg.pt.y = GET_Y_LPARAM (pos);
 
-  if (gdk_event_translate (display, &msg, &ret_val))
+  if (gdk_event_translate (&msg, &ret_val))
     {
       /* If gdk_event_translate() returns TRUE, we return ret_val from
        * the window procedure.
@@ -344,11 +371,6 @@ _gdk_events_init (void)
   };
 #endif
 
-#if 0
-  gdk_ping_msg = RegisterWindowMessage ("gdk-ping");
-  GDK_NOTE (EVENTS, g_print ("gdk-ping = %#x\n", gdk_ping_msg));
-#endif
-
   /* This is the string MSH_MOUSEWHEEL from zmouse.h,
    * http://www.microsoft.com/mouse/intellimouse/sdk/zmouse.h
    * This message is used by mouse drivers than cannot generate WM_MOUSEWHEEL
@@ -440,9 +462,7 @@ gboolean
 gdk_events_pending (void)
 {
   MSG msg;
-  GdkDisplay *display = gdk_display_get_default ();
-
-  return (_gdk_event_queue_find_first (display) ||
+  return (_gdk_event_queue_find_first (_gdk_display) ||
          PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE));
 }
 
@@ -528,13 +548,13 @@ gdk_pointer_grab (GdkWindow    *window,
     hcursor = NULL;
   else if ((hcursor = CopyCursor (cursor_private->hcursor)) == NULL)
     WIN32_API_FAILED ("CopyCursor");
-#if 0
+
   return_val = _gdk_input_grab_pointer (window,
                                        owner_events,
                                        event_mask,
                                        confine_to,
                                        time);
-#endif
+
   if (return_val == GDK_GRAB_SUCCESS)
     {
       if (!GDK_WINDOW_DESTROYED (window))
@@ -561,7 +581,11 @@ gdk_pointer_grab (GdkWindow    *window,
   if (return_val == GDK_GRAB_SUCCESS)
     {
       GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl);
-      p_grab_window = window;
+
+      if (p_grab_window != NULL && p_grab_window != window)
+       generate_grab_broken_event (p_grab_window, FALSE, window);
+      
+      assign_object (&p_grab_window, window);
 
       if (p_grab_cursor != NULL)
        {
@@ -605,21 +629,20 @@ void
 gdk_display_pointer_ungrab (GdkDisplay *display,
                             guint32     time)
 {
-  g_return_if_fail (display == gdk_display_get_default ());
+  g_return_if_fail (display == _gdk_display);
 
   GDK_NOTE (EVENTS, g_print ("%sgdk_display_pointer_ungrab%s",
                             (debug_indent > 0 ? "\n" : ""),
                             (debug_indent == 0 ? "\n" : "")));
-#if 0
+
   _gdk_input_ungrab_pointer (time);
-#endif
 
   if (GetCapture () != NULL)
     ReleaseCapture ();
 
   /* FIXME: Generate GDK_CROSSING_UNGRAB events */
 
-  p_grab_window = NULL;
+  assign_object (&p_grab_window, NULL);
   if (p_grab_cursor != NULL)
     {
       if (GetCursor () == p_grab_cursor)
@@ -658,13 +681,13 @@ find_real_window_for_grabbed_mouse_event (GdkWindow* reported_window,
       GetClientRect (hwnd, &rect);
       ScreenToClient (hwnd, &pt);
       if (!PtInRect (&rect, pt))
-       return _gdk_parent_root;
+       return _gdk_root;
 
       other_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
     }
 
   if (other_window == NULL)
-    return _gdk_parent_root;
+    return _gdk_root;
 
   return other_window;
 }
@@ -682,7 +705,7 @@ find_window_for_mouse_event (GdkWindow* reported_window,
 gboolean
 gdk_display_pointer_is_grabbed (GdkDisplay *display)
 {
-  g_return_val_if_fail (display == gdk_display_get_default (), FALSE);
+  g_return_val_if_fail (display == _gdk_display, FALSE);
   GDK_NOTE (EVENTS, g_print ("gdk_pointer_is_grabbed: %s\n",
                             p_grab_window != NULL ? "TRUE" : "FALSE"));
   return p_grab_window != NULL;
@@ -693,7 +716,7 @@ gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
                                   GdkWindow **grab_window,
                                   gboolean   *owner_events)
 {
-  g_return_val_if_fail (display == gdk_display_get_default (), FALSE);
+  g_return_val_if_fail (display == _gdk_display, FALSE);
 
   if (p_grab_window != NULL)
     {
@@ -713,6 +736,8 @@ gdk_keyboard_grab (GdkWindow *window,
                   gboolean   owner_events,
                   guint32    time)
 {
+  GdkWindow *real_focus_window, *grab_focus_window;
+
   gint return_val;
   
   g_return_val_if_fail (window != NULL, 0);
@@ -730,7 +755,34 @@ gdk_keyboard_grab (GdkWindow *window,
     return_val = GDK_GRAB_ALREADY_GRABBED;
 
   if (return_val == GDK_GRAB_SUCCESS)
-    k_grab_window = window;
+    {
+      if (k_grab_window != NULL && k_grab_window != window)
+       generate_grab_broken_event (k_grab_window, TRUE, window);
+
+      assign_object (&k_grab_window, window);
+
+      if (!k_grab_owner_events)
+       {
+         real_focus_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) GetFocus ());
+         if (real_focus_window)
+           real_focus_window = gdk_window_get_toplevel (real_focus_window);
+         grab_focus_window = gdk_window_get_toplevel (k_grab_window);
+         if (real_focus_window != grab_focus_window)
+           {
+             /* Generate events for focus change from the window that really
+              * has focus to the grabber.
+              */
+             if (real_focus_window && !GDK_WINDOW_DESTROYED (real_focus_window)
+                 && (((GdkWindowObject *) real_focus_window)->event_mask
+                     & GDK_FOCUS_CHANGE_MASK))
+               generate_focus_event (real_focus_window, FALSE);
+
+             if (((GdkWindowObject *) grab_focus_window)->event_mask 
+                 & GDK_FOCUS_CHANGE_MASK)
+               generate_focus_event (grab_focus_window, TRUE);
+           }
+       }
+    }
   
   return return_val;
 }
@@ -739,11 +791,40 @@ void
 gdk_display_keyboard_ungrab (GdkDisplay *display,
                              guint32 time)
 {
-  g_return_if_fail (display == gdk_display_get_default ());
+  GdkWindow *real_focus_window, *grab_focus_window;
+
+  g_return_if_fail (display == _gdk_display);
 
   GDK_NOTE (EVENTS, g_print ("gdk_keyboard_ungrab\n"));
 
-  k_grab_window = NULL;
+  if (k_grab_window && !k_grab_owner_events)
+    {
+      real_focus_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) GetFocus ());
+      if (real_focus_window)
+       real_focus_window = gdk_window_get_toplevel (real_focus_window);
+      if (!GDK_WINDOW_DESTROYED (k_grab_window))
+       grab_focus_window = gdk_window_get_toplevel (k_grab_window);
+      else
+       grab_focus_window = NULL;
+      if (real_focus_window != grab_focus_window)
+       {
+         /* Generate events for focus change from grabber to the window that
+          * really has focus. Important for example if a new window is created
+          * while focus is grabbed.
+          */
+         if (grab_focus_window
+             && (((GdkWindowObject *) grab_focus_window)->event_mask
+                 & GDK_FOCUS_CHANGE_MASK))
+           generate_focus_event (grab_focus_window, FALSE);
+
+         if (real_focus_window && !GDK_WINDOW_DESTROYED (real_focus_window)
+             && (((GdkWindowObject *) real_focus_window)->event_mask
+                 & GDK_FOCUS_CHANGE_MASK))
+           generate_focus_event (real_focus_window, TRUE);
+       }
+    }
+
+  assign_object (&k_grab_window, NULL);
 }
 
 gboolean
@@ -751,7 +832,7 @@ gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
                                    GdkWindow **grab_window,
                                    gboolean   *owner_events)
 {
-  g_return_val_if_fail (display == gdk_display_get_default (), FALSE);
+  g_return_val_if_fail (display == _gdk_display, FALSE);
 
   if (k_grab_window)
     {
@@ -766,31 +847,6 @@ gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
     return FALSE;
 }
 
-static GdkFilterReturn
-gdk_event_apply_filters (MSG      *msg,
-                        GdkEvent *event,
-                        GList    *filters)
-{
-  GdkEventFilter *filter;
-  GList *tmp_list;
-  GdkFilterReturn result;
-  
-  tmp_list = filters;
-  
-  while (tmp_list)
-    {
-      filter = (GdkEventFilter *) tmp_list->data;
-      
-      result = (*filter->function) (msg, event, filter->data);
-      if (result !=  GDK_FILTER_CONTINUE)
-       return result;
-      
-      tmp_list = tmp_list->next;
-    }
-  
-  return GDK_FILTER_CONTINUE;
-}
-
 void 
 gdk_display_add_client_message_filter (GdkDisplay   *display,
                                       GdkAtom       message_type,
@@ -827,6 +883,17 @@ build_key_event_state (GdkEvent *event,
   if (key_state[VK_CAPITAL] & 0x01)
     event->key.state |= GDK_LOCK_MASK;
 
+  if (key_state[VK_LBUTTON] & 0x80)
+    event->key.state |= GDK_BUTTON1_MASK;
+  if (key_state[VK_MBUTTON] & 0x80)
+    event->key.state |= GDK_BUTTON2_MASK;
+  if (key_state[VK_RBUTTON] & 0x80)
+    event->key.state |= GDK_BUTTON3_MASK;
+  if (key_state[VK_XBUTTON1] & 0x80)
+    event->key.state |= GDK_BUTTON4_MASK;
+  if (key_state[VK_XBUTTON2] & 0x80)
+    event->key.state |= GDK_BUTTON5_MASK;
+
   /* Win9x doesn't distinguish between left and right Control and Alt
    * in the keyboard state as returned by GetKeyboardState(), so we
    * have to punt, and accept either Control + either Alt to be AltGr.
@@ -836,7 +903,7 @@ build_key_event_state (GdkEvent *event,
    * does indicate correctly whether it is the right Control or Alt
    * key. But that would be a bit messy.
    */
-  if (!IS_WIN_NT () &&
+  if (!G_WIN32_IS_NT_BASED () &&
       _gdk_keyboard_has_altgr &&
       key_state[VK_CONTROL] & 0x80 &&
       key_state[VK_MENU] & 0x80)
@@ -869,22 +936,41 @@ build_pointer_event_state (MSG *msg)
   gint state;
   
   state = 0;
+
   if (msg->wParam & MK_CONTROL)
     state |= GDK_CONTROL_MASK;
-  if (msg->wParam & MK_LBUTTON)
+
+  if ((msg->message != WM_LBUTTONDOWN &&
+       (msg->wParam & MK_LBUTTON)) ||
+      msg->message == WM_LBUTTONUP)
     state |= GDK_BUTTON1_MASK;
-  if (msg->wParam & MK_MBUTTON)
+
+  if ((msg->message != WM_MBUTTONDOWN &&
+       (msg->wParam & MK_MBUTTON)) ||
+      msg->message == WM_MBUTTONUP)
     state |= GDK_BUTTON2_MASK;
-  if (msg->wParam & MK_RBUTTON)
+
+  if ((msg->message != WM_RBUTTONDOWN &&
+       (msg->wParam & MK_RBUTTON)) ||
+      msg->message == WM_RBUTTONUP)
     state |= GDK_BUTTON3_MASK;
-  if (msg->wParam & MK_XBUTTON1)
+
+  if (((msg->message != WM_XBUTTONDOWN || HIWORD (msg->wParam) != XBUTTON1) &&
+       (msg->wParam & MK_XBUTTON1)) ||
+      (msg->message == WM_XBUTTONUP && HIWORD (msg->wParam) == XBUTTON1))
     state |= GDK_BUTTON4_MASK;
-  if (msg->wParam & MK_XBUTTON2)
+
+  if (((msg->message != WM_XBUTTONDOWN || HIWORD (msg->wParam) != XBUTTON2) &&
+       (msg->wParam & MK_XBUTTON2)) ||
+      (msg->message == WM_XBUTTONUP && HIWORD (msg->wParam) == XBUTTON2))
     state |= GDK_BUTTON5_MASK;
+
   if (msg->wParam & MK_SHIFT)
     state |= GDK_SHIFT_MASK;
+
   if (GetKeyState (VK_MENU) < 0)
     state |= GDK_MOD1_MASK;
+
   if (GetKeyState (VK_CAPITAL) & 0x1)
     state |= GDK_LOCK_MASK;
 
@@ -973,6 +1059,8 @@ print_event (GdkEvent *event)
     CASE (GDK_SCROLL);
     CASE (GDK_WINDOW_STATE);
     CASE (GDK_SETTING);
+    CASE (GDK_OWNER_CHANGE);
+    CASE (GDK_GRAB_BROKEN);
 #undef CASE
     default: g_assert_not_reached ();
     }
@@ -1047,7 +1135,7 @@ print_event (GdkEvent *event)
               event->configure.width, event->configure.height);
       break;
     case GDK_SCROLL:
-      g_print ("(%.4g,%.4g) (%.4g,%.4g)%s",
+      g_print ("(%.4g,%.4g) (%.4g,%.4g) %s ",
               event->scroll.x, event->scroll.y,
               event->scroll.x_root, event->scroll.y_root,
               (event->scroll.direction == GDK_SCROLL_UP ? "UP" :
@@ -1061,6 +1149,18 @@ print_event (GdkEvent *event)
       g_print ("%s: %s",
               _gdk_win32_window_state_to_string (event->window_state.changed_mask),
               _gdk_win32_window_state_to_string (event->window_state.new_window_state));
+    case GDK_SETTING:
+      g_print ("%s: %s",
+              (event->setting.action == GDK_SETTING_ACTION_NEW ? "NEW" :
+               (event->setting.action == GDK_SETTING_ACTION_CHANGED ? "CHANGED" :
+                (event->setting.action == GDK_SETTING_ACTION_DELETED ? "DELETED" :
+                 "???"))),
+              (event->setting.name ? event->setting.name : "NULL"));
+    case GDK_GRAB_BROKEN:
+      g_print ("%s %s %p",
+              (event->grab_broken.keyboard ? "KEYBOARD" : "POINTER"),
+              (event->grab_broken.implicit ? "IMPLICIT" : "EXPLICIT"),
+              (event->grab_broken.grab_window ? GDK_WINDOW_HWND (event->grab_broken.grab_window) : 0));
     default:
       /* Nothing */
       break;
@@ -1102,11 +1202,10 @@ fixup_event (GdkEvent *event)
 }
 
 static void
-append_event (GdkDisplay *display,
-             GdkEvent   *event)
+append_event (GdkEvent *event)
 {
   fixup_event (event);
-  _gdk_event_queue_append (display, event);
+  _gdk_event_queue_append (_gdk_display, event);
   GDK_NOTE (EVENTS, print_event (event));
 }
 
@@ -1178,33 +1277,40 @@ fill_key_event_string (GdkEvent *event)
 }
 
 static GdkFilterReturn
-apply_filters (GdkDisplay *display,
-              GdkWindow  *window,
+apply_filters (GdkWindow  *window,
               MSG        *msg,
               GList      *filters)
 {
-  GdkFilterReturn result;
-  GdkEvent *event = gdk_event_new (GDK_NOTHING);
+  GdkFilterReturn result = GDK_FILTER_CONTINUE;
+  GdkEvent *event;
   GList *node;
+  GList *tmp_list;
 
+  event = gdk_event_new (GDK_NOTHING);
   if (window != NULL)
-    {
-      event->any.window = window;
-      g_object_ref (window);
-    }
+    event->any.window = g_object_ref (window);
   ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
 
   /* I think GdkFilterFunc semantics require the passed-in event
    * to already be in the queue. The filter func can generate
    * more events and append them after it if it likes.
    */
-  node = _gdk_event_queue_append (display, event);
+  node = _gdk_event_queue_append (_gdk_display, event);
   
-  result = gdk_event_apply_filters (msg, event, filters);
+  tmp_list = filters;
+  while (tmp_list)
+    {
+      GdkEventFilter *filter = (GdkEventFilter *) tmp_list->data;
       
+      tmp_list = tmp_list->next;
+      result = filter->function (msg, event, filter->data);
+      if (result !=  GDK_FILTER_CONTINUE)
+       break;
+    }
+
   if (result == GDK_FILTER_CONTINUE || result == GDK_FILTER_REMOVE)
     {
-      _gdk_event_queue_remove_link (display, node);
+      _gdk_event_queue_remove_link (_gdk_display, node);
       g_list_free_1 (node);
       gdk_event_free (event);
     }
@@ -1254,7 +1360,7 @@ synthesize_enter_or_leave_event (GdkWindow        *window,
   event->crossing.focus = TRUE; /* FIXME: Set correctly */
   event->crossing.state = 0;   /* FIXME: Set correctly */
   
-  append_event (gdk_drawable_get_display (window), event);
+  append_event (event);
   
   if (type == GDK_ENTER_NOTIFY &&
       ((GdkWindowObject *) window)->extension_events != 0)
@@ -1466,10 +1572,9 @@ synthesize_expose_events (GdkWindow *window)
          event->expose.region = gdk_region_rectangle (&(event->expose.area));
          event->expose.count = 0;
   
-         append_event (gdk_drawable_get_display (window), event);
+         append_event (event);
        }
-      if (!ReleaseDC (impl->handle, hdc))
-       WIN32_GDI_FAILED ("ReleaseDC");
+      GDI_CALL (ReleaseDC, (impl->handle, hdc));
     }
 }
 
@@ -1516,13 +1621,11 @@ update_colors (GdkWindow *window,
                              impl->handle, cmapp->hpal, k) :
                     (void) 0,
                     g_print (" %p", impl->handle)));
-         if (!UpdateColors (hdc))
-           WIN32_GDI_FAILED ("UpdateColors");
+         GDI_CALL (UpdateColors, (hdc));
          SelectPalette (hdc, holdpal, TRUE);
          RealizePalette (hdc);
        }
-      if (!ReleaseDC (impl->handle, hdc))
-       WIN32_GDI_FAILED ("ReleaseDC");
+      GDI_CALL (ReleaseDC, (impl->handle, hdc));
     }
   GDK_NOTE (COLORMAP, (top ? g_print ("\n") : (void) 0));
 }
@@ -1541,6 +1644,9 @@ translate_mouse_coords (GdkWindow *window1,
   msg->lParam = MAKELPARAM (pt.x, pt.y);
 }
 
+/* The check_extended flag controls whether to check if the windows want
+ * events from extended input devices and if the message should be skipped
+ * because an extended input device is active */
 static gboolean
 propagate (GdkWindow  **window,
           MSG         *msg,
@@ -1548,13 +1654,24 @@ propagate (GdkWindow  **window,
           gboolean     grab_owner_events,
           gint         grab_mask,
           gboolean   (*doesnt_want_it) (gint mask,
-                                        MSG *msg))
+                                        MSG *msg),
+          gboolean     check_extended)
 {
   gboolean in_propagation = FALSE;
 
   if (grab_window != NULL && !grab_owner_events)
     {
       /* Event source is grabbed with owner_events FALSE */
+
+      /* See if the event should be ignored because an extended input device
+       * is used */
+      if (check_extended &&
+         ((GdkWindowObject *) grab_window)->extension_events != 0 &&
+         _gdk_input_ignore_core)
+       {
+         GDK_NOTE (EVENTS, g_print (" (ignored for grabber)"));
+         return FALSE;
+       }
       if ((*doesnt_want_it) (grab_mask, msg))
        {
          GDK_NOTE (EVENTS, g_print (" (grabber doesn't want it)"));
@@ -1569,16 +1686,35 @@ propagate (GdkWindow  **window,
     }
   while (TRUE)
     {
-     if ((*doesnt_want_it) (((GdkWindowObject *) *window)->event_mask, msg))
+      /* See if the event should be ignored because an extended input device
+       * is used */
+      if (check_extended &&
+         ((GdkWindowObject *) *window)->extension_events != 0 &&
+         _gdk_input_ignore_core)
+       {
+         GDK_NOTE (EVENTS, g_print (" (ignored)"));
+         return FALSE;
+       }
+      if ((*doesnt_want_it) (((GdkWindowObject *) *window)->event_mask, msg))
        {
          /* Owner doesn't want it, propagate to parent. */
          GdkWindow *parent = gdk_window_get_parent (*window);
-         if (parent == _gdk_parent_root || parent == NULL)
+         if (parent == _gdk_root || parent == NULL)
            {
              /* No parent; check if grabbed */
              if (grab_window != NULL)
                {
                  /* Event source is grabbed with owner_events TRUE */
+
+                 /* See if the event should be ignored because an extended
+                  * input device is used */
+                 if (check_extended &&
+                     ((GdkWindowObject *) grab_window)->extension_events != 0 &&
+                     _gdk_input_ignore_core)
+                   {
+                     GDK_NOTE (EVENTS, g_print (" (ignored for grabber)"));
+                     return FALSE;
+                   }
                  if ((*doesnt_want_it) (grab_mask, msg))
                    {
                      /* Grabber doesn't want it either */
@@ -1669,23 +1805,29 @@ handle_configure_event (MSG       *msg,
                        GdkWindow *window)
 {
   RECT client_rect;
+  POINT point;
 
   GetClientRect (msg->hwnd, &client_rect);
-  
+  point.x = client_rect.left; /* always 0 */
+  point.y = client_rect.top;
+  /* top level windows need screen coords */
+  if (gdk_window_get_parent (window) == _gdk_root)
+    {
+      ClientToScreen (msg->hwnd, &point);
+      point.x += _gdk_offset_x;
+      point.y += _gdk_offset_y;
+    }
+
   GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->width = client_rect.right - client_rect.left;
   GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->height = client_rect.bottom - client_rect.top;
   
-  ((GdkWindowObject *) window)->x = client_rect.left;
-  ((GdkWindowObject *) window)->y = client_rect.top;
+  ((GdkWindowObject *) window)->x = point.x;
+  ((GdkWindowObject *) window)->y = point.y;
   
   if (((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK)
     {
-      POINT point;
       GdkEvent *event = gdk_event_new (GDK_CONFIGURE);
 
-      point.x = point.y = 0;
-      ClientToScreen (msg->hwnd, &point);
-      
       event->configure.window = window;
 
       event->configure.width = client_rect.right - client_rect.left;
@@ -1694,13 +1836,7 @@ handle_configure_event (MSG       *msg,
       event->configure.x = point.x;
       event->configure.y = point.y;
 
-      if (gdk_window_get_parent (window) == _gdk_parent_root)
-       {
-         event->configure.x += _gdk_offset_x;
-         event->configure.y += _gdk_offset_y;
-       }
-
-      append_event (gdk_drawable_get_display (window), event);
+      append_event (event);
     }
 }
 
@@ -1837,7 +1973,7 @@ erase_background (GdkWindow *window,
     }
 }
 
-static GdkRegion *
+GdkRegion *
 _gdk_win32_hrgn_to_region (HRGN hrgn)
 {
   RGNDATA *rgndata;
@@ -1954,7 +2090,7 @@ handle_wm_paint (MSG        *msg,
     {
       if (!GDK_WINDOW_DESTROYED (window))
        {
-         GList *list = gdk_drawable_get_display (window)->queued_events;
+         GList *list = _gdk_display->queued_events;
 
          *event = gdk_event_new (GDK_EXPOSE);
          (*event)->expose.window = window;
@@ -1996,8 +2132,8 @@ static void
 handle_stuff_while_moving_or_resizing (void)
 {
   int arbitrary_limit = 1;
-  while (g_main_pending () && arbitrary_limit--)
-    g_main_iteration (FALSE);
+  while (g_main_context_pending (NULL) && arbitrary_limit--)
+    g_main_context_iteration (NULL, FALSE);
 }
 
 static VOID CALLBACK
@@ -2006,23 +2142,59 @@ resize_timer_proc (HWND     hwnd,
                   UINT     id,
                   DWORD    time)
 {
-  if (resizing)
+  if (_sizemove_in_progress)
     handle_stuff_while_moving_or_resizing ();
 }
 
+static void
+handle_display_change (void)
+{
+  _gdk_monitor_init ();
+  _gdk_root_window_size_init ();
+  g_signal_emit_by_name (_gdk_screen, "size_changed");
+}
+
+static void
+generate_button_event (GdkEventType type,
+                      gint         button,
+                      GdkWindow   *window,
+                      GdkWindow   *orig_window,
+                      MSG         *msg)
+{
+  GdkEvent *event = gdk_event_new (type);
+  gint xoffset, yoffset;
+
+  event->button.window = window;
+  event->button.time = _gdk_win32_get_next_tick (msg->time);
+  if (window != orig_window)
+    translate_mouse_coords (orig_window, window, msg);
+  event->button.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
+  event->button.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
+  _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
+  event->button.x += xoffset;
+  event->button.y += yoffset;
+  event->button.x_root = msg->pt.x + _gdk_offset_x;
+  event->button.y_root = msg->pt.y + _gdk_offset_y;
+  event->button.axes = NULL;
+  event->button.state = build_pointer_event_state (msg);
+  event->button.button = button;
+  event->button.device = _gdk_display->core_pointer;
+
+  append_event (event);
+
+  if (type == GDK_BUTTON_PRESS)
+    _gdk_event_button_generate (_gdk_display, event);
+}
+
 static gboolean
-gdk_event_translate (GdkDisplay *display,
-                    MSG        *msg,
-                    gint       *ret_valp)
+gdk_event_translate (MSG  *msg,
+                    gint *ret_valp)
 {
-  DWORD pidActWin;
-  DWORD pidThis;
   RECT rect, *drag, orig_drag;
   POINT point;
   MINMAXINFO *mmi;
   HWND hwnd;
   HCURSOR hcursor;
-  CHARSETINFO charset_info;
   BYTE key_state[256];
   HIMC himc;
 
@@ -2039,6 +2211,7 @@ gdk_event_translate (GdkDisplay *display,
 
   static gint update_colors_counter = 0;
   gint button;
+  GdkAtom target;
 
   gchar buf[256];
   gboolean return_val = FALSE;
@@ -2049,18 +2222,13 @@ gdk_event_translate (GdkDisplay *display,
     {
       /* Apply global filters */
 
-      GdkFilterReturn result =
-       apply_filters (display, NULL, msg, _gdk_default_filters);
+      GdkFilterReturn result = apply_filters (NULL, msg, _gdk_default_filters);
       
       /* If result is GDK_FILTER_CONTINUE, we continue as if nothing
-       * happened. If it is GDK_FILTER_REMOVE, we return FALSE from
-       * gdk_event_translate(), meaning that the DefWindowProc() will
-       * be called. If it is GDK_FILTER_TRANSLATE, we return TRUE, and
-       * DefWindowProc() will not be called.
+       * happened. If it is GDK_FILTER_REMOVE or GDK_FILTER_TRANSLATE,
+       * we return TRUE, and DefWindowProc() will not be called.
        */
-      if (result == GDK_FILTER_REMOVE)
-       return FALSE;
-      else if (result == GDK_FILTER_TRANSLATE)
+      if (result == GDK_FILTER_REMOVE || result == GDK_FILTER_TRANSLATE)
        return TRUE;
     }
 
@@ -2084,12 +2252,11 @@ gdk_event_translate (GdkDisplay *display,
           * removed it. Repost the same message to our queue so that
           * we will get it later when we are prepared.
           */
-         GDK_NOTE (MISC, g_print (" (posted)"));
+         GDK_NOTE (EVENTS, g_print (" (posted)"));
        
          PostMessage (msg->hwnd, msg->message,
                       msg->wParam, msg->lParam);
        }
-#ifndef WITHOUT_WM_CREATE
       else if (msg->message == WM_CREATE)
        {
          window = (UNALIGNED GdkWindow*) (((LPCREATESTRUCT) msg->lParam)->lpCreateParams);
@@ -2099,7 +2266,6 @@ gdk_event_translate (GdkDisplay *display,
        {
          GDK_NOTE (EVENTS, g_print (" (no GdkWindow)"));
        }
-#endif
       return FALSE;
     }
   
@@ -2116,15 +2282,9 @@ gdk_event_translate (GdkDisplay *display,
     {
       /* Apply per-window filters */
 
-      GdkFilterReturn result =
-       apply_filters (display, window, msg, ((GdkWindowObject *) window)->filters);
+      GdkFilterReturn result = apply_filters (window, msg, ((GdkWindowObject *) window)->filters);
 
-      if (result == GDK_FILTER_REMOVE)
-       {
-         return_val = FALSE;
-         goto done;
-       }
-      else if (result == GDK_FILTER_TRANSLATE)
+      if (result == GDK_FILTER_REMOVE || result == GDK_FILTER_TRANSLATE)
        {
          return_val = TRUE;
          goto done;
@@ -2135,7 +2295,7 @@ gdk_event_translate (GdkDisplay *display,
     {
       GDK_NOTE (EVENTS, g_print (" (MSH_MOUSEWHEEL)"));
       
-      /* MSG_MOUSEWHEEL is delivered to the foreground window.  Work
+      /* MSH_MOUSEWHEEL is delivered to the foreground window.  Work
        * around that. Also, the position is in screen coordinates, not
        * client coordinates as with the button messages.
        */
@@ -2150,16 +2310,9 @@ gdk_event_translate (GdkDisplay *display,
 
       assign_object (&window, new_window);
 
-      if (((GdkWindowObject *) window)->extension_events != 0 &&
-         _gdk_input_ignore_core)
-       {
-         GDK_NOTE (EVENTS, g_print (" (ignored)"));
-         goto done;
-       }
-
       if (!propagate (&window, msg,
                      p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_scroll))
+                     doesnt_want_scroll, TRUE))
        goto done;
 
       if (GDK_WINDOW_DESTROYED (window))
@@ -2178,9 +2331,9 @@ gdk_event_translate (GdkDisplay *display,
       event->scroll.x_root = (gint16) GET_X_LPARAM (msg->lParam) + _gdk_offset_x;
       event->scroll.y_root = (gint16) GET_Y_LPARAM (msg->lParam) + _gdk_offset_y;
       event->scroll.state = 0; /* No state information with MSH_MOUSEWHEEL */
-      event->scroll.device = display->core_pointer;
+      event->scroll.device = _gdk_display->core_pointer;
 
-      append_event (display, event);
+      append_event (event);
 
       return_val = TRUE;
       goto done;
@@ -2188,52 +2341,53 @@ gdk_event_translate (GdkDisplay *display,
   else if (msg->message == client_message)
     {
       GList *tmp_list;
+      GdkFilterReturn result = GDK_FILTER_CONTINUE;
+
+      GDK_NOTE (EVENTS, g_print (" client_message"));
 
       tmp_list = client_filters;
       while (tmp_list)
        {
          GdkClientFilter *filter = tmp_list->data;
 
+         tmp_list = tmp_list->next;
+
          if (filter->type == GDK_POINTER_TO_ATOM (msg->wParam))
            {
-             GList *this_filter = g_list_append (NULL, filter);
+             GList *filter_list = g_list_append (NULL, filter);
              
-             GdkFilterReturn result =
-               apply_filters (display, window, msg, this_filter);
-
-             GDK_NOTE (EVENTS, g_print (" (client filter match)"));
+             GDK_NOTE (EVENTS, g_print (" (match)"));
 
-             g_list_free (this_filter);
-
-             if (result == GDK_FILTER_REMOVE)
-               {
-                 return_val = FALSE;
-                 goto done;
-               }
-             else if (result == GDK_FILTER_TRANSLATE)
-               {
-                 return_val = TRUE;
-                 goto done;
-               }
-             else /* GDK_FILTER_CONTINUE */
-               {
-                 /* Send unknown client messages on to Gtk for it to use */
+             result = apply_filters (window, msg, filter_list);
 
-                 event = gdk_event_new (GDK_CLIENT_EVENT);
-                 event->client.window = window;
-                 event->client.message_type = GDK_POINTER_TO_ATOM (msg->wParam);
-                 event->client.data_format = 32;
-                 event->client.data.l[0] = msg->lParam;
-                 for (i = 1; i < 5; i++)
-                   event->client.data.l[i] = 0;
+             g_list_free (filter_list);
 
-                 append_event (display, event);
-
-                 return_val = TRUE;
-                 goto done;
-               }
+             if (result != GDK_FILTER_CONTINUE)
+               break;
            }
-         tmp_list = tmp_list->next;
+       }
+
+      if (result == GDK_FILTER_REMOVE || result == GDK_FILTER_TRANSLATE)
+       {
+         return_val = TRUE;
+         goto done;
+       }
+      else
+       {
+         /* Send unknown client messages on to Gtk for it to use */
+
+         event = gdk_event_new (GDK_CLIENT_EVENT);
+         event->client.window = window;
+         event->client.message_type = GDK_POINTER_TO_ATOM (msg->wParam);
+         event->client.data_format = 32;
+         event->client.data.l[0] = msg->lParam;
+         for (i = 1; i < 5; i++)
+           event->client.data.l[i] = 0;
+         
+         append_event (event);
+         
+         return_val = TRUE;
+         goto done;
        }
     }
 
@@ -2242,10 +2396,10 @@ gdk_event_translate (GdkDisplay *display,
     case WM_INPUTLANGCHANGE:
       _gdk_input_locale = (HKL) msg->lParam;
       _gdk_input_locale_is_ime = ImmIsIME (_gdk_input_locale);
-      TranslateCharsetInfo ((DWORD FAR *) msg->wParam,
-                           &charset_info,
-                           TCI_SRCCHARSET);
-      _gdk_input_codepage = charset_info.ciACP;
+      GetLocaleInfo (MAKELCID (LOWORD (_gdk_input_locale), SORT_DEFAULT),
+                    LOCALE_IDEFAULTANSICODEPAGE,
+                    buf, sizeof (buf));
+      _gdk_input_codepage = atoi (buf);
       _gdk_keymap_serial++;
       GDK_NOTE (EVENTS,
                g_print (" cs:%lu hkl:%lx%s cp:%d",
@@ -2258,9 +2412,7 @@ gdk_event_translate (GdkDisplay *display,
     case WM_SYSKEYDOWN:
       GDK_NOTE (EVENTS,
                g_print (" %s ch:%.02x %s",
-                        (GetKeyNameText (msg->lParam, buf,
-                                         sizeof (buf)) > 0 ?
-                         buf : ""),
+                        _gdk_win32_key_to_string (msg->lParam),
                         msg->wParam,
                         decode_key_lparam (msg->lParam)));
 
@@ -2269,13 +2421,12 @@ gdk_event_translate (GdkDisplay *display,
          !(HIWORD (msg->lParam) & KF_ALTDOWN))
        break;
 
-      /* Let the system handle Alt-Tab, Alt-Space, Alt-Enter and
-       * Alt-F4 unless the keyboard is grabbed.
+      /* Let the system handle Alt-Tab, Alt-Space and Alt-F4 unless
+       * the keyboard is grabbed.
        */
       if (k_grab_window == NULL &&
          (msg->wParam == VK_TAB ||
           msg->wParam == VK_SPACE ||
-          msg->wParam == VK_RETURN ||
           msg->wParam == VK_F4))
        break;
 
@@ -2286,9 +2437,7 @@ gdk_event_translate (GdkDisplay *display,
     case WM_KEYDOWN:
       GDK_NOTE (EVENTS, 
                g_print (" %s ch:%.02x %s",
-                        (GetKeyNameText (msg->lParam, buf,
-                                         sizeof (buf)) > 0 ?
-                         buf : ""),
+                        _gdk_win32_key_to_string (msg->lParam),
                         msg->wParam,
                         decode_key_lparam (msg->lParam)));
 
@@ -2301,7 +2450,7 @@ gdk_event_translate (GdkDisplay *display,
 
       if (!propagate (&window, msg,
                      k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
-                     doesnt_want_key))
+                     doesnt_want_key, FALSE))
        break;
 
       if (GDK_WINDOW_DESTROYED (window))
@@ -2316,6 +2465,26 @@ gdk_event_translate (GdkDisplay *display,
       event->key.string = NULL;
       event->key.length = 0;
       event->key.hardware_keycode = msg->wParam;
+      if (HIWORD (msg->lParam) & KF_EXTENDED)
+       {
+         switch (msg->wParam)
+           {
+           case VK_CONTROL:
+             event->key.hardware_keycode = VK_RCONTROL;
+             break;
+           case VK_SHIFT:      /* Actually, KF_EXTENDED is not set
+                                * for the right shift key.
+                                */
+             event->key.hardware_keycode = VK_RSHIFT;
+             break;
+           case VK_MENU:
+             event->key.hardware_keycode = VK_RMENU;
+             break;
+           }
+       }
+      else if (msg->wParam == VK_SHIFT &&
+              LOBYTE (HIWORD (msg->lParam)) == _scancode_rshift)
+       event->key.hardware_keycode = VK_RSHIFT;
 
       API_CALL (GetKeyboardState, (key_state));
 
@@ -2336,7 +2505,7 @@ gdk_event_translate (GdkDisplay *display,
       if (msg->wParam == VK_MENU)
        event->key.state &= ~GDK_MOD1_MASK;
 
-      append_event (display, event);
+      append_event (event);
 
       return_val = TRUE;
       break;
@@ -2383,7 +2552,7 @@ gdk_event_translate (GdkDisplay *display,
 
       if (!propagate (&window, msg,
                      k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
-                     doesnt_want_char))
+                     doesnt_want_char, FALSE))
        break;
 
       if (GDK_WINDOW_DESTROYED (window))
@@ -2407,7 +2576,7 @@ gdk_event_translate (GdkDisplay *display,
              event->key.window = window;
              build_wm_ime_composition_event (event, msg, wbuf[i], key_state);
 
-             append_event (display, event);
+             append_event (event);
            }
          
          if (((GdkWindowObject *) window)->event_mask & GDK_KEY_RELEASE_MASK)
@@ -2417,7 +2586,7 @@ gdk_event_translate (GdkDisplay *display,
              event->key.window = window;
              build_wm_ime_composition_event (event, msg, wbuf[i], key_state);
 
-             append_event (display, event);
+             append_event (event);
            }
        }
       return_val = TRUE;
@@ -2461,16 +2630,9 @@ gdk_event_translate (GdkDisplay *display,
            synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
        }
 
-      if (((GdkWindowObject *) window)->extension_events != 0 &&
-         _gdk_input_ignore_core)
-       {
-         GDK_NOTE (EVENTS, g_print (" (ignored)"));
-         break;
-       }
-
       if (!propagate (&window, msg,
                      p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_button_press))
+                     doesnt_want_button_press, TRUE))
        break;
 
       if (GDK_WINDOW_DESTROYED (window))
@@ -2488,26 +2650,8 @@ gdk_event_translate (GdkDisplay *display,
          p_grab_automatic = TRUE;
        }
 
-      event = gdk_event_new (GDK_BUTTON_PRESS);
-      event->button.window = window;
-      event->button.time = _gdk_win32_get_next_tick (msg->time);
-      if (window != orig_window)
-       translate_mouse_coords (orig_window, window, msg);
-      event->button.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
-      event->button.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
-      _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
-      event->button.x += xoffset;
-      event->button.y += yoffset;
-      event->button.x_root = msg->pt.x + _gdk_offset_x;
-      event->button.y_root = msg->pt.y + _gdk_offset_y;
-      event->button.axes = NULL;
-      event->button.state = build_pointer_event_state (msg);
-      event->button.button = button;
-      event->button.device = display->core_pointer;
-
-      append_event (display, event);
-
-      _gdk_event_button_generate (display, event);
+      generate_button_event (GDK_BUTTON_PRESS, button,
+                            window, orig_window, msg);
 
       return_val = TRUE;
       break;
@@ -2550,38 +2694,24 @@ gdk_event_translate (GdkDisplay *display,
            synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
        }
 
+#if 0
       if (((GdkWindowObject *) window)->extension_events != 0 &&
          _gdk_input_ignore_core)
        {
          GDK_NOTE (EVENTS, g_print (" (ignored)"));
          break;
        }
+#endif
 
       if (!propagate (&window, msg,
                      p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_button_release))
+                     doesnt_want_button_release, TRUE))
        {
        }
       else if (!GDK_WINDOW_DESTROYED (window))
        {
-         event = gdk_event_new (GDK_BUTTON_RELEASE);
-         event->button.window = window;
-         event->button.time = _gdk_win32_get_next_tick (msg->time);
-         if (window != orig_window)
-           translate_mouse_coords (orig_window, window, msg);
-         event->button.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
-         event->button.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
-         _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
-         event->button.x += xoffset;
-         event->button.y += yoffset;
-         event->button.x_root = msg->pt.x + _gdk_offset_x;
-         event->button.y_root = msg->pt.y + _gdk_offset_y;
-         event->button.axes = NULL;
-         event->button.state = build_pointer_event_state (msg);
-         event->button.button = button;
-         event->button.device = display->core_pointer;
-
-         append_event (display, event);
+         generate_button_event (GDK_BUTTON_RELEASE, button,
+                                window, orig_window, msg);
        }
 
       if (p_grab_window != NULL &&
@@ -2601,12 +2731,17 @@ gdk_event_translate (GdkDisplay *display,
                         msg->wParam,
                         GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
 
-      /* HB: only process mouse move messages if we own the active window. */
-      GetWindowThreadProcessId (GetActiveWindow (), &pidActWin);
-      GetWindowThreadProcessId (msg->hwnd, &pidThis);
-      if (pidActWin != pidThis)
+      /* If we haven't moved, don't create any GDK event. Windows
+       * sends WM_MOUSEMOVE messages after a new window is shows under
+       * the mouse, even if the mouse hasn't moved. This disturbs gtk.
+       */
+      if (msg->pt.x + _gdk_offset_x == current_root_x &&
+         msg->pt.y + _gdk_offset_y == current_root_y)
        break;
 
+      current_root_x = msg->pt.x + _gdk_offset_x;
+      current_root_y = msg->pt.y + _gdk_offset_y;
+
       assign_object (&window, find_window_for_mouse_event (window, msg));
 
       if (p_grab_window != NULL)
@@ -2614,7 +2749,22 @@ gdk_event_translate (GdkDisplay *display,
          GdkWindow *real_window = find_real_window_for_grabbed_mouse_event (window, msg);
 
          if (real_window != current_window)
-           synthesize_crossing_events (real_window, GDK_CROSSING_NORMAL, msg);
+           {
+             if (p_grab_owner_events)
+               {
+                 synthesize_crossing_events (real_window, GDK_CROSSING_NORMAL, msg);
+               }
+             else if (current_window == p_grab_window)
+               {
+                 synthesize_leave_event (p_grab_window, msg, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
+                 assign_object (&current_window, _gdk_root);
+               }
+             else if (real_window == p_grab_window)
+               {
+                 synthesize_enter_event (p_grab_window, msg, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
+                 assign_object (&current_window, p_grab_window);
+               }
+           }
        }
       else
        {
@@ -2622,16 +2772,9 @@ gdk_event_translate (GdkDisplay *display,
            synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
        }
 
-      if (((GdkWindowObject *) window)->extension_events != 0 &&
-         _gdk_input_ignore_core)
-       {
-         GDK_NOTE (EVENTS, g_print (" (ignored)"));
-         break;
-       }
-
       if (!propagate (&window, msg,
                      p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_button_motion))
+                     doesnt_want_button_motion, TRUE))
        break;
 
       if (GDK_WINDOW_DESTROYED (window))
@@ -2640,15 +2783,6 @@ gdk_event_translate (GdkDisplay *display,
       if (window != orig_window)
        translate_mouse_coords (orig_window, window, msg);
 
-      /* If we haven't moved, don't create any event.
-       * Windows sends WM_MOUSEMOVE messages after button presses
-       * even if the mouse doesn't move. This disturbs gtk.
-       */
-      if (window == current_window &&
-         GET_X_LPARAM (msg->lParam) == current_x &&
-         GET_Y_LPARAM (msg->lParam) == current_y)
-       break;
-
       event = gdk_event_new (GDK_MOTION_NOTIFY);
       event->motion.window = window;
       event->motion.time = _gdk_win32_get_next_tick (msg->time);
@@ -2657,14 +2791,14 @@ gdk_event_translate (GdkDisplay *display,
       _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
       event->motion.x += xoffset;
       event->motion.y += yoffset;
-      event->motion.x_root = msg->pt.x + _gdk_offset_x;
-      event->motion.y_root = msg->pt.y + _gdk_offset_y;
+      event->motion.x_root = current_root_x;
+      event->motion.y_root = current_root_y;
       event->motion.axes = NULL;
       event->motion.state = build_pointer_event_state (msg);
       event->motion.is_hint = FALSE;
-      event->motion.device = display->core_pointer;
+      event->motion.device = _gdk_display->core_pointer;
 
-      append_event (display, event);
+      append_event (event);
 
       return_val = TRUE;
       break;
@@ -2676,7 +2810,7 @@ gdk_event_translate (GdkDisplay *display,
       if (current_window != NULL &&
          (((GdkWindowObject *) current_window)->event_mask & GDK_LEAVE_NOTIFY_MASK))
        {
-         synthesize_crossing_events (_gdk_parent_root, GDK_CROSSING_NORMAL, msg);
+         synthesize_crossing_events (_gdk_root, GDK_CROSSING_NORMAL, msg);
        }
 
       break;
@@ -2698,6 +2832,7 @@ gdk_event_translate (GdkDisplay *display,
          synthesize_enter_or_leave_event (current_window, msg, 
                                           GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, detail,
                                           current_x, current_y);
+         assign_object (&current_window, _gdk_root);
        }
       else
        {
@@ -2729,16 +2864,9 @@ gdk_event_translate (GdkDisplay *display,
          assign_object (&window, new_window);
        }
 
-      if (((GdkWindowObject *) window)->extension_events != 0 &&
-         _gdk_input_ignore_core)
-       {
-         GDK_NOTE (EVENTS, g_print (" (ignored)"));
-         break;
-       }
-
       if (!propagate (&window, msg,
                      p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_scroll))
+                     doesnt_want_scroll, TRUE))
        break;
 
       if (GDK_WINDOW_DESTROYED (window))
@@ -2750,7 +2878,6 @@ gdk_event_translate (GdkDisplay *display,
       event->scroll.window = window;
       event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
        GDK_SCROLL_UP : GDK_SCROLL_DOWN;
-      event->scroll.window = window;
       event->scroll.time = _gdk_win32_get_next_tick (msg->time);
       _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
       event->scroll.x = (gint16) point.x + xoffset;
@@ -2758,9 +2885,9 @@ gdk_event_translate (GdkDisplay *display,
       event->scroll.x_root = (gint16) GET_X_LPARAM (msg->lParam) + _gdk_offset_x;
       event->scroll.y_root = (gint16) GET_Y_LPARAM (msg->lParam) + _gdk_offset_y;
       event->scroll.state = build_pointer_event_state (msg);
-      event->scroll.device = display->core_pointer;
+      event->scroll.device = _gdk_display->core_pointer;
 
-      append_event (display, event);
+      append_event (event);
       
       return_val = TRUE;
       break;
@@ -2795,16 +2922,25 @@ gdk_event_translate (GdkDisplay *display,
       break;
 
      case WM_MOUSEACTIVATE:
-       if (gdk_window_get_window_type (window) == GDK_WINDOW_TEMP) 
+       if (gdk_window_get_window_type (window) == GDK_WINDOW_TEMP 
+          || !((GdkWindowObject *)window)->accept_focus)
         {
           *ret_valp = MA_NOACTIVATE;
           return_val = TRUE;
         }
        break;
 
-    case WM_SETFOCUS:
     case WM_KILLFOCUS:
-      if (p_grab_window != NULL && !p_grab_owner_events && !(p_grab_mask & GDK_FOCUS_CHANGE_MASK))
+      if (p_grab_window != NULL && !GDK_WINDOW_DESTROYED (p_grab_window))
+       generate_grab_broken_event (p_grab_window, FALSE, NULL);
+
+      if (k_grab_window != NULL && !GDK_WINDOW_DESTROYED (k_grab_window) 
+         && k_grab_window != p_grab_window)
+       generate_grab_broken_event (k_grab_window, TRUE, NULL);
+
+      /* fallthrough */
+    case WM_SETFOCUS:
+      if (k_grab_window != NULL && !k_grab_owner_events)
        break;
 
       if (!(((GdkWindowObject *) window)->event_mask & GDK_FOCUS_CHANGE_MASK))
@@ -2813,12 +2949,7 @@ gdk_event_translate (GdkDisplay *display,
       if (GDK_WINDOW_DESTROYED (window))
        break;
 
-      event = gdk_event_new (GDK_FOCUS_CHANGE);
-      event->focus_change.window = window;
-      event->focus_change.in = (msg->message == WM_SETFOCUS);
-
-      append_event (display, event);
-
+      generate_focus_event (window, (msg->message == WM_SETFOCUS));
       return_val = TRUE;
       break;
 
@@ -2876,7 +3007,7 @@ gdk_event_translate (GdkDisplay *display,
       event = gdk_event_new (msg->wParam ? GDK_MAP : GDK_UNMAP);
       event->any.window = window;
 
-      append_event (display, event);
+      append_event (event);
       
       if (event->any.type == GDK_UNMAP &&
          p_grab_window == window)
@@ -2946,12 +3077,12 @@ gdk_event_translate (GdkDisplay *display,
       break;
 
     case WM_ENTERSIZEMOVE:
-      resizing = TRUE;
+      _sizemove_in_progress = TRUE;
       resize_timer = SetTimer (NULL, 0, 20, resize_timer_proc);
       break;
 
     case WM_EXITSIZEMOVE:
-      resizing = FALSE;
+      _sizemove_in_progress = FALSE;
       KillTimer (NULL, resize_timer);
       break;
 
@@ -2959,28 +3090,34 @@ gdk_event_translate (GdkDisplay *display,
       /* Once we've entered the moving or sizing modal loop, we won't
        * return to the main loop until we're done sizing or moving.
        */
-      if (resizing &&
+      if (_sizemove_in_progress &&
         GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
         !GDK_WINDOW_DESTROYED (window))
        {
          RECT client_rect;
+         POINT point;
 
          GetClientRect (msg->hwnd, &client_rect);
+         point.x = client_rect.left; /* always 0 */
+         point.y = client_rect.top;
+         /* top level windows need screen coords */
+         if (gdk_window_get_parent (window) == _gdk_root)
+           {
+             ClientToScreen (msg->hwnd, &point);
+             point.x += _gdk_offset_x;
+             point.y += _gdk_offset_y;
+           }
   
          GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->width = client_rect.right - client_rect.left;
          GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->height = client_rect.bottom - client_rect.top;
          
-         ((GdkWindowObject *) window)->x = client_rect.left;
-         ((GdkWindowObject *) window)->y = client_rect.top;
-         
+         ((GdkWindowObject *) window)->x = point.x;
+         ((GdkWindowObject *) window)->y = point.y;
+
          if (((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK)
            {
-             POINT point;
              GdkEvent *event = gdk_event_new (GDK_CONFIGURE);
              
-             point.x = point.y = 0;
-             ClientToScreen (msg->hwnd, &point);
-             
              event->configure.window = window;
              
              event->configure.width = client_rect.right - client_rect.left;
@@ -2989,12 +3126,6 @@ gdk_event_translate (GdkDisplay *display,
              event->configure.x = point.x;
              event->configure.y = point.y;
              
-             if (gdk_window_get_parent (window) == _gdk_parent_root)
-               {
-                 event->configure.x += _gdk_offset_x;
-                 event->configure.y += _gdk_offset_y;
-               }
-             
              if (((GdkWindowObject *) window)->resize_count > 1)
                ((GdkWindowObject *) window)->resize_count -= 1;
              
@@ -3009,7 +3140,7 @@ gdk_event_translate (GdkDisplay *display,
 #else /* Calling append_event() is slower, but guarantees that events won't
        * get reordered, I think.
        */
-             append_event (display, event);
+             append_event (event);
 #endif
              
              /* Dispatch main loop - to realize resizes... */
@@ -3157,7 +3288,7 @@ gdk_event_translate (GdkDisplay *display,
       impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl);
       mmi = (MINMAXINFO*) msg->lParam;
       GDK_NOTE (EVENTS, g_print (" (mintrack:%ldx%ld maxtrack:%ldx%ld "
-                                "maxpos:+%ld+%ld maxsize:%ldx%ld)",
+                                "maxpos:%+ld%+ld maxsize:%ldx%ld)",
                                 mmi->ptMinTrackSize.x, mmi->ptMinTrackSize.y,
                                 mmi->ptMaxTrackSize.x, mmi->ptMaxTrackSize.y,
                                 mmi->ptMaxPosition.x, mmi->ptMaxPosition.y,
@@ -3189,14 +3320,14 @@ gdk_event_translate (GdkDisplay *display,
          maxw = rect.right - rect.left;
          maxh = rect.bottom - rect.top;
          mmi->ptMaxTrackSize.x = maxw > 0 && maxw < G_MAXSHORT ? maxw : G_MAXSHORT;
-         mmi->ptMaxTrackSize.y = maxh > 0 && maxh < G_MAXSHORT ? maxw : G_MAXSHORT;
+         mmi->ptMaxTrackSize.y = maxh > 0 && maxh < G_MAXSHORT ? maxh : G_MAXSHORT;
        }
 
       if (impl->hint_flags & (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE))
        {
          /* Don't call DefWindowProc() */
          GDK_NOTE (EVENTS, g_print (" (handled, mintrack:%ldx%ld maxtrack:%ldx%ld "
-                                    "maxpos:+%ld+%ld maxsize:%ldx%ld)",
+                                    "maxpos:%+ld%+ld maxsize:%ldx%ld)",
                                     mmi->ptMinTrackSize.x, mmi->ptMinTrackSize.y,
                                     mmi->ptMaxTrackSize.x, mmi->ptMaxTrackSize.y,
                                     mmi->ptMaxPosition.x, mmi->ptMaxPosition.y,
@@ -3210,8 +3341,7 @@ gdk_event_translate (GdkDisplay *display,
                                 GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
 
       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
-         !IsIconic (msg->hwnd) &&
-         IsWindowVisible (msg->hwnd))
+         !IsIconic (msg->hwnd))
        {
          if (!GDK_WINDOW_DESTROYED (window))
            handle_configure_event (msg, window);
@@ -3227,14 +3357,14 @@ gdk_event_translate (GdkDisplay *display,
       event = gdk_event_new (GDK_DELETE);
       event->any.window = window;
 
-      append_event (display, event);
+      append_event (event);
 
       return_val = TRUE;
       break;
 
     case WM_DESTROY:
       if (window == current_window)
-       assign_object (&current_window, _gdk_parent_root);
+       assign_object (&current_window, _gdk_root);
 
       if (p_grab_window == window)
        gdk_pointer_ungrab (msg->time);
@@ -3242,7 +3372,7 @@ gdk_event_translate (GdkDisplay *display,
       if (k_grab_window == window)
        gdk_keyboard_ungrab (msg->time);
 
-      if ((window != NULL) && (_gdk_root_window != msg->hwnd))
+      if ((window != NULL) && (msg->hwnd != GetDesktopWindow ()))
        gdk_window_destroy_notify (window);
 
       if (window == NULL || GDK_WINDOW_DESTROYED (window))
@@ -3251,12 +3381,94 @@ gdk_event_translate (GdkDisplay *display,
       event = gdk_event_new (GDK_DESTROY);
       event->any.window = window;
 
-      append_event (display, event);
+      append_event (event);
 
       return_val = TRUE;
       break;
 
+    case WM_DISPLAYCHANGE:
+      handle_display_change ();
+      break;
+      
+    case WM_DESTROYCLIPBOARD:
+      if (!_ignore_destroy_clipboard)
+       {
+         event = gdk_event_new (GDK_SELECTION_CLEAR);
+         event->selection.window = window;
+         event->selection.selection = GDK_SELECTION_CLIPBOARD;
+         event->selection.time = _gdk_win32_get_next_tick (msg->time);
+          append_event (event);
+       }
+      else
+       return_val = TRUE;
+      break;
+
+    case WM_RENDERFORMAT:
+      GDK_NOTE (EVENTS, g_print (" %s", _gdk_win32_cf_to_string (msg->wParam)));
+
+      if (!(target = g_hash_table_lookup (_format_atom_table, GINT_TO_POINTER (msg->wParam))))
+       {
+         GDK_NOTE (EVENTS, g_print (" (target not found)"));
+         return_val = TRUE;
+         break;
+       }
+
+      /* We need to render to clipboard immediately, don't call
+       * append_event()
+       */
+      if (_gdk_event_func)
+       {
+         event = gdk_event_new (GDK_SELECTION_REQUEST);
+         event->selection.window = window;
+         event->selection.send_event = FALSE;
+         event->selection.selection = GDK_SELECTION_CLIPBOARD;
+         event->selection.target = target;
+         event->selection.property = _gdk_selection_property;
+         event->selection.requestor = (guint32) msg->hwnd;
+         event->selection.time = msg->time;
+
+         fixup_event (event);
+         GDK_NOTE (EVENTS, g_print (" (calling gdk_event_func)"));
+         GDK_NOTE (EVENTS, print_event (event));
+         (*_gdk_event_func) (event, _gdk_event_data);
+         gdk_event_free (event);
+
+         /* Now the clipboard owner should have rendered */
+         if (!_delayed_rendering_data)
+           GDK_NOTE (EVENTS, g_print (" (no _delayed_rendering_data?)"));
+         else
+           {
+             if (msg->wParam == CF_DIB)
+               {
+                 _delayed_rendering_data =
+                   _gdk_win32_selection_convert_to_dib (_delayed_rendering_data,
+                                                        target);
+                 if (!_delayed_rendering_data)
+                   {
+                     g_warning ("Cannot convert to DIB from delayed rendered image");
+                     break;
+                   }
+               }
+             /* The requestor is holding the clipboard, no
+              * OpenClipboard() is required/possible
+              */
+             API_CALL (SetClipboardData, (msg->wParam, _delayed_rendering_data));
+             _delayed_rendering_data = NULL;
+           }
+       }
+      break;
+
 #ifdef HAVE_WINTAB
+    case WM_ACTIVATE:
+      /* Bring any tablet contexts to the top of the overlap order when
+       * one of our windows is activated.
+       * NOTE: It doesn't seem to work well if it is done in WM_ACTIVATEAPP
+       * instead
+       */
+      if (LOWORD(msg->wParam) != WA_INACTIVE)
+       _gdk_input_set_tablet_active ();
+      break;
+      
       /* Handle WINTAB events here, as we know that gdkinput.c will
        * use the fixed WT_DEFBASE as lcMsgBase, and we thus can use the
        * constants as case labels.
@@ -3281,8 +3493,9 @@ gdk_event_translate (GdkDisplay *display,
 
       event = gdk_event_new (GDK_NOTHING);
       event->any.window = window;
+      g_object_ref (window);
       if (_gdk_input_other_event (event, msg, window))
-       append_event (display, event);
+       append_event (event);
       else
        gdk_event_free (event);
       break;
@@ -3317,13 +3530,12 @@ gdk_event_prepare (GSource *source,
 {
   MSG msg;
   gboolean retval;
-  GdkDisplay *display = gdk_display_get_default ();
-  
+
   GDK_THREADS_ENTER ();
 
   *timeout = -1;
 
-  retval = (_gdk_event_queue_find_first (display) != NULL ||
+  retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
            PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE));
 
   GDK_THREADS_LEAVE ();
@@ -3336,12 +3548,11 @@ gdk_event_check (GSource *source)
 {
   MSG msg;
   gboolean retval;
-  GdkDisplay *display = gdk_display_get_default ();
   
   GDK_THREADS_ENTER ();
 
   if (event_poll_fd.revents & G_IO_IN)
-    retval = (_gdk_event_queue_find_first (display) != NULL ||
+    retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
              PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE));
   else
     retval = FALSE;
@@ -3357,12 +3568,11 @@ gdk_event_dispatch (GSource     *source,
                    gpointer     user_data)
 {
   GdkEvent *event;
-  GdkDisplay *display = gdk_display_get_default ();
  
   GDK_THREADS_ENTER ();
 
-  _gdk_events_queue (display);
-  event = _gdk_event_unqueue (display);
+  _gdk_events_queue (_gdk_display);
+  event = _gdk_event_unqueue (_gdk_display);
 
   if (event)
     {
@@ -3432,7 +3642,7 @@ gdk_display_sync (GdkDisplay * display)
 {
   MSG msg;
 
-  g_return_if_fail (display == gdk_display_get_default ());
+  g_return_if_fail (display == _gdk_display);
 
   /* Process all messages currently available */
   while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
@@ -3442,7 +3652,7 @@ gdk_display_sync (GdkDisplay * display)
 void
 gdk_display_flush (GdkDisplay * display)
 {
-  g_return_if_fail (display == gdk_display_get_default ());
+  g_return_if_fail (display == _gdk_display);
 
   /* Nothing */
 }