]> Pileus Git - ~andy/gtk/blobdiff - gdk/win32/gdkevents-win32.c
Minor documentation improvements
[~andy/gtk] / gdk / win32 / gdkevents-win32.c
index 89dc4c85767466d930d7a31f0dfa1672c58bf1ae..cc7343c7f62b60ec46d3b8d5a54fcb8b1e389cf5 100644 (file)
@@ -1,6 +1,8 @@
 /* GDK - The GIMP Drawing Kit
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  * Copyright (C) 1998-2002 Tor Lillqvist
+ * Copyright (C) 2001,2009 Hans Breuer
+ * Copyright (C) 2007-2009 Cody Russell
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * not have TrackMouseEvent at all (?) --hb
  */
 
-#include <config.h>
+#include "config.h"
 
 #include <glib/gprintf.h>
 
-#if defined (__GNUC__) && defined (HAVE_DIMM_H)
-/* The w32api imm.h clashes a bit with the IE5.5 dimm.h */
-# define IMEMENUITEMINFOA hidden_IMEMENUITEMINFOA
-# define IMEMENUITEMINFOW hidden_IMEMENUITEMINFOW
-#endif
-
 #include "gdk.h"
+#include "gdkdisplayprivate.h"
 #include "gdkprivate-win32.h"
-#include "gdkinput-win32.h"
+#include "gdkwin32.h"
 #include "gdkkeysyms.h"
+#include "gdkdevicemanager-win32.h"
+#include "gdkdeviceprivate.h"
+#include "gdkdevice-wintab.h"
+#include "gdkwin32dnd.h"
+#include "gdkdndprivate.h"
 
 #include <windowsx.h>
 
 
 #include <imm.h>
 
-#if defined (__GNUC__) && defined (HAVE_DIMM_H)
-# undef IMEMENUITEMINFOA
-# undef IMEMENUITEMINFOW
-#endif
-
-#ifdef HAVE_DIMM_H
-#include <dimm.h>
-#endif
-
 #ifndef XBUTTON1
 #define XBUTTON1 1
 #define XBUTTON2 2
@@ -108,25 +101,14 @@ static gboolean gdk_event_dispatch (GSource     *source,
                                    gpointer     user_data);
 
 static void append_event (GdkEvent *event);
+static gboolean is_modally_blocked (GdkWindow   *window);
 
 /* Private variable declarations
  */
 
-static GdkWindow *p_grab_window = NULL; /* Window that currently holds
-                                        * the pointer grab
-                                        */
-
-static GdkWindow *p_grab_confine_to = NULL;
-
-static GdkWindow *k_grab_window = NULL; /* Window the holds the
-                                        * keyboard grab
-                                        */
-
 static GList *client_filters;  /* Filters for client messages */
+extern gint       _gdk_input_ignore_core;
 
-static gboolean p_grab_automatic;
-static GdkEventMask p_grab_mask;
-static gboolean p_grab_owner_events, k_grab_owner_events;
 static HCURSOR p_grab_cursor;
 
 static GSourceFuncs event_funcs = {
@@ -138,23 +120,21 @@ static GSourceFuncs event_funcs = {
 
 GPollFD event_poll_fd;
 
-static GdkWindow *current_window = NULL;
+static GdkWindow *current_toplevel = NULL;
 static gint current_x, current_y;
 static gint current_root_x, current_root_y;
-static UINT msh_mousewheel;
 static UINT client_message;
 
-#ifdef HAVE_DIMM_H
-static IActiveIMMApp *active_imm_app = NULL;
-static IActiveIMMMessagePumpOwner *active_imm_msgpump_owner = NULL;
-#endif
+static UINT got_gdk_events_message;
+static HWND modal_win32_dialog = NULL;
 
 #if 0
 static HKL latin_locale = NULL;
 #endif
 
 static gboolean in_ime_composition = FALSE;
-static UINT     resize_timer;
+static UINT     modal_timer;
+static UINT     sync_timer = 0;
 
 static int debug_indent = 0;
 
@@ -176,40 +156,19 @@ static void
 track_mouse_event (DWORD dwFlags,
                   HWND  hwnd)
 {
-  typedef BOOL (WINAPI *PFN_TrackMouseEvent) (LPTRACKMOUSEEVENT);
-  static PFN_TrackMouseEvent p_TrackMouseEvent = NULL;
-  static gboolean once = FALSE;
-
-  if (!once)
-    {
-      HMODULE user32;
-      HINSTANCE commctrl32;
+  TRACKMOUSEEVENT tme;
 
-      user32 = GetModuleHandle ("user32.dll");
-      if ((p_TrackMouseEvent = (PFN_TrackMouseEvent)GetProcAddress (user32, "TrackMouseEvent")) == NULL)
-        {
-          if ((commctrl32 = LoadLibrary ("commctrl32.dll")) != NULL)
-           p_TrackMouseEvent = (PFN_TrackMouseEvent)
-             GetProcAddress (commctrl32, "_TrackMouseEvent");
-        }
-      once = TRUE;
-    }
+  tme.cbSize = sizeof(TRACKMOUSEEVENT);
+  tme.dwFlags = dwFlags;
+  tme.hwndTrack = hwnd;
+  tme.dwHoverTime = HOVER_DEFAULT; /* not used */
 
-  if (p_TrackMouseEvent)
-    {
-      TRACKMOUSEEVENT tme;
-      tme.cbSize = sizeof(TRACKMOUSEEVENT);
-      tme.dwFlags = dwFlags;
-      tme.hwndTrack = hwnd;
-      tme.dwHoverTime = HOVER_DEFAULT; /* not used */
-
-      if (!p_TrackMouseEvent (&tme))
-        WIN32_API_FAILED ("TrackMouseEvent");
-      else if (dwFlags == TME_LEAVE)
-        GDK_NOTE (EVENTS, g_print(" (TrackMouseEvent %p)", hwnd));
-      else if (dwFlags == TME_CANCEL)
-       GDK_NOTE (EVENTS, g_print(" (cancel TrackMouseEvent %p)", hwnd));
-    }
+  if (!TrackMouseEvent (&tme))
+    WIN32_API_FAILED ("TrackMouseEvent");
+  else if (dwFlags == TME_LEAVE)
+    GDK_NOTE (EVENTS, g_print(" (TrackMouseEvent %p)", hwnd));
+  else if (dwFlags == TME_CANCEL)
+    GDK_NOTE (EVENTS, g_print(" (cancel TrackMouseEvent %p)", hwnd));
 }
 
 gulong
@@ -226,31 +185,44 @@ _gdk_win32_get_next_tick (gulong suggested_tick)
 }
 
 static void
-generate_focus_event (GdkWindow *window,
-                     gboolean   in)
+generate_focus_event (GdkDeviceManager *device_manager,
+                      GdkWindow        *window,
+                      gboolean          in)
 {
+  GdkDevice *device;
   GdkEvent *event;
 
+  device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard;
+
   event = gdk_event_new (GDK_FOCUS_CHANGE);
   event->focus_change.window = window;
   event->focus_change.in = in;
+  gdk_event_set_device (event, device);
 
   append_event (event);
 }
 
 static void
-generate_grab_broken_event (GdkWindow *window,
-                           gboolean   keyboard,
-                           GdkWindow *grab_window)
+generate_grab_broken_event (GdkDeviceManager *device_manager,
+                            GdkWindow        *window,
+                            gboolean          keyboard,
+                            GdkWindow        *grab_window)
 {
   GdkEvent *event = gdk_event_new (GDK_GRAB_BROKEN);
+  GdkDevice *device;
+
+  if (keyboard)
+    device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard;
+  else
+    device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_pointer;
 
   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;
-         
+  gdk_event_set_device (event, device);
+
   append_event (event);
 }
 
@@ -262,9 +234,6 @@ inner_window_procedure (HWND   hwnd,
 {
   MSG msg;
   DWORD pos;
-#ifdef HAVE_DIMM_H
-  LRESULT lres;
-#endif
   gint ret_val = 0;
 
   msg.hwnd = hwnd;
@@ -281,21 +250,16 @@ inner_window_procedure (HWND   hwnd,
       /* If gdk_event_translate() returns TRUE, we return ret_val from
        * the window procedure.
        */
+      if (modal_win32_dialog)
+       PostMessageW (modal_win32_dialog, got_gdk_events_message,
+                     (WPARAM) 1, 0);
       return ret_val;
     }
   else
     {
-      /* Otherwise call DefWindowProc(). */
-      GDK_NOTE (EVENTS, g_print (" DefWindowProc"));
-#ifndef HAVE_DIMM_H
-      return DefWindowProc (hwnd, message, wparam, lparam);
-#else
-      if (active_imm_app == NULL ||
-         (*active_imm_app->lpVtbl->OnDefWindowProc) (active_imm_app, hwnd, message, wparam, lparam, &lres) == S_FALSE)
-       return DefWindowProc (hwnd, message, wparam, lparam);
-      else
-       return lres;
-#endif
+      /* Otherwise call DefWindowProcW(). */
+      GDK_NOTE (EVENTS, g_print (" DefWindowProcW"));
+      return DefWindowProcW (hwnd, message, wparam, lparam);
     }
 }
 
@@ -315,8 +279,7 @@ _gdk_win32_window_procedure (HWND   hwnd,
   retval = inner_window_procedure (hwnd, message, wparam, lparam);
   debug_indent -= 2;
 
-  GDK_NOTE (EVENTS, g_print (" => %ld%s",
-                            retval, (debug_indent == 0 ? "\n" : "")));
+  GDK_NOTE (EVENTS, g_print (" => %I64d%s", (gint64) retval, (debug_indent == 0 ? "\n" : "")));
 
   return retval;
 }
@@ -325,9 +288,6 @@ void
 _gdk_events_init (void)
 {
   GSource *source;
-#ifdef HAVE_DIMM_H
-  HRESULT hres;
-#endif
 
 #if 0
   int i, j, n;
@@ -371,14 +331,8 @@ _gdk_events_init (void)
   };
 #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
-   * or on Win95.
-   */
-  msh_mousewheel = RegisterWindowMessage ("MSWHEEL_ROLLMSG");
-
   client_message = RegisterWindowMessage ("GDK_WIN32_CLIENT_MESSAGE");
+  got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
 
 #if 0
   /* Check if we have some input locale identifier loaded that uses a
@@ -422,6 +376,7 @@ _gdk_events_init (void)
 #endif
 
   source = g_source_new (&event_funcs, sizeof (GSource));
+  g_source_set_name (source, "GDK Win32 event source"); 
   g_source_set_priority (source, GDK_PRIORITY_EVENTS);
 
 #ifdef G_WITH_CYGWIN
@@ -436,59 +391,18 @@ _gdk_events_init (void)
   g_source_add_poll (source, &event_poll_fd);
   g_source_set_can_recurse (source, TRUE);
   g_source_attach (source, NULL);
-
-#ifdef HAVE_DIMM_H
-  hres = CoCreateInstance (&CLSID_CActiveIMM,
-                          NULL,
-                          CLSCTX_ALL,
-                          &IID_IActiveIMMApp,
-                          (LPVOID *) &active_imm_app);
-  
-  if (hres == S_OK)
-    {
-      GDK_NOTE (EVENTS, g_print ("IActiveIMMApp created %p\n",
-                                active_imm_app));
-      (*active_imm_app->lpVtbl->Activate) (active_imm_app, TRUE);
-      
-      hres = (*active_imm_app->lpVtbl->QueryInterface) (active_imm_app, &IID_IActiveIMMMessagePumpOwner, (void **) &active_imm_msgpump_owner);
-      GDK_NOTE (EVENTS, g_print ("IActiveIMMMessagePumpOwner created %p\n",
-                                active_imm_msgpump_owner));
-      (active_imm_msgpump_owner->lpVtbl->Start) (active_imm_msgpump_owner);
-    }
-#endif
 }
 
 gboolean
-gdk_events_pending (void)
+_gdk_win32_display_has_pending (GdkDisplay *display)
 {
   MSG msg;
-  return (_gdk_event_queue_find_first (_gdk_display) ||
-         PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE));
+  return (_gdk_event_queue_find_first (display) ||
+         (modal_win32_dialog == NULL &&
+          PeekMessageW (&msg, NULL, 0, 0, PM_NOREMOVE)));
 }
 
-GdkEvent*
-gdk_event_get_graphics_expose (GdkWindow *window)
-{
-  MSG msg;
-  GdkEvent *event = NULL;
-
-  g_return_val_if_fail (window != NULL, NULL);
-  
-  GDK_NOTE (EVENTS, g_print ("gdk_event_get_graphics_expose\n"));
-
-  if (PeekMessage (&msg, GDK_WINDOW_HWND (window), WM_PAINT, WM_PAINT, PM_REMOVE))
-    {
-      handle_wm_paint (&msg, window, TRUE, &event);
-      if (event != NULL)
-       {
-         GDK_NOTE (EVENTS, g_print ("gdk_event_get_graphics_expose: got it!\n"));
-         return event;
-       }
-    }
-  
-  GDK_NOTE (EVENTS, g_print ("gdk_event_get_graphics_expose: nope\n"));
-  return NULL; 
-}
+#if 0 /* Unused, but might be useful to re-introduce in some debugging output? */
 
 static char *
 event_mask_string (GdkEventMask mask)
@@ -526,146 +440,76 @@ event_mask_string (GdkEventMask mask)
   return bfr;
 }
 
+#endif
+
 GdkGrabStatus
-gdk_pointer_grab (GdkWindow    *window,
-                 gboolean      owner_events,
-                 GdkEventMask  event_mask,
-                 GdkWindow    *confine_to,
-                 GdkCursor    *cursor,
-                 guint32       time)
+_gdk_windowing_device_grab (GdkDevice    *device,
+                            GdkWindow    *window,
+                            GdkWindow    *native_window,
+                            gboolean      owner_events,
+                            GdkEventMask       event_mask,
+                            GdkWindow    *confine_to,
+                            GdkCursor    *cursor,
+                            guint32          time)
 {
   HCURSOR hcursor;
-  GdkCursorPrivate *cursor_private;
-  gint return_val = GDK_GRAB_SUCCESS;
+  GdkWin32Cursor *cursor_private;
+  gint return_val;
+  GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (native_window->impl);
 
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
   
-  cursor_private = (GdkCursorPrivate*) cursor;
+  cursor_private = (GdkWin32Cursor*) cursor;
   
   if (!cursor)
     hcursor = NULL;
   else if ((hcursor = CopyCursor (cursor_private->hcursor)) == NULL)
     WIN32_API_FAILED ("CopyCursor");
 
-  return_val = _gdk_input_grab_pointer (window,
-                                       owner_events,
-                                       event_mask,
-                                       confine_to,
-                                       time);
-
-  if (return_val == GDK_GRAB_SUCCESS)
-    {
-      if (!GDK_WINDOW_DESTROYED (window))
-       {
-         GDK_NOTE (EVENTS, g_print ("%sgdk_pointer_grab: %p %s %p %s%s",
-                                    (debug_indent > 0 ? "\n" : ""),
-                                    GDK_WINDOW_HWND (window),
-                                    (owner_events ? "TRUE" : "FALSE"),
-                                    hcursor,
-                                    event_mask_string (event_mask),
-                                    (debug_indent == 0 ? "\n" : "")));
-
-         p_grab_mask = event_mask;
-         p_grab_owner_events = owner_events;
-         p_grab_automatic = FALSE;
-         
-         SetCapture (GDK_WINDOW_HWND (window));
-         return_val = GDK_GRAB_SUCCESS;
-       }
-      else
-       return_val = GDK_GRAB_ALREADY_GRABBED;
-    }
-  
-  if (return_val == GDK_GRAB_SUCCESS)
-    {
-      GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl);
-
-      if (p_grab_window != NULL && p_grab_window != window)
-       generate_grab_broken_event (p_grab_window, FALSE, window);
-      
-      p_grab_window = window;
-
-      if (p_grab_cursor != NULL)
-       {
-         if (GetCursor () == p_grab_cursor)
-           SetCursor (NULL);
-         DestroyCursor (p_grab_cursor);
-       }
-
-      p_grab_cursor = hcursor;
-
-      if (p_grab_cursor != NULL)
-       SetCursor (p_grab_cursor);
-      else if (impl->hcursor != NULL)
-       SetCursor (impl->hcursor);
-      else
-       SetCursor (LoadCursor (NULL, IDC_ARROW));
-
-      if (confine_to != NULL)
-       {
-         gint x, y, width, height;
-         RECT rect;
-
-         gdk_window_get_origin (confine_to, &x, &y);
-         gdk_drawable_get_size (confine_to, &width, &height);
-
-         rect.left = x;
-         rect.top = y;
-         rect.right = x + width;
-         rect.bottom = y + height;
-         API_CALL (ClipCursor, (&rect));
-         p_grab_confine_to = confine_to;
-       }
-
-      /* FIXME: Generate GDK_CROSSING_GRAB events */
-    }
-  
-  return return_val;
-}
-
-void
-gdk_display_pointer_ungrab (GdkDisplay *display,
-                            guint32     time)
-{
-  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" : "")));
-
-  _gdk_input_ungrab_pointer (time);
-
-  if (GetCapture () != NULL)
-    ReleaseCapture ();
-
-  /* FIXME: Generate GDK_CROSSING_UNGRAB events */
+  return_val = GDK_DEVICE_GET_CLASS (device)->grab (device,
+                                                    native_window,
+                                                    owner_events,
+                                                    event_mask,
+                                                    confine_to,
+                                                    cursor,
+                                                    time);
 
-  p_grab_window = NULL;
+  /* TODO_CSW: grab brokens, confine window, input_grab */
   if (p_grab_cursor != NULL)
     {
       if (GetCursor () == p_grab_cursor)
-       SetCursor (NULL);
+        SetCursor (NULL);
       DestroyCursor (p_grab_cursor);
-      p_grab_cursor = NULL;
     }
 
-  if (p_grab_confine_to != NULL)
-    {
-      API_CALL (ClipCursor, (NULL));
-      p_grab_confine_to = NULL;
-    }
+  p_grab_cursor = hcursor;
+
+  if (p_grab_cursor != NULL)
+    SetCursor (p_grab_cursor);
+  else if (impl->hcursor != NULL)
+    SetCursor (impl->hcursor);
+  else
+    SetCursor (LoadCursor (NULL, IDC_ARROW));
+
+  return return_val;
 }
 
 static GdkWindow *
-find_real_window_for_grabbed_mouse_event (GdkWindow* reported_window,
-                                         MSG*       msg)
+find_window_for_mouse_event (GdkWindow* reported_window,
+                            MSG*       msg)
 {
   HWND hwnd;
   POINTS points;
   POINT pt;
   GdkWindow* other_window = NULL;
+  GdkDeviceManagerWin32 *device_manager;
+
+  device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (_gdk_display));
+
+  if (!_gdk_display_get_last_device_grab (_gdk_display, device_manager->core_pointer))
+    return reported_window;
 
   points = MAKEPOINTS (msg->lParam);
   pt.x = points.x;
@@ -683,192 +527,21 @@ find_real_window_for_grabbed_mouse_event (GdkWindow* reported_window,
       if (!PtInRect (&rect, pt))
        return _gdk_root;
 
-      other_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
+      other_window = gdk_win32_handle_table_lookup (hwnd);
     }
 
   if (other_window == NULL)
     return _gdk_root;
 
-  return other_window;
-}
-
-static GdkWindow* 
-find_window_for_mouse_event (GdkWindow* reported_window,
-                            MSG*       msg)
-{
-  if (p_grab_window == NULL || !p_grab_owner_events)
-    return reported_window;
-  else
-    return find_real_window_for_grabbed_mouse_event (reported_window, msg);
-}
-
-gboolean
-gdk_display_pointer_is_grabbed (GdkDisplay *display)
-{
-  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;
-}
-
-gboolean
-gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
-                                  GdkWindow **grab_window,
-                                  gboolean   *owner_events)
-{
-  g_return_val_if_fail (display == _gdk_display, FALSE);
-
-  if (p_grab_window != NULL)
-    {
-      if (grab_window)
-        *grab_window = p_grab_window;
-      if (owner_events)
-        *owner_events = p_grab_owner_events;
-
-      return TRUE;
-    }
-  else
-    return FALSE;
-}
-
-GdkGrabStatus
-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);
-  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-  
-  GDK_NOTE (EVENTS, g_print ("gdk_keyboard_grab %p\n",
-                            GDK_WINDOW_HWND (window)));
-
-  if (!GDK_WINDOW_DESTROYED (window))
-    {
-      k_grab_owner_events = owner_events != 0;
-      return_val = GDK_GRAB_SUCCESS;
-    }
-  else
-    return_val = GDK_GRAB_ALREADY_GRABBED;
-
-  if (return_val == GDK_GRAB_SUCCESS)
-    {
-      if (k_grab_window != NULL && k_grab_window != window)
-       generate_grab_broken_event (k_grab_window, TRUE, window);
-
-      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;
-}
-
-void
-gdk_display_keyboard_ungrab (GdkDisplay *display,
-                             guint32 time)
-{
-  GdkWindow *real_focus_window, *grab_focus_window;
-
-  g_return_if_fail (display == _gdk_display);
-
-  GDK_NOTE (EVENTS, g_print ("gdk_keyboard_ungrab\n"));
-
-  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);
-       }
-    }
-
-  k_grab_window = NULL;
-}
-
-gboolean
-gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
-                                   GdkWindow **grab_window,
-                                   gboolean   *owner_events)
-{
-  g_return_val_if_fail (display == _gdk_display, FALSE);
-
-  if (k_grab_window)
-    {
-      if (grab_window)
-        *grab_window = k_grab_window;
-      if (owner_events)
-        *owner_events = k_grab_owner_events;
-
-      return TRUE;
-    }
-  else
-    return FALSE;
-}
-
-void 
-gdk_display_add_client_message_filter (GdkDisplay   *display,
-                                      GdkAtom       message_type,
-                                      GdkFilterFunc func,
-                                      gpointer      data)
-{
-  /* XXX */
-  gdk_add_client_message_filter (message_type, func, data);
-}
-
-void 
-gdk_add_client_message_filter (GdkAtom       message_type,
-                              GdkFilterFunc func,
-                              gpointer      data)
-{
-  GdkClientFilter *filter = g_new (GdkClientFilter, 1);
+  /* need to also adjust the coordinates to the new window */
+  pt.x = points.x;
+  pt.y = points.y;
+  ClientToScreen (msg->hwnd, &pt);
+  ScreenToClient (GDK_WINDOW_HWND (other_window), &pt);
+  /* ATTENTION: need to update client coords */
+  msg->lParam = MAKELPARAM (pt.x, pt.y);
 
-  filter->type = message_type;
-  filter->function = func;
-  filter->data = data;
-  
-  client_filters = g_list_append (client_filters, filter);
+  return other_window;
 }
 
 static void
@@ -894,21 +567,6 @@ build_key_event_state (GdkEvent *event,
   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.
-   *
-   * Alternatively, we could have some state saved when the Control
-   * and Alt keys messages come in, as the KF_EXTENDED bit in lParam
-   * does indicate correctly whether it is the right Control or Alt
-   * key. But that would be a bit messy.
-   */
-  if (!G_WIN32_IS_NT_BASED () &&
-      _gdk_keyboard_has_altgr &&
-      key_state[VK_CONTROL] & 0x80 &&
-      key_state[VK_MENU] & 0x80)
-    key_state[VK_LCONTROL] = key_state[VK_RMENU] = 0x80;
-
   if (_gdk_keyboard_has_altgr &&
       (key_state[VK_LCONTROL] & 0x80) &&
       (key_state[VK_RMENU] & 0x80))
@@ -1015,10 +673,11 @@ print_event_state (guint state)
 #undef CASE
 }
 
-static void
-print_event (GdkEvent *event)
+void
+_gdk_win32_print_event (const GdkEvent *event)
 {
   gchar *escaped, *kvname;
+  gchar *selection_name, *target_name, *property_name;
 
   g_print ("%s%*s===> ", (debug_indent > 0 ? "\n" : ""), debug_indent, "");
   switch (event->any.type)
@@ -1055,7 +714,6 @@ print_event (GdkEvent *event)
     CASE (GDK_DROP_FINISHED);
     CASE (GDK_CLIENT_EVENT);
     CASE (GDK_VISIBILITY_NOTIFY);
-    CASE (GDK_NO_EXPOSE);
     CASE (GDK_SCROLL);
     CASE (GDK_WINDOW_STATE);
     CASE (GDK_SETTING);
@@ -1065,7 +723,7 @@ print_event (GdkEvent *event)
     default: g_assert_not_reached ();
     }
 
-  g_print (" %p ", GDK_WINDOW_HWND (event->any.window));
+  g_print (" %p ", event->any.window ? GDK_WINDOW_HWND (event->any.window) : NULL);
 
   switch (event->any.type)
     {
@@ -1134,6 +792,35 @@ print_event (GdkEvent *event)
               event->configure.x, event->configure.y,
               event->configure.width, event->configure.height);
       break;
+    case GDK_SELECTION_CLEAR:
+    case GDK_SELECTION_REQUEST:
+    case GDK_SELECTION_NOTIFY:
+      selection_name = gdk_atom_name (event->selection.selection);
+      target_name = gdk_atom_name (event->selection.target);
+      property_name = gdk_atom_name (event->selection.property);
+      g_print ("sel:%s tgt:%s prop:%s",
+              selection_name, target_name, property_name);
+      g_free (selection_name);
+      g_free (target_name);
+      g_free (property_name);
+      break;
+    case GDK_DRAG_ENTER:
+    case GDK_DRAG_LEAVE:
+    case GDK_DRAG_MOTION:
+    case GDK_DRAG_STATUS:
+    case GDK_DROP_START:
+    case GDK_DROP_FINISHED:
+      if (event->dnd.context != NULL)
+       g_print ("ctx:%p: %s %s src:%p dest:%p",
+                event->dnd.context,
+                _gdk_win32_drag_protocol_to_string (event->dnd.context->protocol),
+                event->dnd.context->is_source ? "SOURCE" : "DEST",
+                event->dnd.context->source_window == NULL ? NULL : GDK_WINDOW_HWND (event->dnd.context->source_window),
+                event->dnd.context->dest_window == NULL ? NULL : GDK_WINDOW_HWND (event->dnd.context->dest_window));
+      break;
+    case GDK_CLIENT_EVENT:
+      /* no more GdkEventClient */
+      break;
     case GDK_SCROLL:
       g_print ("(%.4g,%.4g) (%.4g,%.4g) %s ",
               event->scroll.x, event->scroll.y,
@@ -1204,9 +891,18 @@ fixup_event (GdkEvent *event)
 static void
 append_event (GdkEvent *event)
 {
+  GList *link;
+  
   fixup_event (event);
+#if 1
+  link = _gdk_event_queue_append (_gdk_display, event);
+  GDK_NOTE (EVENTS, _gdk_win32_print_event (event));
+  /* event morphing, the passed in may not be valid afterwards */
+  _gdk_windowing_got_event (_gdk_display, link, event, 0);
+#else
   _gdk_event_queue_append (_gdk_display, event);
-  GDK_NOTE (EVENTS, print_event (event));
+  GDK_NOTE (EVENTS, _gdk_win32_print_event (event));
+#endif
 }
 
 static void
@@ -1220,7 +916,7 @@ fill_key_event_string (GdkEvent *event)
    */
   
   c = 0;
-  if (event->key.keyval != GDK_VoidSymbol)
+  if (event->key.keyval != GDK_KEY_VoidSymbol)
     c = gdk_keyval_to_unicode (event->key.keyval);
 
   if (c)
@@ -1257,13 +953,13 @@ fill_key_event_string (GdkEvent *event)
       if (event->key.string)
        event->key.length = bytes_written;
     }
-  else if (event->key.keyval == GDK_Escape)
+  else if (event->key.keyval == GDK_KEY_Escape)
     {
       event->key.length = 1;
       event->key.string = g_strdup ("\033");
     }
-  else if (event->key.keyval == GDK_Return ||
-          event->key.keyval == GDK_KP_Enter)
+  else if (event->key.keyval == GDK_KEY_Return ||
+          event->key.keyval == GDK_KEY_KP_Enter)
     {
       event->key.length = 1;
       event->key.string = g_strdup ("\r");
@@ -1277,9 +973,9 @@ fill_key_event_string (GdkEvent *event)
 }
 
 static GdkFilterReturn
-apply_filters (GdkWindow  *window,
-              MSG        *msg,
-              GList      *filters)
+apply_event_filters (GdkWindow  *window,
+                    MSG        *msg,
+                    GList     **filters)
 {
   GdkFilterReturn result = GDK_FILTER_CONTINUE;
   GdkEvent *event;
@@ -1297,13 +993,34 @@ apply_filters (GdkWindow  *window,
    */
   node = _gdk_event_queue_append (_gdk_display, event);
   
-  tmp_list = filters;
+  tmp_list = *filters;
   while (tmp_list)
     {
       GdkEventFilter *filter = (GdkEventFilter *) tmp_list->data;
-      
-      tmp_list = tmp_list->next;
+      GList *node;
+
+      if ((filter->flags & GDK_EVENT_FILTER_REMOVED) != 0)
+        {
+          tmp_list = tmp_list->next;
+          continue;
+        }
+
+      filter->ref_count++;
       result = filter->function (msg, event, filter->data);
+
+      /* get the next node after running the function since the
+         function may add or remove a next node */
+      node = tmp_list;
+      tmp_list = tmp_list->next;
+
+      filter->ref_count--;
+      if (filter->ref_count == 0)
+        {
+          *filters = g_list_remove_link (*filters, node);
+          g_list_free_1 (node);
+          g_free (filter);
+        }
+
       if (result !=  GDK_FILTER_CONTINUE)
        break;
     }
@@ -1318,335 +1035,139 @@ apply_filters (GdkWindow  *window,
     {
       ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
       fixup_event (event);
-      GDK_NOTE (EVENTS, print_event (event));
+      GDK_NOTE (EVENTS, _gdk_win32_print_event (event));
     }
   return result;
 }
 
-static gboolean
-gdk_window_is_ancestor (GdkWindow *ancestor,
-                       GdkWindow *window)
+/*
+ * On Windows, transient windows will not have their own taskbar entries.
+ * Because of this, we must hide and restore groups of transients in both
+ * directions.  That is, all transient children must be hidden or restored
+ * with this window, but if this window's transient owner also has a
+ * transient owner then this window's transient owner must be hidden/restored
+ * with this one.  And etc, up the chain until we hit an ancestor that has no
+ * transient owner.
+ *
+ * It would be a good idea if applications don't chain transient windows
+ * together.  There's a limit to how much evil GTK can try to shield you
+ * from.
+ */
+static void
+show_window_recurse (GdkWindow *window, gboolean hide_window)
+{
+  GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+  GSList *children = impl->transient_children;
+  GdkWindow *child = NULL;
+
+  if (!impl->changing_state)
+    {
+      impl->changing_state = TRUE;
+
+      if (children != NULL)
+       {
+         while (children != NULL)
+           {
+             child = children->data;
+             show_window_recurse (child, hide_window);
+
+             children = g_slist_next (children);
+           }
+       }
+
+      if (GDK_WINDOW_IS_MAPPED (window))
+       {
+         if (!hide_window)
+           {
+             if (gdk_window_get_state (window) & GDK_WINDOW_STATE_ICONIFIED)
+               {
+                 if (gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED)
+                   {
+                     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMAXIMIZED);
+                   }
+                 else
+                   {
+                     ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
+                   }
+               }
+           }
+         else
+           {
+             ShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE);
+           }
+       }
+
+      impl->changing_state = FALSE;
+    }
+}
+
+static void
+do_show_window (GdkWindow *window, gboolean hide_window)
 {
-  if (ancestor == NULL || window == NULL)
-    return FALSE;
+  GdkWindow *tmp_window = NULL;
+  GdkWindowImplWin32 *tmp_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+  if (!tmp_impl->changing_state)
+    {
+      /* Find the top-level window in our transient chain. */
+      while (tmp_impl->transient_owner != NULL)
+       {
+         tmp_window = tmp_impl->transient_owner;
+         tmp_impl = GDK_WINDOW_IMPL_WIN32 (tmp_window->impl);
+       }
+
+      /* If we couldn't find one, use the window provided. */
+      if (tmp_window == NULL)
+       {
+         tmp_window = window;
+       }
 
-  return (gdk_window_get_parent (window) == ancestor ||
-         gdk_window_is_ancestor (ancestor, gdk_window_get_parent (window)));
+      /* Recursively show/hide every window in the chain. */
+      if (tmp_window != window)
+       {
+         show_window_recurse (tmp_window, hide_window);
+       }
+    }
 }
 
 static void
-synthesize_enter_or_leave_event (GdkWindow     *window,
-                                MSG            *msg,
-                                GdkEventType    type,
-                                GdkCrossingMode mode,
-                                GdkNotifyType detail,
-                                gint            x,
-                                gint            y)
+synthesize_enter_or_leave_event (GdkWindow        *window,
+                                 MSG             *msg,
+                                 GdkEventType     type,
+                                 GdkCrossingMode   mode,
+                                 GdkNotifyType     detail)
 {
   GdkEvent *event;
-  gint xoffset, yoffset;
+  POINT pt;
+
+  pt = msg->pt;
+  ScreenToClient (GDK_WINDOW_HWND (window), &pt);
   
   event = gdk_event_new (type);
   event->crossing.window = window;
   event->crossing.subwindow = NULL;
   event->crossing.time = _gdk_win32_get_next_tick (msg->time);
-  _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
-  event->crossing.x = x + xoffset;
-  event->crossing.y = y + yoffset;
+  event->crossing.x = pt.x;
+  event->crossing.y = pt.y;
   event->crossing.x_root = msg->pt.x + _gdk_offset_x;
   event->crossing.y_root = msg->pt.y + _gdk_offset_y;
   event->crossing.mode = mode;
   event->crossing.detail = detail;
   event->crossing.focus = TRUE; /* FIXME: Set correctly */
   event->crossing.state = 0;   /* FIXME: Set correctly */
-  
+  gdk_event_set_device (event, _gdk_display->core_pointer);
+
   append_event (event);
   
   if (type == GDK_ENTER_NOTIFY &&
-      ((GdkWindowObject *) window)->extension_events != 0)
-    _gdk_input_enter_event (window);
-}
-
-static void
-synthesize_leave_event (GdkWindow      *window,
-                       MSG            *msg,
-                       GdkCrossingMode mode,
-                       GdkNotifyType   detail)
-{
-  POINT pt;
-
-  if (p_grab_window != NULL && !p_grab_owner_events && !(p_grab_mask & GDK_LEAVE_NOTIFY_MASK))
-    return;
-
-  if (!(((GdkWindowObject *) window)->event_mask & GDK_LEAVE_NOTIFY_MASK))
-    return;
-
-  /* Leave events are at (current_x,current_y) in current_window */
-
-  if (current_window != window)
-    {
-      pt.x = current_x;
-      pt.y = current_y;
-      ClientToScreen (GDK_WINDOW_HWND (current_window), &pt);
-      ScreenToClient (GDK_WINDOW_HWND (window), &pt);
-      synthesize_enter_or_leave_event (window, msg, GDK_LEAVE_NOTIFY, mode, detail, pt.x, pt.y);
-    }
-  else
-    synthesize_enter_or_leave_event (window, msg, GDK_LEAVE_NOTIFY, mode, detail, current_x, current_y);
-
-  /* This would only make sense if the WM_MOUSEMOVE messages would come
-   * before the respective WM_MOUSELEAVE message, which apparently they
-   * do not.
-  track_mouse_event (TME_CANCEL, msg->hwnd);
-   */
-}
-  
-static void
-synthesize_enter_event (GdkWindow      *window,
-                       MSG            *msg,
-                       GdkCrossingMode mode,
-                       GdkNotifyType   detail)
-{
-  POINT pt;
-
-  if (p_grab_window != NULL && !p_grab_owner_events && !(p_grab_mask & GDK_ENTER_NOTIFY_MASK))
-    return;
-
-  if (!(((GdkWindowObject *) window)->event_mask & GDK_ENTER_NOTIFY_MASK))
-    return;
-
-  /* Enter events are at GET_X_LPARAM (msg->lParam), GET_Y_LPARAM
-   * (msg->lParam) in msg->hwnd
-   */
-
-  pt.x = GET_X_LPARAM (msg->lParam);
-  pt.y = GET_Y_LPARAM (msg->lParam);
-  if (msg->hwnd != GDK_WINDOW_HWND (window))
-    {
-      ClientToScreen (msg->hwnd, &pt);
-      ScreenToClient (GDK_WINDOW_HWND (window), &pt);
-    }
-  synthesize_enter_or_leave_event (window, msg, GDK_ENTER_NOTIFY, mode, detail, pt.x, pt.y);
-
-  track_mouse_event (TME_LEAVE, GDK_WINDOW_HWND (window));
-}
-  
-static void
-synthesize_enter_events (GdkWindow      *from,
-                        GdkWindow      *to,
-                        MSG            *msg,
-                        GdkCrossingMode mode,
-                        GdkNotifyType   detail)
-{
-  GdkWindow *prev = gdk_window_get_parent (to);
-  
-  if (prev != from)
-    synthesize_enter_events (from, prev, msg, mode, detail);
-  synthesize_enter_event (to, msg, mode, detail);
+      window->extension_events != 0)
+    _gdk_device_wintab_update_window_coords (window);
 }
                         
-static void
-synthesize_leave_events (GdkWindow     *from,
-                        GdkWindow      *to,
-                        MSG            *msg,
-                        GdkCrossingMode mode,
-                        GdkNotifyType   detail)
-{
-  GdkWindow *next = gdk_window_get_parent (from);
-  
-  synthesize_leave_event (from, msg, mode, detail);
-  if (next != to)
-    synthesize_leave_events (next, to, msg, mode, detail);
-}
-                        
-static void
-synthesize_crossing_events (GdkWindow      *window,
-                           GdkCrossingMode mode,
-                           MSG            *msg)
-{
-  GdkWindow *intermediate, *tem, *common_ancestor;
-
-  if (gdk_window_is_ancestor (current_window, window))
-    {
-      /* Pointer has moved to an inferior window. */
-      synthesize_leave_event (current_window, msg, mode, GDK_NOTIFY_INFERIOR);
-      
-      /* If there are intermediate windows, generate ENTER_NOTIFY
-       * events for them
-       */
-      intermediate = gdk_window_get_parent (window);
-      if (intermediate != current_window)
-       {
-         synthesize_enter_events (current_window, intermediate, msg, mode, GDK_NOTIFY_VIRTUAL);
-       }
-      
-      synthesize_enter_event (window, msg, mode, GDK_NOTIFY_ANCESTOR);
-    }
-  else if (gdk_window_is_ancestor (window, current_window))
-    {
-      /* Pointer has moved to an ancestor window. */
-      synthesize_leave_event (current_window, msg, mode, GDK_NOTIFY_ANCESTOR);
-      
-      /* If there are intermediate windows, generate LEAVE_NOTIFY
-       * events for them
-       */
-      intermediate = gdk_window_get_parent (current_window);
-      if (intermediate != window)
-       {
-         synthesize_leave_events (intermediate, window, msg, mode, GDK_NOTIFY_VIRTUAL);
-       }
-
-      synthesize_enter_event (window, msg, mode, GDK_NOTIFY_INFERIOR);
-    }
-  else if (current_window)
-    {
-      /* Find least common ancestor of current_window and window */
-      tem = current_window;
-      do {
-       common_ancestor = gdk_window_get_parent (tem);
-       tem = common_ancestor;
-      } while (common_ancestor &&
-              !gdk_window_is_ancestor (common_ancestor, window));
-      if (common_ancestor)
-       {
-         synthesize_leave_event (current_window, msg, mode, GDK_NOTIFY_NONLINEAR);
-         intermediate = gdk_window_get_parent (current_window);
-         if (intermediate != common_ancestor)
-           {
-             synthesize_leave_events (intermediate, common_ancestor,
-                                      msg, mode, GDK_NOTIFY_NONLINEAR_VIRTUAL);
-           }
-         intermediate = gdk_window_get_parent (window);
-         if (intermediate != common_ancestor)
-           {
-             synthesize_enter_events (common_ancestor, intermediate,
-                                      msg, mode, GDK_NOTIFY_NONLINEAR_VIRTUAL);
-           }
-         synthesize_enter_event (window, msg, mode, GDK_NOTIFY_NONLINEAR);
-       }
-    }
-  else
-    {
-      /* Dunno where we are coming from */
-      synthesize_enter_event (window, msg, mode, GDK_NOTIFY_UNKNOWN);
-    }
-
-  assign_object (&current_window, window);
-}
-
-static void
-synthesize_expose_events (GdkWindow *window)
-{
-  RECT r;
-  HDC hdc;
-  GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (((GdkWindowObject *) window)->impl);
-  GList *list = gdk_window_get_children (window);
-  GList *head = list;
-  GdkEvent *event;
-  int k;
-  
-  while (list)
-    {
-      synthesize_expose_events ((GdkWindow *) list->data);
-      list = list->next;
-    }
-
-  g_list_free (head);
-
-  if (((GdkWindowObject *) window)->input_only)
-    ;
-  else if (!(hdc = GetDC (impl->handle)))
-    WIN32_GDI_FAILED ("GetDC");
-  else
-    {
-      if ((k = GetClipBox (hdc, &r)) == ERROR)
-       WIN32_GDI_FAILED ("GetClipBox");
-      else if (k != NULLREGION)
-       {
-         event = gdk_event_new (GDK_EXPOSE);
-         event->expose.window = window;
-         event->expose.area.x = r.left;
-         event->expose.area.y = r.top;
-         event->expose.area.width = r.right - r.left;
-         event->expose.area.height = r.bottom - r.top;
-         event->expose.region = gdk_region_rectangle (&(event->expose.area));
-         event->expose.count = 0;
-  
-         append_event (event);
-       }
-      GDI_CALL (ReleaseDC, (impl->handle, hdc));
-    }
-}
-
-static void
-update_colors (GdkWindow *window,
-              gboolean   top)
-{
-  HDC hdc;
-  GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (((GdkWindowObject *) window)->impl);
-  GList *list = gdk_window_get_children (window);
-  GList *head = list;
-
-  GDK_NOTE (COLORMAP, (top ? g_print ("update_colors:") : (void) 0));
-
-  while (list)
-    {
-      update_colors ((GdkWindow *) list->data, FALSE);
-      list = list->next;
-    }
-  g_list_free (head);
-
-  if (((GdkWindowObject *) window)->input_only ||
-      impl->colormap == NULL)
-    return;
-
-  if (!(hdc = GetDC (impl->handle)))
-    WIN32_GDI_FAILED ("GetDC");
-  else
-    {
-      GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (impl->colormap);
-      HPALETTE holdpal;
-      gint k;
-      
-      if ((holdpal = SelectPalette (hdc, cmapp->hpal, TRUE)) == NULL)
-       WIN32_GDI_FAILED ("SelectPalette");
-      else if ((k = RealizePalette (hdc)) == GDI_ERROR)
-       WIN32_GDI_FAILED ("RealizePalette");
-      else
-       {
-         GDK_NOTE (COLORMAP,
-                   (k > 0 ?
-                    g_print (" %p pal=%p: realized %d colors\n"
-                             "update_colors:",
-                             impl->handle, cmapp->hpal, k) :
-                    (void) 0,
-                    g_print (" %p", impl->handle)));
-         GDI_CALL (UpdateColors, (hdc));
-         SelectPalette (hdc, holdpal, TRUE);
-         RealizePalette (hdc);
-       }
-      GDI_CALL (ReleaseDC, (impl->handle, hdc));
-    }
-  GDK_NOTE (COLORMAP, (top ? g_print ("\n") : (void) 0));
-}
-
-static void
-translate_mouse_coords (GdkWindow *window1,
-                       GdkWindow *window2,
-                       MSG       *msg)
-{
-  POINT pt;
-
-  pt.x = GET_X_LPARAM (msg->lParam);
-  pt.y = GET_Y_LPARAM (msg->lParam);
-  ClientToScreen (GDK_WINDOW_HWND (window1), &pt);
-  ScreenToClient (GDK_WINDOW_HWND (window2), &pt);
-  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 */
+ * because an extended input device is active
+ */
 static gboolean
 propagate (GdkWindow  **window,
           MSG         *msg,
@@ -1657,16 +1178,15 @@ propagate (GdkWindow  **window,
                                         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 */
+      /* See if the event should be ignored because an extended input
+       * device is used
+       */
       if (check_extended &&
-         ((GdkWindowObject *) grab_window)->extension_events != 0 &&
+         grab_window->extension_events != 0 &&
          _gdk_input_ignore_core)
        {
          GDK_NOTE (EVENTS, g_print (" (ignored for grabber)"));
@@ -1684,18 +1204,20 @@ propagate (GdkWindow  **window,
          return TRUE;
        }
     }
+
+  /* If we come here, we know that if grab_window != NULL then
+   * grab_owner_events is TRUE
+   */
   while (TRUE)
     {
-      /* See if the event should be ignored because an extended input device
-       * is used */
       if (check_extended &&
-         ((GdkWindowObject *) *window)->extension_events != 0 &&
+         (*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))
+      if ((*doesnt_want_it) ((*window)->event_mask, msg))
        {
          /* Owner doesn't want it, propagate to parent. */
          GdkWindow *parent = gdk_window_get_parent (*window);
@@ -1706,10 +1228,8 @@ propagate (GdkWindow  **window,
                {
                  /* 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 &&
+                     grab_window->extension_events != 0 &&
                      _gdk_input_ignore_core)
                    {
                      GDK_NOTE (EVENTS, g_print (" (ignored for grabber)"));
@@ -1738,7 +1258,6 @@ propagate (GdkWindow  **window,
          else
            {
              assign_object (window, parent);
-             in_propagation = TRUE;
              /* The only branch where we actually continue the loop */
            }
        }
@@ -1764,42 +1283,6 @@ doesnt_want_char (gint mask,
   return !(mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK));
 }
 
-static gboolean
-doesnt_want_button_press (gint mask,
-                         MSG *msg)
-{
-  return !(mask & GDK_BUTTON_PRESS_MASK);
-}
-
-static gboolean
-doesnt_want_button_release (gint mask,
-                           MSG *msg)
-{
-  return !(mask & GDK_BUTTON_RELEASE_MASK);
-}
-
-static gboolean
-doesnt_want_button_motion (gint mask,
-                          MSG *msg)
-{
-  return !((mask & GDK_POINTER_MOTION_MASK) ||
-          ((msg->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON)) && (mask & GDK_BUTTON_MOTION_MASK)) ||
-          ((msg->wParam & MK_LBUTTON) && (mask & GDK_BUTTON1_MOTION_MASK)) ||
-          ((msg->wParam & MK_MBUTTON) && (mask & GDK_BUTTON2_MOTION_MASK)) ||
-          ((msg->wParam & MK_RBUTTON) && (mask & GDK_BUTTON3_MOTION_MASK)));
-}
-
-static gboolean
-doesnt_want_scroll (gint mask,
-                   MSG *msg)
-{
-#if 0
-  return !(mask & GDK_SCROLL_MASK);
-#else
-  return !(mask & GDK_BUTTON_PRESS_MASK);
-#endif
-}
-
 static void
 handle_configure_event (MSG       *msg,
                        GdkWindow *window)
@@ -1810,6 +1293,7 @@ handle_configure_event (MSG       *msg,
   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)
     {
@@ -1818,13 +1302,15 @@ handle_configure_event (MSG       *msg,
       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;
+  window->width = client_rect.right - client_rect.left;
+  window->height = client_rect.bottom - client_rect.top;
   
-  ((GdkWindowObject *) window)->x = point.x;
-  ((GdkWindowObject *) window)->y = point.y;
+  window->x = point.x;
+  window->y = point.y;
+
+  _gdk_window_update_size (window);
   
-  if (((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK)
+  if (window->event_mask & GDK_STRUCTURE_MASK)
     {
       GdkEvent *event = gdk_event_new (GDK_CONFIGURE);
 
@@ -1840,145 +1326,12 @@ handle_configure_event (MSG       *msg,
     }
 }
 
-static void
-erase_background (GdkWindow *window,
-                 HDC        hdc)
-{
-  HDC bgdc = NULL;
-  HBRUSH hbr = NULL;
-  HPALETTE holdpal = NULL;
-  RECT rect;
-  COLORREF bg;
-  GdkColormap *colormap;
-  GdkColormapPrivateWin32 *colormap_private;
-  int x, y;
-  int x_offset, y_offset;
-  
-  if (((GdkWindowObject *) window)->input_only ||
-      ((GdkWindowObject *) window)->bg_pixmap == GDK_NO_BG ||
-      GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.no_bg)
-    {
-      return;
-    }
-
-  colormap = gdk_drawable_get_colormap (window);
-
-  if (colormap &&
-      (colormap->visual->type == GDK_VISUAL_PSEUDO_COLOR ||
-       colormap->visual->type == GDK_VISUAL_STATIC_COLOR))
-    {
-      int k;
-         
-      colormap_private = GDK_WIN32_COLORMAP_DATA (colormap);
-
-      if (!(holdpal = SelectPalette (hdc,  colormap_private->hpal, FALSE)))
-        WIN32_GDI_FAILED ("SelectPalette");
-      else if ((k = RealizePalette (hdc)) == GDI_ERROR)
-       WIN32_GDI_FAILED ("RealizePalette");
-      else if (k > 0)
-       GDK_NOTE (COLORMAP, g_print ("erase_background: realized %p: %d colors\n",
-                                    colormap_private->hpal, k));
-    }
-  
-  x_offset = y_offset = 0;
-  while (window && ((GdkWindowObject *) window)->bg_pixmap == GDK_PARENT_RELATIVE_BG)
-    {
-      /* If this window should have the same background as the parent,
-       * fetch the parent. (And if the same goes for the parent, fetch
-       * the grandparent, etc.)
-       */
-      x_offset += ((GdkWindowObject *) window)->x;
-      y_offset += ((GdkWindowObject *) window)->y;
-      window = GDK_WINDOW (((GdkWindowObject *) window)->parent);
-    }
-  
-  if (GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.no_bg)
-    {
-      /* Improves scolling effect, e.g. main buttons of testgtk */
-      return;
-    }
-
-  GetClipBox (hdc, &rect);
-
-  if (((GdkWindowObject *) window)->bg_pixmap == NULL)
-    {
-      bg = _gdk_win32_colormap_color (GDK_DRAWABLE_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->colormap,
-                                     ((GdkWindowObject *) window)->bg_color.pixel);
-      
-      if (!(hbr = CreateSolidBrush (bg)))
-       WIN32_GDI_FAILED ("CreateSolidBrush");
-      else if (!FillRect (hdc, &rect, hbr))
-       WIN32_GDI_FAILED ("FillRect");
-      if (hbr != NULL)
-       DeleteObject (hbr);
-    }
-  else if (((GdkWindowObject *) window)->bg_pixmap != GDK_NO_BG)
-    {
-      GdkPixmap *pixmap = ((GdkWindowObject *) window)->bg_pixmap;
-      GdkPixmapImplWin32 *pixmap_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl);
-      
-      if (x_offset == 0 && y_offset == 0 &&
-         pixmap_impl->width <= 8 && pixmap_impl->height <= 8)
-       {
-         if (!(hbr = CreatePatternBrush (GDK_PIXMAP_HBITMAP (pixmap))))
-           WIN32_GDI_FAILED ("CreatePatternBrush");
-         else if (!FillRect (hdc, &rect, hbr))
-           WIN32_GDI_FAILED ("FillRect");
-         if (hbr != NULL)
-           DeleteObject (hbr);
-       }
-      else
-       {
-         HGDIOBJ oldbitmap;
-
-         if (!(bgdc = CreateCompatibleDC (hdc)))
-           {
-             WIN32_GDI_FAILED ("CreateCompatibleDC");
-             return;
-           }
-         if (!(oldbitmap = SelectObject (bgdc, GDK_PIXMAP_HBITMAP (pixmap))))
-           {
-             WIN32_GDI_FAILED ("SelectObject");
-             DeleteDC (bgdc);
-             return;
-           }
-         x = -x_offset;
-         while (x < rect.right)
-           {
-             if (x + pixmap_impl->width >= rect.left)
-               {
-                 y = -y_offset;
-                 while (y < rect.bottom)
-                   {
-                     if (y + pixmap_impl->height >= rect.top)
-                       {
-                         if (!BitBlt (hdc, x, y,
-                                      pixmap_impl->width, pixmap_impl->height,
-                                      bgdc, 0, 0, SRCCOPY))
-                           {
-                             WIN32_GDI_FAILED ("BitBlt");
-                             SelectObject (bgdc, oldbitmap);
-                             DeleteDC (bgdc);
-                             return;
-                           }
-                       }
-                     y += pixmap_impl->height;
-                   }
-               }
-             x += pixmap_impl->width;
-           }
-         SelectObject (bgdc, oldbitmap);
-         DeleteDC (bgdc);
-       }
-    }
-}
-
-static GdkRegion *
+cairo_region_t *
 _gdk_win32_hrgn_to_region (HRGN hrgn)
 {
   RGNDATA *rgndata;
   RECT *rects;
-  GdkRegion *result;
+  cairo_region_t *result;
   gint nbytes;
   guint i;
 
@@ -1997,7 +1350,7 @@ _gdk_win32_hrgn_to_region (HRGN hrgn)
       return NULL;
     }
 
-  result = gdk_region_new ();
+  result = cairo_region_create ();
   rects = (RECT *) rgndata->Buffer;
   for (i = 0; i < rgndata->rdh.nCount; i++)
     {
@@ -2008,7 +1361,7 @@ _gdk_win32_hrgn_to_region (HRGN hrgn)
       r.width = rects[i].right - r.x;
       r.height = rects[i].bottom - r.y;
 
-      gdk_region_union_with_rect (result, &r);
+      cairo_region_union_rectangle (result, &r);
     }
 
   g_free (rgndata);
@@ -2036,12 +1389,12 @@ handle_wm_paint (MSG        *msg,
   HRGN hrgn = CreateRectRgn (0, 0, 0, 0);
   HDC hdc;
   PAINTSTRUCT paintstruct;
-  GdkRegion *update_region;
-  gint xoffset, yoffset;
+  cairo_region_t *update_region;
 
   if (GetUpdateRgn (msg->hwnd, hrgn, FALSE) == ERROR)
     {
       WIN32_GDI_FAILED ("GetUpdateRgn");
+      DeleteObject (hrgn);
       return;
     }
 
@@ -2055,29 +1408,6 @@ handle_wm_paint (MSG        *msg,
 
   EndPaint (msg->hwnd, &paintstruct);
 
-  /* HB: don't generate GDK_EXPOSE events for InputOnly
-   * windows -> backing store now works!
-   */
-  if (((GdkWindowObject *) window)->input_only)
-    {
-      DeleteObject (hrgn);
-      return;
-    }
-
-  if (!(((GdkWindowObject *) window)->event_mask & GDK_EXPOSURE_MASK))
-    {
-      GDK_NOTE (EVENTS, g_print (" (ignored)"));
-      DeleteObject (hrgn);
-      return;
-    }
-
-#if 0 /* we need to process exposes even with GDK_NO_BG
-   * Otherwise The GIMP canvas update is broken ....
-   */
-  if (((GdkWindowObject *) window)->bg_pixmap == GDK_NO_BG)
-    break;
-#endif
-
   if ((paintstruct.rcPaint.right == paintstruct.rcPaint.left) ||
       (paintstruct.rcPaint.bottom == paintstruct.rcPaint.top))
     {
@@ -2114,36 +1444,73 @@ handle_wm_paint (MSG        *msg,
            }
        }
 
+      DeleteObject (hrgn);
       return;
     }
 
   update_region = _gdk_win32_hrgn_to_region (hrgn);
-
-  _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
-  gdk_region_offset (update_region, xoffset, yoffset);
-  
-  _gdk_window_process_expose (window, update_region);
-  gdk_region_destroy (update_region);
+  if (!cairo_region_is_empty (update_region))
+    _gdk_window_invalidate_for_expose (window, update_region);
+  cairo_region_destroy (update_region);
 
   DeleteObject (hrgn);
 }
 
-static void
-handle_stuff_while_moving_or_resizing (void)
+static VOID CALLBACK 
+modal_timer_proc (HWND     hwnd,
+                 UINT     msg,
+                 UINT_PTR id,
+                 DWORD    time)
 {
   int arbitrary_limit = 1;
-  while (g_main_pending () && arbitrary_limit--)
-    g_main_iteration (FALSE);
+
+  while (_modal_operation_in_progress &&
+        g_main_context_pending (NULL) &&
+        arbitrary_limit--)
+    g_main_context_iteration (NULL, FALSE);
+}
+
+void
+_gdk_win32_begin_modal_call (void)
+{
+  g_assert (!_modal_operation_in_progress);
+
+  _modal_operation_in_progress = TRUE;
+
+  modal_timer = SetTimer (NULL, 0, 10, modal_timer_proc);
+  if (modal_timer == 0)
+    WIN32_API_FAILED ("SetTimer");
+}
+
+void
+_gdk_win32_end_modal_call (void)
+{
+  g_assert (_modal_operation_in_progress);
+
+  _modal_operation_in_progress = FALSE;
+
+  if (modal_timer != 0)
+    {
+      API_CALL (KillTimer, (NULL, modal_timer));
+      modal_timer = 0;
+   }
 }
 
 static VOID CALLBACK
-resize_timer_proc (HWND     hwnd,
-                  UINT     msg,
-                  UINT     id,
-                  DWORD    time)
+sync_timer_proc (HWND     hwnd,
+                UINT     msg,
+                UINT_PTR id,
+                DWORD    time)
 {
-  if (_sizemove_in_progress)
-    handle_stuff_while_moving_or_resizing ();
+  MSG message;
+  if (PeekMessageW (&message, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE))
+    {
+      return;
+    }
+
+  RedrawWindow (hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN);
+
+  KillTimer (hwnd, sync_timer);
 }
 
 static void
@@ -2155,35 +1522,165 @@ handle_display_change (void)
 }
 
 static void
-generate_button_event (GdkEventType type,
-                      gint         button,
-                      GdkWindow   *window,
-                      GdkWindow   *orig_window,
-                      MSG         *msg)
+generate_button_event (GdkEventType      type,
+                       gint              button,
+                       GdkWindow        *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;
+  gdk_event_set_device (event, _gdk_display->core_pointer);
 
   append_event (event);
+}
+
+static void
+ensure_stacking_on_unminimize (MSG *msg)
+{
+  HWND rover;
+  HWND lowest_transient = NULL;
+
+  rover = msg->hwnd;
+  while ((rover = GetNextWindow (rover, GW_HWNDNEXT)))
+    {
+      GdkWindow *rover_gdkw = gdk_win32_handle_table_lookup (rover);
+
+      /* Checking window group not implemented yet */
+      if (rover_gdkw)
+       {
+         GdkWindowImplWin32 *rover_impl =
+           GDK_WINDOW_IMPL_WIN32 (rover_gdkw->impl);
+
+         if (GDK_WINDOW_IS_MAPPED (rover_gdkw) &&
+             (rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY ||
+              rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
+              rover_impl->transient_owner != NULL))
+           {
+             lowest_transient = rover;
+           }
+       }
+    }
+  if (lowest_transient != NULL)
+    {
+      GDK_NOTE (EVENTS, g_print (" restacking: %p", lowest_transient));
+      SetWindowPos (msg->hwnd, lowest_transient, 0, 0, 0, 0,
+                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+    }
+}
+
+static gboolean
+ensure_stacking_on_window_pos_changing (MSG       *msg,
+                                       GdkWindow *window)
+{
+  GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+  WINDOWPOS *windowpos = (WINDOWPOS *) msg->lParam;
+
+  if (GetActiveWindow () == msg->hwnd &&
+      impl->type_hint != GDK_WINDOW_TYPE_HINT_UTILITY &&
+      impl->type_hint != GDK_WINDOW_TYPE_HINT_DIALOG &&
+      impl->transient_owner == NULL)
+    {
+      /* Make sure the window stays behind any transient-type windows
+       * of the same window group.
+       *
+       * If the window is not active and being activated, we let
+       * Windows bring it to the top and rely on the WM_ACTIVATEAPP
+       * handling to bring any utility windows on top of it.
+       */
+      HWND rover;
+      gboolean restacking;
+
+      rover = windowpos->hwndInsertAfter;
+      restacking = FALSE;
+      while (rover)
+       {
+         GdkWindow *rover_gdkw = gdk_win32_handle_table_lookup (rover);
+
+         /* Checking window group not implemented yet */
+         if (rover_gdkw)
+           {
+             GdkWindowImplWin32 *rover_impl =
+               GDK_WINDOW_IMPL_WIN32 (rover_gdkw->impl);
+
+             if (GDK_WINDOW_IS_MAPPED (rover_gdkw) &&
+                 (rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY ||
+                  rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
+                  rover_impl->transient_owner != NULL))
+               {
+                 restacking = TRUE;
+                 windowpos->hwndInsertAfter = rover;
+               }
+           }
+         rover = GetNextWindow (rover, GW_HWNDNEXT);
+       }
+
+      if (restacking)
+       {
+         GDK_NOTE (EVENTS, g_print (" restacking: %p", windowpos->hwndInsertAfter));
+         return TRUE;
+       }
+    }
+  return FALSE;
+}
+
+static void
+ensure_stacking_on_activate_app (MSG       *msg,
+                                GdkWindow *window)
+{
+  GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+  if (impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY ||
+      impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
+      impl->transient_owner != NULL)
+    {
+      SetWindowPos (msg->hwnd, HWND_TOP, 0, 0, 0, 0,
+                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+      return;
+    }
+
+  if (IsWindowVisible (msg->hwnd) &&
+      msg->hwnd == GetActiveWindow ())
+    {
+      /* This window is not a transient-type window and it is the
+       * activated window. Make sure this window is as visible as
+       * possible, just below the lowest transient-type window of this
+       * app.
+       */
+      HWND rover;
+
+      rover = msg->hwnd;
+      while ((rover = GetNextWindow (rover, GW_HWNDPREV)))
+       {
+         GdkWindow *rover_gdkw = gdk_win32_handle_table_lookup (rover);
+
+         /* Checking window group not implemented yet */
+         if (rover_gdkw)
+           {
+             GdkWindowImplWin32 *rover_impl =
+               GDK_WINDOW_IMPL_WIN32 (rover_gdkw->impl);
 
-  if (type == GDK_BUTTON_PRESS)
-    _gdk_event_button_generate (_gdk_display, event);
+             if (GDK_WINDOW_IS_MAPPED (rover_gdkw) &&
+                 (rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY ||
+                  rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
+                  rover_impl->transient_owner != NULL))
+               {
+                 GDK_NOTE (EVENTS, g_print (" restacking: %p", rover));
+                 SetWindowPos (msg->hwnd, rover, 0, 0, 0, 0,
+                               SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+                 break;
+               }
+           }
+       }
+    }
 }
 
 static gboolean
@@ -2197,6 +1694,7 @@ gdk_event_translate (MSG  *msg,
   HCURSOR hcursor;
   BYTE key_state[256];
   HIMC himc;
+  WINDOWPOS *windowpos;
 
   GdkEvent *event;
 
@@ -2206,10 +1704,14 @@ gdk_event_translate (MSG  *msg,
   GdkWindow *window = NULL;
   GdkWindowImplWin32 *impl;
 
-  GdkWindow *orig_window, *new_window;
-  gint xoffset, yoffset;
+  GdkWindow *orig_window, *new_window, *toplevel;
+
+  GdkDeviceManager *device_manager;
+
+  GdkDeviceGrabInfo *keyboard_grab = NULL;
+  GdkDeviceGrabInfo *pointer_grab = NULL;
+  GdkWindow *grab_window = NULL;
 
-  static gint update_colors_counter = 0;
   gint button;
   GdkAtom target;
 
@@ -2222,17 +1724,17 @@ gdk_event_translate (MSG  *msg,
     {
       /* Apply global filters */
 
-      GdkFilterReturn result = apply_filters (NULL, msg, _gdk_default_filters);
+      GdkFilterReturn result = apply_event_filters (NULL, msg, &_gdk_default_filters);
       
       /* If result is GDK_FILTER_CONTINUE, we continue as if nothing
        * happened. If it is GDK_FILTER_REMOVE or GDK_FILTER_TRANSLATE,
-       * we return TRUE, and DefWindowProc() will not be called.
+       * we return TRUE, and DefWindowProcW() will not be called.
        */
       if (result == GDK_FILTER_REMOVE || result == GDK_FILTER_TRANSLATE)
        return TRUE;
     }
 
-  window = gdk_win32_handle_table_lookup ((GdkNativeWindow) msg->hwnd);
+  window = gdk_win32_handle_table_lookup (msg->hwnd);
   orig_window = window;
 
   if (window == NULL)
@@ -2240,7 +1742,7 @@ gdk_event_translate (MSG  *msg,
       /* XXX Handle WM_QUIT here ? */
       if (msg->message == WM_QUIT)
        {
-         GDK_NOTE (EVENTS, g_print (" %d", msg->wParam));
+         GDK_NOTE (EVENTS, g_print (" %d", (int) msg->wParam));
          exit (msg->wParam);
        }
       else if (msg->message == WM_MOVE ||
@@ -2254,12 +1756,11 @@ gdk_event_translate (MSG  *msg,
           */
          GDK_NOTE (EVENTS, g_print (" (posted)"));
        
-         PostMessage (msg->hwnd, msg->message,
-                      msg->wParam, msg->lParam);
+         PostMessageW (msg->hwnd, msg->message, msg->wParam, msg->lParam);
        }
       else if (msg->message == WM_CREATE)
        {
-         window = (UNALIGNED GdkWindow*) (((LPCREATESTRUCT) msg->lParam)->lpCreateParams);
+         window = (UNALIGNED GdkWindow*) (((LPCREATESTRUCTW) msg->lParam)->lpCreateParams);
          GDK_WINDOW_HWND (window) = msg->hwnd;
        }
       else
@@ -2268,7 +1769,14 @@ gdk_event_translate (MSG  *msg,
        }
       return FALSE;
     }
-  
+
+  device_manager = gdk_display_get_device_manager (_gdk_display);
+
+  keyboard_grab = _gdk_display_get_last_device_grab (_gdk_display,
+                                                     GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard);
+  pointer_grab = _gdk_display_get_last_device_grab (_gdk_display,
+                                                    GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_pointer);
+
   g_object_ref (window);
 
   /* window's refcount has now been increased, so code below should
@@ -2278,11 +1786,11 @@ gdk_event_translate (MSG  *msg,
    */
 #define return GOTO_DONE_INSTEAD
   
-  if (!GDK_WINDOW_DESTROYED (window) && ((GdkWindowObject *) window)->filters)
+  if (!GDK_WINDOW_DESTROYED (window) && window->filters)
     {
       /* Apply per-window filters */
 
-      GdkFilterReturn result = apply_filters (window, msg, ((GdkWindowObject *) window)->filters);
+      GdkFilterReturn result = apply_event_filters (window, msg, &window->filters);
 
       if (result == GDK_FILTER_REMOVE || result == GDK_FILTER_TRANSLATE)
        {
@@ -2291,60 +1799,19 @@ gdk_event_translate (MSG  *msg,
        }
     }
 
-  if (msg->message == msh_mousewheel)
-    {
-      GDK_NOTE (EVENTS, g_print (" (MSH_MOUSEWHEEL)"));
-      
-      /* 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.
-       */
-      point.x = GET_X_LPARAM (msg->lParam);
-      point.y = GET_Y_LPARAM (msg->lParam);
-      if ((hwnd = WindowFromPoint (point)) == NULL)
-       goto done;
-
-      msg->hwnd = hwnd;
-      if ((new_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) msg->hwnd)) == NULL)
-       goto done;
-
-      assign_object (&window, new_window);
-
-      if (!propagate (&window, msg,
-                     p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_scroll, TRUE))
-       goto done;
-
-      if (GDK_WINDOW_DESTROYED (window))
-       goto done;
-
-      ScreenToClient (msg->hwnd, &point);
-
-      event = gdk_event_new (GDK_SCROLL);
-      event->scroll.window = window;
-      event->scroll.direction = ((int) msg->wParam > 0) ?
-       GDK_SCROLL_UP : GDK_SCROLL_DOWN;
-      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;
-      event->scroll.y = (gint16) point.y + yoffset;
-      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 = _gdk_display->core_pointer;
-
-      append_event (event);
-
-      return_val = TRUE;
-      goto done;
-    }
-  else if (msg->message == client_message)
+  if (msg->message == client_message)
     {
       GList *tmp_list;
       GdkFilterReturn result = GDK_FILTER_CONTINUE;
+      GList *node;
 
       GDK_NOTE (EVENTS, g_print (" client_message"));
 
+      event = gdk_event_new (GDK_NOTHING);
+      ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
+
+      node = _gdk_event_queue_append (_gdk_display, event);
+
       tmp_list = client_filters;
       while (tmp_list)
        {
@@ -2354,38 +1821,33 @@ gdk_event_translate (MSG  *msg,
 
          if (filter->type == GDK_POINTER_TO_ATOM (msg->wParam))
            {
-             GList *filter_list = g_list_append (NULL, filter);
-             
              GDK_NOTE (EVENTS, g_print (" (match)"));
 
-             result = apply_filters (window, msg, filter_list);
-
-             g_list_free (filter_list);
+             result = (*filter->function) (msg, event, filter->data);
 
              if (result != GDK_FILTER_CONTINUE)
                break;
            }
        }
 
-      if (result == GDK_FILTER_REMOVE || result == GDK_FILTER_TRANSLATE)
+      switch (result)
        {
+       case GDK_FILTER_REMOVE:
+         _gdk_event_queue_remove_link (_gdk_display, node);
+         g_list_free_1 (node);
+         gdk_event_free (event);
+         return_val = TRUE;
+         goto done;
+
+       case GDK_FILTER_TRANSLATE:
+         ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+         GDK_NOTE (EVENTS, _gdk_win32_print_event (event));
          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);
-         
+
+       case GDK_FILTER_CONTINUE:
+         /* No more: Send unknown client messages on to Gtk for it to use */
+         GDK_NOTE (EVENTS, _gdk_win32_print_event (event));
          return_val = TRUE;
          goto done;
        }
@@ -2402,9 +1864,9 @@ gdk_event_translate (MSG  *msg,
       _gdk_input_codepage = atoi (buf);
       _gdk_keymap_serial++;
       GDK_NOTE (EVENTS,
-               g_print (" cs:%lu hkl:%lx%s cp:%d",
+               g_print (" cs:%lu hkl:%p%s cp:%d",
                         (gulong) msg->wParam,
-                        msg->lParam, _gdk_input_locale_is_ime ? " (IME)" : "",
+                        (gpointer) msg->lParam, _gdk_input_locale_is_ime ? " (IME)" : "",
                         _gdk_input_codepage));
       break;
 
@@ -2413,7 +1875,7 @@ gdk_event_translate (MSG  *msg,
       GDK_NOTE (EVENTS,
                g_print (" %s ch:%.02x %s",
                         _gdk_win32_key_to_string (msg->lParam),
-                        msg->wParam,
+                        (int) msg->wParam,
                         decode_key_lparam (msg->lParam)));
 
       /* If posted without us having keyboard focus, ignore */
@@ -2421,13 +1883,12 @@ gdk_event_translate (MSG  *msg,
          !(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 &&
+      if (!keyboard_grab &&
          (msg->wParam == VK_TAB ||
           msg->wParam == VK_SPACE ||
-          msg->wParam == VK_RETURN ||
           msg->wParam == VK_F4))
        break;
 
@@ -2439,7 +1900,7 @@ gdk_event_translate (MSG  *msg,
       GDK_NOTE (EVENTS, 
                g_print (" %s ch:%.02x %s",
                         _gdk_win32_key_to_string (msg->lParam),
-                        msg->wParam,
+                        (int) msg->wParam,
                         decode_key_lparam (msg->lParam)));
 
     keyup_or_down:
@@ -2449,8 +1910,11 @@ gdk_event_translate (MSG  *msg,
          in_ime_composition)
        break;
 
-      if (!propagate (&window, msg,
-                     k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
+      if (keyboard_grab &&
+          !propagate (&window, msg,
+                     keyboard_grab->window,
+                     keyboard_grab->owner_events,
+                     GDK_ALL_EVENTS_MASK,
                      doesnt_want_key, FALSE))
        break;
 
@@ -2462,10 +1926,11 @@ gdk_event_translate (MSG  *msg,
                             GDK_KEY_PRESS : GDK_KEY_RELEASE);
       event->key.window = window;
       event->key.time = _gdk_win32_get_next_tick (msg->time);
-      event->key.keyval = GDK_VoidSymbol;
+      event->key.keyval = GDK_KEY_VoidSymbol;
       event->key.string = NULL;
       event->key.length = 0;
       event->key.hardware_keycode = msg->wParam;
+      gdk_event_set_device (event, GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard);
       if (HIWORD (msg->lParam) & KF_EXTENDED)
        {
          switch (msg->wParam)
@@ -2493,12 +1958,16 @@ gdk_event_translate (MSG  *msg,
       
       build_key_event_state (event, key_state);
 
-      gdk_keymap_translate_keyboard_state (NULL,
-                                          event->key.hardware_keycode,
-                                          event->key.state,
-                                          event->key.group,
-                                          &event->key.keyval,
-                                          NULL, NULL, NULL);
+      if (msg->wParam == VK_PACKET &&
+         ToUnicode (VK_PACKET, HIWORD (msg->lParam), key_state, wbuf, 1, 0) == 1)
+       event->key.keyval = gdk_unicode_to_keyval (wbuf[0]);
+      else
+       gdk_keymap_translate_keyboard_state (_gdk_win32_display_get_keymap (_gdk_display),
+                                            event->key.hardware_keycode,
+                                            event->key.state,
+                                            event->key.group,
+                                            &event->key.keyval,
+                                            NULL, NULL, NULL);
 
       fill_key_event_string (event);
 
@@ -2514,7 +1983,7 @@ gdk_event_translate (MSG  *msg,
     case WM_SYSCHAR:
       if (msg->wParam != VK_SPACE)
        {
-         /* To prevent beeps, don't let DefWindowProc() be called */
+         /* To prevent beeps, don't let DefWindowProcW() be called */
          return_val = TRUE;
          goto done;
        }
@@ -2546,13 +2015,16 @@ gdk_event_translate (MSG  *msg,
        * WM_IME_CHAR might work on NT4 or Win9x with ActiveIMM, but
        * use WM_IME_COMPOSITION there, too, to simplify the code.
        */
-      GDK_NOTE (EVENTS, g_print (" %#lx", msg->lParam));
+      GDK_NOTE (EVENTS, g_print (" %#lx", (long) msg->lParam));
 
       if (!(msg->lParam & GCS_RESULTSTR))
        break;
 
-      if (!propagate (&window, msg,
-                     k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
+      if (keyboard_grab &&
+          !propagate (&window, msg,
+                     keyboard_grab->window,
+                     keyboard_grab->owner_events,
+                     GDK_ALL_EVENTS_MASK,
                      doesnt_want_char, FALSE))
        break;
 
@@ -2570,21 +2042,23 @@ gdk_event_translate (MSG  *msg,
 
       for (i = 0; i < ccount; i++)
        {
-         if (((GdkWindowObject *) window)->event_mask & GDK_KEY_PRESS_MASK)
+         if (window->event_mask & GDK_KEY_PRESS_MASK)
            {
              /* Build a key press event */
              event = gdk_event_new (GDK_KEY_PRESS);
              event->key.window = window;
+        gdk_event_set_device (event, GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard);
              build_wm_ime_composition_event (event, msg, wbuf[i], key_state);
 
              append_event (event);
            }
          
-         if (((GdkWindowObject *) window)->event_mask & GDK_KEY_RELEASE_MASK)
+         if (window->event_mask & GDK_KEY_RELEASE_MASK)
            {
              /* Build a key release event.  */
              event = gdk_event_new (GDK_KEY_RELEASE);
              event->key.window = window;
+        gdk_event_set_device (event, GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard);
              build_wm_ime_composition_event (event, msg, wbuf[i], key_state);
 
              append_event (event);
@@ -2617,42 +2091,13 @@ gdk_event_translate (MSG  *msg,
                         GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
 
       assign_object (&window, find_window_for_mouse_event (window, msg));
-
-      if (p_grab_window != NULL)
-       {
-         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);
-       }
-      else
-       {
-         if (window != current_window)
-           synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
-       }
-
-      if (!propagate (&window, msg,
-                     p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_button_press, TRUE))
-       break;
-
+      /* TODO_CSW?: there used to some synthesize and propagate */
       if (GDK_WINDOW_DESTROYED (window))
        break;
 
-      /* Emulate X11's automatic active grab */
-      if (!p_grab_window)
-       {
-         /* No explicit active grab, let's start one automatically */
-         GDK_NOTE (EVENTS, g_print (" (automatic grab)"));
-         gdk_pointer_grab (window,
-                           FALSE,
-                           ((GdkWindowObject *) window)->event_mask,
-                           NULL, NULL, 0);
-         p_grab_automatic = TRUE;
-       }
-
+      /* TODO_CSW? Emulate X11's automatic active grab */
       generate_button_event (GDK_BUTTON_PRESS, button,
-                            window, orig_window, msg);
+                            window, msg);
 
       return_val = TRUE;
       break;
@@ -2681,22 +2126,8 @@ gdk_event_translate (MSG  *msg,
                         GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
 
       assign_object (&window, find_window_for_mouse_event (window, msg));
-
-      if (p_grab_window != NULL)
-       {
-         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);
-       }
-      else
-       {
-         if (window != current_window)
-           synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
-       }
-
 #if 0
-      if (((GdkWindowObject *) window)->extension_events != 0 &&
+      if (window->extension_events != 0 &&
          _gdk_input_ignore_core)
        {
          GDK_NOTE (EVENTS, g_print (" (ignored)"));
@@ -2704,34 +2135,34 @@ gdk_event_translate (MSG  *msg,
        }
 #endif
 
-      if (!propagate (&window, msg,
-                     p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_button_release, TRUE))
-       {
-       }
-      else if (!GDK_WINDOW_DESTROYED (window))
-       {
-         generate_button_event (GDK_BUTTON_RELEASE, button,
-                                window, orig_window, msg);
-       }
-
-      if (p_grab_window != NULL &&
-         p_grab_automatic &&
-         (msg->wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) == 0)
-       {
-         /* Terminate automatic grab */
-         gdk_pointer_ungrab (0);
-       }
+      generate_button_event (GDK_BUTTON_RELEASE, button,
+                            window, msg);
 
       return_val = TRUE;
       break;
 
     case WM_MOUSEMOVE:
       GDK_NOTE (EVENTS,
-               g_print (" %#x (%d,%d)",
-                        msg->wParam,
+               g_print (" %p (%d,%d)",
+                        (gpointer) msg->wParam,
                         GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
 
+      assign_object (&window, find_window_for_mouse_event (window, msg));
+      toplevel = gdk_window_get_toplevel (window);
+      if (current_toplevel != toplevel)
+       {
+         GDK_NOTE (EVENTS, g_print (" toplevel %p -> %p", 
+             current_toplevel ? GDK_WINDOW_HWND (current_toplevel) : NULL, 
+             toplevel ? GDK_WINDOW_HWND (toplevel) : NULL));
+         if (current_toplevel)
+           synthesize_enter_or_leave_event (current_toplevel, msg,
+                                       GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
+         synthesize_enter_or_leave_event (toplevel, msg,
+                                     GDK_ENTER_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
+         assign_object (&current_toplevel, toplevel);
+         track_mouse_event (TME_LEAVE, GDK_WINDOW_HWND (toplevel));
+       }
+
       /* 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.
@@ -2743,46 +2174,17 @@ gdk_event_translate (MSG  *msg,
       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)
-       {
-         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);
-       }
-      else
-       {
-         if (window != current_window)
-           synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
-       }
-
-      if (!propagate (&window, msg,
-                     p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_button_motion, TRUE))
-       break;
-
-      if (GDK_WINDOW_DESTROYED (window))
-       break;
-
-      if (window != orig_window)
-       translate_mouse_coords (orig_window, window, msg);
-
       event = gdk_event_new (GDK_MOTION_NOTIFY);
       event->motion.window = window;
       event->motion.time = _gdk_win32_get_next_tick (msg->time);
       event->motion.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
       event->motion.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
-      _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
-      event->motion.x += xoffset;
-      event->motion.y += yoffset;
       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 = _gdk_display->core_pointer;
+      gdk_event_set_device (event, _gdk_display->core_pointer);
 
       append_event (event);
 
@@ -2793,41 +2195,38 @@ gdk_event_translate (MSG  *msg,
       GDK_NOTE (EVENTS,
                g_print (" (%d,%d)",
                         GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam)));
-      if (current_window != NULL &&
-         (((GdkWindowObject *) current_window)->event_mask & GDK_LEAVE_NOTIFY_MASK))
+#if 0 /* TODO_CSW? */
+      if (current_toplevel != NULL &&
+         (current_toplevel->event_mask & GDK_LEAVE_NOTIFY_MASK))
        {
-         synthesize_crossing_events (_gdk_root, GDK_CROSSING_NORMAL, msg);
+         synthesize_enter_or_leave_event (current_toplevel, msg,
+                                          GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
        }
-
+#endif
       break;
 
     case WM_MOUSELEAVE:
       GDK_NOTE (EVENTS, g_print (" %d (%ld,%ld)",
                                 HIWORD (msg->wParam), msg->pt.x, msg->pt.y));
 
-      if (!gdk_win32_handle_table_lookup ((GdkNativeWindow) WindowFromPoint (msg->pt)))
+      if (!gdk_win32_handle_table_lookup (WindowFromPoint (msg->pt)))
        {
-         GdkNotifyType detail;
-
-         if (GDK_WINDOW_TYPE (current_window) != GDK_WINDOW_CHILD)
-           detail = GDK_NOTIFY_ANCESTOR;
-         else
-           detail = GDK_NOTIFY_UNKNOWN;
-
          /* we are only interested if we don't know the new window */
-         synthesize_enter_or_leave_event (current_window, msg, 
-                                          GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, detail,
-                                          current_x, current_y);
+         if (current_toplevel)
+           synthesize_enter_or_leave_event (current_toplevel, msg,
+                                       GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
+         assign_object (&current_toplevel, NULL);
        }
       else
        {
          GDK_NOTE (EVENTS, g_print (" (ignored)"));
        }
+      
       return_val = TRUE;
       break;
 
     case WM_MOUSEWHEEL:
-      GDK_NOTE (EVENTS, g_print (" %d", HIWORD (msg->wParam)));
+      GDK_NOTE (EVENTS, g_print (" %d", (short) HIWORD (msg->wParam)));
 
       /* WM_MOUSEWHEEL is delivered to the focus window. Work around
        * that. Also, the position is in screen coordinates, not client
@@ -2841,7 +2240,7 @@ gdk_event_translate (MSG  *msg,
        break;
 
       msg->hwnd = hwnd;
-      if ((new_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) msg->hwnd)) == NULL)
+      if ((new_window = gdk_win32_handle_table_lookup (msg->hwnd)) == NULL)
        break;
 
       if (new_window != window)
@@ -2849,14 +2248,6 @@ gdk_event_translate (MSG  *msg,
          assign_object (&window, new_window);
        }
 
-      if (!propagate (&window, msg,
-                     p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_scroll, TRUE))
-       break;
-
-      if (GDK_WINDOW_DESTROYED (window))
-       break;
-
       ScreenToClient (msg->hwnd, &point);
 
       event = gdk_event_new (GDK_SCROLL);
@@ -2864,76 +2255,101 @@ gdk_event_translate (MSG  *msg,
       event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
        GDK_SCROLL_UP : GDK_SCROLL_DOWN;
       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;
-      event->scroll.y = (gint16) point.y + yoffset;
+      event->scroll.x = (gint16) point.x;
+      event->scroll.y = (gint16) point.y;
       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 = _gdk_display->core_pointer;
+      gdk_event_set_device (event, _gdk_display->core_pointer);
 
       append_event (event);
       
       return_val = TRUE;
       break;
 
-    case WM_QUERYNEWPALETTE:
-      if (gdk_visual_get_system ()->type == GDK_VISUAL_PSEUDO_COLOR)
-       {
-         synthesize_expose_events (window);
-         update_colors_counter = 0;
-       }
-      return_val = TRUE;
+    case WM_HSCROLL:
+      /* Just print more debugging information, don't actually handle it. */
+      GDK_NOTE (EVENTS,
+               (g_print (" %s",
+                         (LOWORD (msg->wParam) == SB_ENDSCROLL ? "ENDSCROLL" :
+                          (LOWORD (msg->wParam) == SB_LEFT ? "LEFT" :
+                           (LOWORD (msg->wParam) == SB_RIGHT ? "RIGHT" :
+                            (LOWORD (msg->wParam) == SB_LINELEFT ? "LINELEFT" :
+                             (LOWORD (msg->wParam) == SB_LINERIGHT ? "LINERIGHT" :
+                              (LOWORD (msg->wParam) == SB_PAGELEFT ? "PAGELEFT" :
+                               (LOWORD (msg->wParam) == SB_PAGERIGHT ? "PAGERIGHT" :
+                                (LOWORD (msg->wParam) == SB_THUMBPOSITION ? "THUMBPOSITION" :
+                                 (LOWORD (msg->wParam) == SB_THUMBTRACK ? "THUMBTRACK" :
+                                  "???")))))))))),
+                (LOWORD (msg->wParam) == SB_THUMBPOSITION ||
+                 LOWORD (msg->wParam) == SB_THUMBTRACK) ?
+                (g_print (" %d", HIWORD (msg->wParam)), 0) : 0));
       break;
 
-    case WM_PALETTECHANGED:
-      GDK_NOTE (EVENTS_OR_COLORMAP, g_print (" %p", (HWND) msg->wParam));
-      if (gdk_visual_get_system ()->type != GDK_VISUAL_PSEUDO_COLOR)
-       break;
-
-      return_val = TRUE;
-
-      if (msg->hwnd == (HWND) msg->wParam)
-       break;
-
-      if (++update_colors_counter == 5)
-       {
-         synthesize_expose_events (window);
-         update_colors_counter = 0;
-         break;
-       }
-      
-      update_colors (window, TRUE);
+    case WM_VSCROLL:
+      /* Just print more debugging information, don't actually handle it. */
+      GDK_NOTE (EVENTS,
+               (g_print (" %s",
+                         (LOWORD (msg->wParam) == SB_ENDSCROLL ? "ENDSCROLL" :
+                          (LOWORD (msg->wParam) == SB_BOTTOM ? "BOTTOM" :
+                           (LOWORD (msg->wParam) == SB_TOP ? "TOP" :
+                            (LOWORD (msg->wParam) == SB_LINEDOWN ? "LINDOWN" :
+                             (LOWORD (msg->wParam) == SB_LINEUP ? "LINEUP" :
+                              (LOWORD (msg->wParam) == SB_PAGEDOWN ? "PAGEDOWN" :
+                               (LOWORD (msg->wParam) == SB_PAGEUP ? "PAGEUP" :
+                                (LOWORD (msg->wParam) == SB_THUMBPOSITION ? "THUMBPOSITION" :
+                                 (LOWORD (msg->wParam) == SB_THUMBTRACK ? "THUMBTRACK" :
+                                  "???")))))))))),
+                (LOWORD (msg->wParam) == SB_THUMBPOSITION ||
+                 LOWORD (msg->wParam) == SB_THUMBTRACK) ?
+                (g_print (" %d", HIWORD (msg->wParam)), 0) : 0));
       break;
 
      case WM_MOUSEACTIVATE:
-       if (gdk_window_get_window_type (window) == GDK_WINDOW_TEMP) 
-        {
-          *ret_valp = MA_NOACTIVATE;
-          return_val = TRUE;
-        }
+       {
+        GdkWindow *tmp;
+
+        if (gdk_window_get_window_type (window) == GDK_WINDOW_TEMP 
+            || !window->accept_focus)
+          {
+            *ret_valp = MA_NOACTIVATE;
+            return_val = TRUE;
+          }
+
+        tmp = _gdk_modal_current ();
+
+        if (tmp != NULL)
+          {
+            if (gdk_window_get_toplevel (window) != tmp)
+              {
+                *ret_valp = MA_NOACTIVATEANDEAT;
+                return_val = TRUE;
+              }
+          }
+       }
+
        break;
 
     case WM_KILLFOCUS:
-      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);
+      if (keyboard_grab != NULL &&
+         !GDK_WINDOW_DESTROYED (keyboard_grab->window))
+       {
+         generate_grab_broken_event (device_manager, keyboard_grab->window, TRUE, NULL);
+       }
 
       /* fallthrough */
     case WM_SETFOCUS:
-      if (k_grab_window != NULL && !k_grab_owner_events)
+      if (keyboard_grab != NULL &&
+         !keyboard_grab->owner_events)
        break;
 
-      if (!(((GdkWindowObject *) window)->event_mask & GDK_FOCUS_CHANGE_MASK))
+      if (!(window->event_mask & GDK_FOCUS_CHANGE_MASK))
        break;
 
       if (GDK_WINDOW_DESTROYED (window))
        break;
 
-      generate_focus_event (window, (msg->message == WM_SETFOCUS));
+      generate_focus_event (device_manager, window, (msg->message == WM_SETFOCUS));
       return_val = TRUE;
       break;
 
@@ -2943,11 +2359,16 @@ gdk_event_translate (MSG  *msg,
       if (GDK_WINDOW_DESTROYED (window))
        break;
 
-      erase_background (window, (HDC) msg->wParam);
       return_val = TRUE;
       *ret_valp = 1;
       break;
 
+    case WM_SYNCPAINT:
+      sync_timer = SetTimer (GDK_WINDOW_HWND (window),
+                            1,
+                            200, sync_timer_proc);
+      break;
+
     case WM_PAINT:
       handle_wm_paint (msg, window, FALSE, NULL);
       break;
@@ -2956,13 +2377,16 @@ gdk_event_translate (MSG  *msg,
       GDK_NOTE (EVENTS, g_print (" %#x %#x",
                                 LOWORD (msg->lParam), HIWORD (msg->lParam)));
 
-      if (p_grab_window == NULL && LOWORD (msg->lParam) != HTCLIENT)
+      if (pointer_grab != NULL)
+        grab_window = pointer_grab->window;
+
+      if (grab_window == NULL && LOWORD (msg->lParam) != HTCLIENT)
        break;
 
-      if (p_grab_window != NULL && p_grab_cursor != NULL)
+      if (grab_window != NULL && p_grab_cursor != NULL)
        hcursor = p_grab_cursor;
       else if (!GDK_WINDOW_DESTROYED (window))
-       hcursor = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->hcursor;
+       hcursor = GDK_WINDOW_IMPL_WIN32 (window->impl)->hcursor;
       else
        hcursor = NULL;
 
@@ -2976,9 +2400,16 @@ gdk_event_translate (MSG  *msg,
       break;
 
     case WM_SHOWWINDOW:
-      GDK_NOTE (EVENTS, g_print (" %d", msg->wParam));
-
-      if (!(((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK))
+      GDK_NOTE (EVENTS, g_print (" %s %s",
+                                (msg->wParam ? "YES" : "NO"),
+                                (msg->lParam == 0 ? "ShowWindow" :
+                                 (msg->lParam == SW_OTHERUNZOOM ? "OTHERUNZOOM" :
+                                  (msg->lParam == SW_OTHERZOOM ? "OTHERZOOM" :
+                                   (msg->lParam == SW_PARENTCLOSING ? "PARENTCLOSING" :
+                                    (msg->lParam == SW_PARENTOPENING ? "PARENTOPENING" :
+                                     "???")))))));
+
+      if (!(window->event_mask & GDK_STRUCTURE_MASK))
        break;
 
       if (msg->lParam == SW_OTHERUNZOOM ||
@@ -2992,18 +2423,41 @@ gdk_event_translate (MSG  *msg,
       event->any.window = window;
 
       append_event (event);
-      
-      if (event->any.type == GDK_UNMAP &&
-         p_grab_window == window)
-       gdk_pointer_ungrab (msg->time);
 
-      if (event->any.type == GDK_UNMAP &&
-         k_grab_window == window)
-       gdk_keyboard_ungrab (msg->time);
+      if (event->any.type == GDK_UNMAP)
+       {
+         impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+         if (impl->transient_owner && GetForegroundWindow () == GDK_WINDOW_HWND (window))
+           {
+             SetForegroundWindow (GDK_WINDOW_HWND (impl->transient_owner));
+           }
+
+         if (pointer_grab != NULL)
+           {
+             if (pointer_grab->window == window)
+               gdk_pointer_ungrab (msg->time);
+           }
+
+         if (keyboard_grab &&
+        keyboard_grab->window == window)
+           gdk_keyboard_ungrab (msg->time);
+       }
 
       return_val = TRUE;
       break;
 
+    case WM_SYSCOMMAND:
+      switch (msg->wParam)
+       {
+       case SC_MINIMIZE:
+       case SC_RESTORE:
+         do_show_window (window, msg->wParam == SC_MINIMIZE ? TRUE : FALSE);
+         break;
+       }
+
+      break;
+
     case WM_SIZE:
       GDK_NOTE (EVENTS,
                g_print (" %s %dx%d",
@@ -3017,16 +2471,19 @@ gdk_event_translate (MSG  *msg,
       if (msg->wParam == SIZE_MINIMIZED)
        {
          /* Don't generate any GDK event. This is *not* an UNMAP. */
-
-         if (p_grab_window == window)
-           gdk_pointer_ungrab (msg->time);
-
-         if (k_grab_window == window)
+         if (pointer_grab != NULL)
+           {
+             if (pointer_grab->window == window)
+               gdk_pointer_ungrab (msg->time);
+           }
+         if (keyboard_grab &&
+        keyboard_grab->window == window)
            gdk_keyboard_ungrab (msg->time);
 
          gdk_synthesize_window_state (window,
                                       GDK_WINDOW_STATE_WITHDRAWN,
                                       GDK_WINDOW_STATE_ICONIFIED);
+         do_show_window (window, TRUE);
        }
       else if ((msg->wParam == SIZE_RESTORED ||
                msg->wParam == SIZE_MAXIMIZED) &&
@@ -3035,101 +2492,107 @@ gdk_event_translate (MSG  *msg,
          GdkWindowState withdrawn_bit =
            IsWindowVisible (msg->hwnd) ? GDK_WINDOW_STATE_WITHDRAWN : 0;
 
+         if (window->state & GDK_WINDOW_STATE_ICONIFIED)
+           ensure_stacking_on_unminimize (msg);
+
          if (!GDK_WINDOW_DESTROYED (window))
            handle_configure_event (msg, window);
          
          if (msg->wParam == SIZE_RESTORED)
-           gdk_synthesize_window_state (window,
-                                        GDK_WINDOW_STATE_ICONIFIED |
-                                        GDK_WINDOW_STATE_MAXIMIZED |
-                                        withdrawn_bit,
-                                        0);
+           {
+             gdk_synthesize_window_state (window,
+                                          GDK_WINDOW_STATE_ICONIFIED |
+                                          GDK_WINDOW_STATE_MAXIMIZED |
+                                          withdrawn_bit,
+                                          0);
+
+             if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_TEMP && !GDK_WINDOW_IS_MAPPED (window))
+               {
+                 do_show_window (window, FALSE);
+               }
+           }
          else if (msg->wParam == SIZE_MAXIMIZED)
-           gdk_synthesize_window_state (window,
-                                        GDK_WINDOW_STATE_ICONIFIED |
-                                        withdrawn_bit,
-                                        GDK_WINDOW_STATE_MAXIMIZED);
+           {
+             gdk_synthesize_window_state (window,
+                                          GDK_WINDOW_STATE_ICONIFIED |
+                                          withdrawn_bit,
+                                          GDK_WINDOW_STATE_MAXIMIZED);
+           }
 
-         if (((GdkWindowObject *) window)->resize_count > 1)
-           ((GdkWindowObject *) window)->resize_count -= 1;
+         if (window->resize_count > 1)
+           window->resize_count -= 1;
          
-         if (((GdkWindowObject *) window)->extension_events != 0)
-           _gdk_input_configure_event (window);
+         if (window->extension_events != 0)
+      _gdk_device_wintab_update_window_coords (window);
 
          return_val = TRUE;
        }
       break;
 
     case WM_ENTERSIZEMOVE:
-      _sizemove_in_progress = TRUE;
-      resize_timer = SetTimer (NULL, 0, 20, resize_timer_proc);
+    case WM_ENTERMENULOOP:
+      _gdk_win32_begin_modal_call ();
       break;
 
     case WM_EXITSIZEMOVE:
-      _sizemove_in_progress = FALSE;
-      KillTimer (NULL, resize_timer);
+    case WM_EXITMENULOOP:
+      _gdk_win32_end_modal_call ();
+      break;
+
+    case WM_WINDOWPOSCHANGING:
+      GDK_NOTE (EVENTS, (windowpos = (WINDOWPOS *) msg->lParam,
+                        g_print (" %s %s %dx%d@%+d%+d now below %p",
+                                 _gdk_win32_window_pos_bits_to_string (windowpos->flags),
+                                 (windowpos->hwndInsertAfter == HWND_BOTTOM ? "BOTTOM" :
+                                  (windowpos->hwndInsertAfter == HWND_NOTOPMOST ? "NOTOPMOST" :
+                                   (windowpos->hwndInsertAfter == HWND_TOP ? "TOP" :
+                                    (windowpos->hwndInsertAfter == HWND_TOPMOST ? "TOPMOST" :
+                                     (sprintf (buf, "%p", windowpos->hwndInsertAfter),
+                                      buf))))),
+                                 windowpos->cx, windowpos->cy, windowpos->x, windowpos->y,
+                                 GetNextWindow (msg->hwnd, GW_HWNDPREV))));
+
+      if (GDK_WINDOW_IS_MAPPED (window))
+       return_val = ensure_stacking_on_window_pos_changing (msg, window);
       break;
 
-    case WM_WINDOWPOSCHANGED :
+    case WM_WINDOWPOSCHANGED:
+      windowpos = (WINDOWPOS *) msg->lParam;
+      GDK_NOTE (EVENTS, g_print (" %s %s %dx%d@%+d%+d",
+                                _gdk_win32_window_pos_bits_to_string (windowpos->flags),
+                                (windowpos->hwndInsertAfter == HWND_BOTTOM ? "BOTTOM" :
+                                 (windowpos->hwndInsertAfter == HWND_NOTOPMOST ? "NOTOPMOST" :
+                                  (windowpos->hwndInsertAfter == HWND_TOP ? "TOP" :
+                                   (windowpos->hwndInsertAfter == HWND_TOPMOST ? "TOPMOST" :
+                                    (sprintf (buf, "%p", windowpos->hwndInsertAfter),
+                                     buf))))),
+                                windowpos->cx, windowpos->cy, windowpos->x, windowpos->y));
+
+      /* If position and size haven't changed, don't do anything */
+      if (_modal_operation_in_progress &&
+         (windowpos->flags & SWP_NOMOVE) &&
+         (windowpos->flags & SWP_NOSIZE))
+       break;
+
       /* 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 (_sizemove_in_progress &&
+      if (_modal_operation_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)
+         if (window->event_mask & GDK_STRUCTURE_MASK)
            {
-             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 = point.x;
-         ((GdkWindowObject *) window)->y = point.y;
+             GDK_NOTE (EVENTS, g_print (" do magic"));
+             if (window->resize_count > 1)
+               window->resize_count -= 1;
 
-         if (((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK)
-           {
-             GdkEvent *event = gdk_event_new (GDK_CONFIGURE);
-             
-             event->configure.window = window;
-             
-             event->configure.width = client_rect.right - client_rect.left;
-             event->configure.height = client_rect.bottom - client_rect.top;
-             
-             event->configure.x = point.x;
-             event->configure.y = point.y;
-             
-             if (((GdkWindowObject *) window)->resize_count > 1)
-               ((GdkWindowObject *) window)->resize_count -= 1;
-             
-#if 0 /* I don't like calling _gdk_event_func() from here, isn't there
-       * a risk of getting events processed in the wrong order, like
-       * Owen says in the discussion of bug #99540?
-       */
-             fixup_event (event);
-             if (_gdk_event_func)
-               (*_gdk_event_func) (event, _gdk_event_data);
-             gdk_event_free (event);
-#else /* Calling append_event() is slower, but guarantees that events won't
-       * get reordered, I think.
-       */
-             append_event (event);
-#endif
-             
+             handle_configure_event (msg, window);
+             g_main_context_iteration (NULL, FALSE);
+#if 0
              /* Dispatch main loop - to realize resizes... */
-             handle_stuff_while_moving_or_resizing ();
-             
+             modal_timer_proc (msg->hwnd, msg->message, 0, msg->time);
+#endif
              /* Claim as handled, so that WM_SIZE and WM_MOVE are avoided */
              return_val = TRUE;
              *ret_valp = 1;
@@ -3139,6 +2602,7 @@ gdk_event_translate (MSG  *msg,
 
     case WM_SIZING:
       GetWindowRect (GDK_WINDOW_HWND (window), &rect);
+      drag = (RECT *) msg->lParam;
       GDK_NOTE (EVENTS, g_print (" %s curr:%s drag:%s",
                                 (msg->wParam == WMSZ_BOTTOM ? "BOTTOM" :
                                  (msg->wParam == WMSZ_BOTTOMLEFT ? "BOTTOMLEFT" :
@@ -3151,13 +2615,13 @@ gdk_event_translate (MSG  *msg,
                                        (msg->wParam == WMSZ_BOTTOMRIGHT ? "BOTTOMRIGHT" :
                                         "???")))))))),
                                 _gdk_win32_rect_to_string (&rect),
-                                _gdk_win32_rect_to_string ((RECT *) msg->lParam)));
+                                _gdk_win32_rect_to_string (drag)));
 
-      impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl);
-      drag = (RECT *) msg->lParam;
+      impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
       orig_drag = *drag;
       if (impl->hint_flags & GDK_HINT_RESIZE_INC)
        {
+         GDK_NOTE (EVENTS, g_print (" (RESIZE_INC)"));
          if (impl->hint_flags & GDK_HINT_BASE_SIZE)
            {
              /* Resize in increments relative to the base size */
@@ -3186,7 +2650,6 @@ gdk_event_translate (MSG  *msg,
              if (drag->bottom == rect.bottom)
                break;
              adjust_drag (&drag->bottom, rect.bottom, impl->hints.height_inc);
-
              break;
 
            case WMSZ_BOTTOMLEFT:
@@ -3241,7 +2704,7 @@ gdk_event_translate (MSG  *msg,
            {
              *ret_valp = TRUE;
              return_val = TRUE;
-             GDK_NOTE (EVENTS, g_print (" (handled RESIZE_INC: drag:%s)",
+             GDK_NOTE (EVENTS, g_print (" (handled RESIZE_INC: %s)",
                                         _gdk_win32_rect_to_string (drag)));
            }
        }
@@ -3250,18 +2713,106 @@ gdk_event_translate (MSG  *msg,
 
       if (impl->hint_flags & GDK_HINT_ASPECT)
        {
-         gdouble drag_aspect = (gdouble) (drag->right - drag->left) / (drag->bottom - drag->top);
-         
-         GDK_NOTE (EVENTS, g_print (" (aspect:%g)", drag_aspect));
-         if (drag_aspect < impl->hints.min_aspect ||
-             drag_aspect > impl->hints.max_aspect)
+         RECT decorated_rect;
+         RECT undecorated_drag;
+         int decoration_width, decoration_height;
+         gdouble drag_aspect;
+         int drag_width, drag_height, new_width, new_height;
+
+         GetClientRect (GDK_WINDOW_HWND (window), &rect);
+         decorated_rect = rect;
+         _gdk_win32_adjust_client_rect (window, &decorated_rect);
+
+         /* Set undecorated_drag to the client area being dragged
+          * out, in screen coordinates.
+          */
+         undecorated_drag = *drag;
+         undecorated_drag.left -= decorated_rect.left - rect.left;
+         undecorated_drag.right -= decorated_rect.right - rect.right;
+         undecorated_drag.top -= decorated_rect.top - rect.top;
+         undecorated_drag.bottom -= decorated_rect.bottom - rect.bottom;
+
+         decoration_width = (decorated_rect.right - decorated_rect.left) - (rect.right - rect.left);
+         decoration_height = (decorated_rect.bottom - decorated_rect.top) - (rect.bottom - rect.top);
+
+         drag_width = undecorated_drag.right - undecorated_drag.left;
+         drag_height = undecorated_drag.bottom - undecorated_drag.top;
+
+         drag_aspect = (gdouble) drag_width / drag_height;
+
+         GDK_NOTE (EVENTS, g_print (" (ASPECT:%g--%g curr: %g)",
+                                    impl->hints.min_aspect, impl->hints.max_aspect, drag_aspect));
+
+         if (drag_aspect < impl->hints.min_aspect)
            {
-             *drag = rect;
-             *ret_valp = TRUE;
-             return_val = TRUE;
-             GDK_NOTE (EVENTS, g_print (" (handled ASPECT: drag:%s)",
-                                        _gdk_win32_rect_to_string (drag)));
+             /* Aspect is getting too narrow */
+             switch (msg->wParam)
+               {
+               case WMSZ_BOTTOM:
+               case WMSZ_TOP:
+                 /* User drags top or bottom edge outward. Keep height, increase width. */
+                 new_width = impl->hints.min_aspect * drag_height;
+                 drag->left -= (new_width - drag_width) / 2;
+                 drag->right = drag->left + new_width + decoration_width;
+                 break;
+               case WMSZ_BOTTOMLEFT:
+               case WMSZ_BOTTOMRIGHT:
+                 /* User drags bottom-left or bottom-right corner down. Adjust height. */
+                 new_height = drag_width / impl->hints.min_aspect;
+                 drag->bottom = drag->top + new_height + decoration_height;
+                 break;
+               case WMSZ_LEFT:
+               case WMSZ_RIGHT:
+                 /* User drags left or right edge inward. Decrease height */
+                 new_height = drag_width / impl->hints.min_aspect;
+                 drag->top += (drag_height - new_height) / 2;
+                 drag->bottom = drag->top + new_height + decoration_height;
+                 break;
+               case WMSZ_TOPLEFT:
+               case WMSZ_TOPRIGHT:
+                 /* User drags top-left or top-right corner up. Adjust height. */
+                 new_height = drag_width / impl->hints.min_aspect;
+                 drag->top = drag->bottom - new_height - decoration_height;
+               }
            }
+         else if (drag_aspect > impl->hints.max_aspect)
+           {
+             /* Aspect is getting too wide */
+             switch (msg->wParam)
+               {
+               case WMSZ_BOTTOM:
+               case WMSZ_TOP:
+                 /* User drags top or bottom edge inward. Decrease width. */
+                 new_width = impl->hints.max_aspect * drag_height;
+                 drag->left += (drag_width - new_width) / 2;
+                 drag->right = drag->left + new_width + decoration_width;
+                 break;
+               case WMSZ_BOTTOMLEFT:
+               case WMSZ_TOPLEFT:
+                 /* User drags bottom-left or top-left corner left. Adjust width. */
+                 new_width = impl->hints.max_aspect * drag_height;
+                 drag->left = drag->right - new_width - decoration_width;
+                 break;
+               case WMSZ_BOTTOMRIGHT:
+               case WMSZ_TOPRIGHT:
+                 /* User drags bottom-right or top-right corner right. Adjust width. */
+                 new_width = impl->hints.max_aspect * drag_height;
+                 drag->right = drag->left + new_width + decoration_width;
+                 break;
+               case WMSZ_LEFT:
+               case WMSZ_RIGHT:
+                 /* User drags left or right edge outward. Increase height. */
+                 new_height = drag_width / impl->hints.max_aspect;
+                 drag->top -= (new_height - drag_height) / 2;
+                 drag->bottom = drag->top + new_height + decoration_height;
+                 break;
+               }
+           }
+
+         *ret_valp = TRUE;
+         return_val = TRUE;
+         GDK_NOTE (EVENTS, g_print (" (handled ASPECT: %s)",
+                                    _gdk_win32_rect_to_string (drag)));
        }
       break;
 
@@ -3269,7 +2820,7 @@ gdk_event_translate (MSG  *msg,
       if (GDK_WINDOW_DESTROYED (window))
        break;
 
-      impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl);
+      impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
       mmi = (MINMAXINFO*) msg->lParam;
       GDK_NOTE (EVENTS, g_print (" (mintrack:%ldx%ld maxtrack:%ldx%ld "
                                 "maxpos:%+ld%+ld maxsize:%ldx%ld)",
@@ -3309,7 +2860,7 @@ gdk_event_translate (MSG  *msg,
 
       if (impl->hint_flags & (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE))
        {
-         /* Don't call DefWindowProc() */
+         /* Don't call DefWindowProcW() */
          GDK_NOTE (EVENTS, g_print (" (handled, mintrack:%ldx%ld maxtrack:%ldx%ld "
                                     "maxpos:%+ld%+ld maxsize:%ldx%ld)",
                                     mmi->ptMinTrackSize.x, mmi->ptMinTrackSize.y,
@@ -3343,17 +2894,25 @@ gdk_event_translate (MSG  *msg,
 
       append_event (event);
 
+      impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
+
+      if (impl->transient_owner && GetForegroundWindow() == GDK_WINDOW_HWND (window))
+       {
+         SetForegroundWindow (GDK_WINDOW_HWND (impl->transient_owner));
+       }
+
       return_val = TRUE;
       break;
 
     case WM_DESTROY:
-      if (window == current_window)
-       assign_object (&current_window, _gdk_root);
-
-      if (p_grab_window == window)
-       gdk_pointer_ungrab (msg->time);
+      if (pointer_grab != NULL)
+       {
+         if (pointer_grab->window == window)
+           gdk_pointer_ungrab (msg->time);
+       }
 
-      if (k_grab_window == window)
+      if (keyboard_grab &&
+          keyboard_grab->window == window)
        gdk_keyboard_ungrab (msg->time);
 
       if ((window != NULL) && (msg->hwnd != GetDesktopWindow ()))
@@ -3384,7 +2943,10 @@ gdk_event_translate (MSG  *msg,
           append_event (event);
        }
       else
-       return_val = TRUE;
+       {
+         return_val = TRUE;
+       }
+
       break;
 
     case WM_RENDERFORMAT:
@@ -3400,50 +2962,73 @@ gdk_event_translate (MSG  *msg,
       /* 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);
+      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;
+      event->selection.requestor = gdk_win32_handle_table_lookup (msg->hwnd);
+      event->selection.time = msg->time;
 
-         /* 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;
-           }
-       }
+      fixup_event (event);
+      GDK_NOTE (EVENTS, g_print (" (calling _gdk_event_emit)"));
+      GDK_NOTE (EVENTS, _gdk_win32_print_event (event));
+      _gdk_event_emit (event);
+      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
+           */
+          GDK_NOTE (DND,
+                    g_print (" SetClipboardData(%s,%p)",
+                             _gdk_win32_cf_to_string (msg->wParam),
+                             _delayed_rendering_data));
+
+          API_CALL (SetClipboardData, (msg->wParam, _delayed_rendering_data));
+          _delayed_rendering_data = NULL;
+        }
       break;
 
-#ifdef HAVE_WINTAB
     case WM_ACTIVATE:
+      GDK_NOTE (EVENTS, g_print (" %s%s %p",
+                                (LOWORD (msg->wParam) == WA_ACTIVE ? "ACTIVE" :
+                                 (LOWORD (msg->wParam) == WA_CLICKACTIVE ? "CLICKACTIVE" :
+                                  (LOWORD (msg->wParam) == WA_INACTIVE ? "INACTIVE" : "???"))),
+                                HIWORD (msg->wParam) ? " minimized" : "",
+                                (HWND) msg->lParam));
+      /* We handle mouse clicks for modally-blocked windows under WM_MOUSEACTIVATE,
+       * but we still need to deal with alt-tab, or with SetActiveWindow() type
+       * situations.
+       */
+      if (is_modally_blocked (window) && LOWORD (msg->wParam) == WA_ACTIVE)
+       {
+         GdkWindow *modal_current = _gdk_modal_current ();
+         SetActiveWindow (GDK_WINDOW_HWND (modal_current));
+         *ret_valp = 0;
+         return_val = TRUE;
+         break;
+       }
+
       /* 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
@@ -3452,24 +3037,32 @@ gdk_event_translate (MSG  *msg,
       if (LOWORD(msg->wParam) != WA_INACTIVE)
        _gdk_input_set_tablet_active ();
       break;
-      
+
+    case WM_ACTIVATEAPP:
+      GDK_NOTE (EVENTS, g_print (" %s thread: %I64d",
+                                msg->wParam ? "YES" : "NO",
+                                (gint64) msg->lParam));
+      if (msg->wParam && GDK_WINDOW_IS_MAPPED (window))
+       ensure_stacking_on_activate_app (msg, window);
+      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.
        */
     case WT_PACKET:
-      GDK_NOTE (EVENTS, g_print (" %d %#lx",
-                                msg->wParam, msg->lParam));
+      GDK_NOTE (EVENTS, g_print (" %d %p",
+                                (int) msg->wParam, (gpointer) msg->lParam));
       goto wintab;
       
     case WT_CSRCHANGE:
-      GDK_NOTE (EVENTS, g_print (" %d %#lx",
-                                msg->wParam, msg->lParam));
+      GDK_NOTE (EVENTS, g_print (" %d %p",
+                                (int) msg->wParam, (gpointer) msg->lParam));
       goto wintab;
       
     case WT_PROXIMITY:
-      GDK_NOTE (EVENTS, g_print (" %#x %d %d",
-                                msg->wParam,
+      GDK_NOTE (EVENTS, g_print (" %p %d %d",
+                                (gpointer) msg->wParam,
                                 LOWORD (msg->lParam),
                                 HIWORD (msg->lParam)));
       /* Fall through */
@@ -3478,12 +3071,13 @@ gdk_event_translate (MSG  *msg,
       event = gdk_event_new (GDK_NOTHING);
       event->any.window = window;
       g_object_ref (window);
+
       if (_gdk_input_other_event (event, msg, window))
        append_event (event);
       else
        gdk_event_free (event);
+
       break;
-#endif
     }
 
 done:
@@ -3496,15 +3090,18 @@ done:
 }
 
 void
-_gdk_events_queue (GdkDisplay *display)
+_gdk_win32_display_queue_events (GdkDisplay *display)
 {
   MSG msg;
 
+  if (modal_win32_dialog != NULL)
+    return;
+  
   while (!_gdk_event_queue_find_first (display) &&
-        PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
+        PeekMessageW (&msg, NULL, 0, 0, PM_REMOVE))
     {
       TranslateMessage (&msg);
-      DispatchMessage (&msg);
+      DispatchMessageW (&msg);
     }
 }
 
@@ -3520,7 +3117,8 @@ gdk_event_prepare (GSource *source,
   *timeout = -1;
 
   retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
-           PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE));
+           (modal_win32_dialog == NULL &&
+            PeekMessageW (&msg, NULL, 0, 0, PM_NOREMOVE)));
 
   GDK_THREADS_LEAVE ();
 
@@ -3536,10 +3134,15 @@ gdk_event_check (GSource *source)
   GDK_THREADS_ENTER ();
 
   if (event_poll_fd.revents & G_IO_IN)
-    retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
-             PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE));
+    {
+      retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
+               (modal_win32_dialog == NULL &&
+                PeekMessageW (&msg, NULL, 0, 0, PM_NOREMOVE)));
+    }
   else
-    retval = FALSE;
+    {
+      retval = FALSE;
+    }
 
   GDK_THREADS_LEAVE ();
 
@@ -3555,15 +3158,22 @@ gdk_event_dispatch (GSource     *source,
  
   GDK_THREADS_ENTER ();
 
-  _gdk_events_queue (_gdk_display);
+  _gdk_win32_display_queue_events (_gdk_display);
   event = _gdk_event_unqueue (_gdk_display);
 
   if (event)
     {
-      if (_gdk_event_func)
-       (*_gdk_event_func) (event, _gdk_event_data);
+      _gdk_event_emit (event);
       
       gdk_event_free (event);
+
+      /* Do drag & drop if it is still pending */
+      if (_dnd_source_state == GDK_WIN32_DND_PENDING) 
+       {
+         _dnd_source_state = GDK_WIN32_DND_DRAGGING;
+         _gdk_win32_dnd_do_dragdrop ();
+         _dnd_source_state = GDK_WIN32_DND_NONE;
+       }
     }
   
   GDK_THREADS_LEAVE ();
@@ -3571,78 +3181,28 @@ gdk_event_dispatch (GSource     *source,
   return TRUE;
 }
 
-static void
-check_for_too_much_data (GdkEvent *event)
-{
-  if (event->client.data.l[1] ||
-      event->client.data.l[2] ||
-      event->client.data.l[3] ||
-      event->client.data.l[4])
-    g_warning ("Only four bytes of data are passed in client messages on Win32\n");
-}
-
-gboolean
-gdk_event_send_client_message_for_display (GdkDisplay     *display,
-                                           GdkEvent       *event, 
-                                           GdkNativeWindow winid)
-{
-  check_for_too_much_data (event);
-
-  return PostMessage ((HWND) winid, client_message,
-                     (WPARAM) event->client.message_type,
-                     event->client.data.l[0]);
-}
-
 void
-gdk_screen_broadcast_client_message (GdkScreen *screen, 
-                                    GdkEvent  *event)
+gdk_win32_set_modal_dialog_libgtk_only (HWND window)
 {
-  check_for_too_much_data (event);
-
-  PostMessage (HWND_BROADCAST, client_message,
-              (WPARAM) event->client.message_type,
-              event->client.data.l[0]);
+  modal_win32_dialog = window;
 }
 
-void
-gdk_flush (void)
+static gboolean
+is_modally_blocked (GdkWindow *window)
 {
-#if 0
-  MSG msg;
-
-  /* Process all messages currently available */
-  while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
-    {
-      TranslateMessage (&msg);
-      DispatchMessage (&msg);
-    }
-#endif
-
-  GdiFlush ();
+  GdkWindow *modal_current = _gdk_modal_current ();
+  return modal_current != NULL ? gdk_window_get_toplevel (window) != modal_current : FALSE;
 }
 
 void
-gdk_display_sync (GdkDisplay * display)
+_gdk_win32_display_sync (GdkDisplay * display)
 {
   MSG msg;
 
   g_return_if_fail (display == _gdk_display);
 
   /* Process all messages currently available */
-  while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
-    DispatchMessage (&msg);
-}
-
-void
-gdk_display_flush (GdkDisplay * display)
-{
-  g_return_if_fail (display == _gdk_display);
-
-  /* Nothing */
+  while (PeekMessageW (&msg, NULL, 0, 0, PM_REMOVE))
+    DispatchMessageW (&msg);
 }
 
-gboolean
-gdk_net_wm_supports (GdkAtom property)
-{
-  return FALSE;
-}