diff -ur gtk+-8bfbb2c/gdk/gdkinternals.h gtk+-8bfbb2c/gdk/gdkinternals.h
--- gtk+-8bfbb2c/gdk/gdkinternals.h	2015-12-27 02:42:10.000000000 +0000
+++ gtk+-8bfbb2c/gdk/gdkinternals.h	2015-12-28 14:05:47.078083700 +0000
@@ -372,6 +372,12 @@
 
   GdkFrameClock *frame_clock; /* NULL to use from parent or default */
   GdkWindowInvalidateHandlerFunc invalidate_handler;
+
+  cairo_surface_t *shadow_surface;
+  gint shadow_width;
+  gint shadow_height;
+  gint shadow_window_x_offset;
+  gint shadow_window_y_offset;
 };
 
 #define GDK_WINDOW_TYPE(d) ((((GdkWindow *)(d)))->window_type)
diff -ur gtk+-8bfbb2c/gdk/gdkwindow.c gtk+-8bfbb2c/gdk/gdkwindow.c
--- gtk+-8bfbb2c/gdk/gdkwindow.c	2015-12-27 02:42:10.000000000 +0000
+++ gtk+-8bfbb2c/gdk/gdkwindow.c	2015-12-28 14:43:55.501676600 +0000
@@ -2044,6 +2044,13 @@
               window->background = NULL;
             }
 
+
+          if (window->shadow_surface)
+            {
+              cairo_surface_destroy (window->shadow_surface);
+              window->shadow_surface = NULL;
+            }
+
 	  if (window->window_type == GDK_WINDOW_FOREIGN)
 	    g_assert (window->children == NULL);
 	  else
@@ -11548,3 +11555,49 @@
   else
     return FALSE;
 }
+
+void
+gdk_window_set_shadow_surface (GdkWindow       *window,
+                               cairo_surface_t *surface,
+                               gint             width,
+                               gint             height,
+                               gint             window_x_offset,
+                               gint             window_y_offset)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (!GDK_WINDOW_DESTROYED (window));
+
+  if (window->shadow_surface)
+    cairo_surface_destroy (window->shadow_surface);
+
+  if (surface)
+    window->shadow_surface = cairo_surface_reference (surface);
+  else
+    window->shadow_surface = NULL;
+
+  window->shadow_width = width;
+  window->shadow_height = height;
+  window->shadow_window_x_offset = window_x_offset;
+  window->shadow_window_y_offset = window_y_offset;
+}
+
+cairo_surface_t *
+gdk_window_get_shadow_surface (GdkWindow       *window,
+                               gint            *width,
+                               gint            *height,
+                               gint            *window_x_offset,
+                               gint            *window_y_offset)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+  g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), NULL);
+
+  if (window->shadow_surface == NULL)
+    return NULL;
+
+  *width = window->shadow_width;
+  *height = window->shadow_height;
+  *window_x_offset = window->shadow_window_x_offset;
+  *window_y_offset = window->shadow_window_y_offset;
+
+  return window->shadow_surface;
+}
diff -ur gtk+-8bfbb2c/gdk/gdkwindow.h gtk+-8bfbb2c/gdk/gdkwindow.h
--- gtk+-8bfbb2c/gdk/gdkwindow.h	2015-12-27 02:42:10.000000000 +0000
+++ gtk+-8bfbb2c/gdk/gdkwindow.h	2015-12-28 15:42:58.871627500 +0000
@@ -1075,6 +1075,21 @@
 GdkGLContext * gdk_window_create_gl_context    (GdkWindow      *window,
                                                 GError        **error);
 
+GDK_AVAILABLE_IN_3_20
+void       gdk_window_set_shadow_surface       (GdkWindow       *window,
+                                                cairo_surface_t *surface,
+                                                gint             width,
+                                                gint             height,
+                                                gint             window_x_offset,
+                                                gint             window_y_offset);
+
+GDK_AVAILABLE_IN_3_20
+cairo_surface_t *gdk_window_get_shadow_surface (GdkWindow       *window,
+                                                gint            *width,
+                                                gint            *height,
+                                                gint            *window_x_offset,
+                                                gint            *window_y_offset);
+
 G_END_DECLS
 
 #endif /* __GDK_WINDOW_H__ */
diff -ur gtk+-8bfbb2c/gdk/win32/gdkevents-win32.c gtk+-8bfbb2c/gdk/win32/gdkevents-win32.c
--- gtk+-8bfbb2c/gdk/win32/gdkevents-win32.c	2015-12-28 18:46:57.042297100 +0000
+++ gtk+-8bfbb2c/gdk/win32/gdkevents-win32.c	2015-12-28 18:30:59.956762700 +0000
@@ -55,6 +55,7 @@
 #include "gdkwin32dnd.h"
 #include "gdkdndprivate.h"
 
+#include <cairo-win32.h>
 #include <windowsx.h>
 
 #ifdef G_WITH_CYGWIN
@@ -1546,6 +1547,98 @@
   return result;
 }
 
+/*
+void
+SetLayeredWindow (HWND hwnd, HWND above, LONG x, LONG y, LONG width, LONG height, cairo_surface_t *content, UINT flags)
+{
+  POINT src_point = {0, 0};
+  POINT dst_point = {x, y};
+  SIZE dst_size = {width, height};
+  BLENDFUNCTION alpha_blender = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
+  static gint pngcounter = 0;
+  gchar *pngname;
+
+  if (hwnd == NULL)
+    return;
+
+  if (content)
+  {
+    pngname = g_strdup_printf ("F:\\e43\\src\\mingw\\gtk+-3.0-git-8bfbb2c-1\\shadow%d.png", pngcounter++);
+    cairo_surface_write_to_png (content, pngname);
+    g_free (pngname);
+    if (g_getenv ("GET_RES_FROM_IMAGE") != NULL)
+    {
+      dst_size.cx = GetDeviceCaps (cairo_win32_surface_get_dc (content), HORZRES);
+      dst_size.cy = GetDeviceCaps (cairo_win32_surface_get_dc (content), VERTRES);
+    }
+  }
+
+  API_CALL (UpdateLayeredWindow, (hwnd,
+                                  NULL,
+                                  SWP_NOMOVE & flags ? NULL : &dst_point,
+                                  SWP_NOSIZE & flags ? NULL : &dst_size,
+                                  SWP_NOREDRAW & flags ? NULL : content == NULL ? NULL : cairo_win32_surface_get_dc (content),
+                                  SWP_NOREDRAW & flags ? NULL : content == NULL ? NULL : &src_point,
+                                  0, &alpha_blender, ULW_ALPHA));
+
+  API_CALL (SetWindowPos, (hwnd, above, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE));
+}
+*/
+void
+SetLayeredWindow (HDWP movegroup, GdkWindow *shadowed, LONG x, LONG y, LONG width, LONG height, UINT flags)
+{
+  POINT src_point = {0, 0};
+  POINT dst_point = {x, y};
+  SIZE dst_size = {width, height};
+  BLENDFUNCTION alpha_blender = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
+  static gint pngcounter = 0;
+  gchar *pngname;
+
+  if (shadowed == NULL)
+    return;
+
+  if (shadowed->shadow_surface)
+    {
+
+      //pngname = g_strdup_printf ("F:\\e43\\src\\mingw\\gtk+-3.0-git-8bfbb2c-1\\shadow%04d.png", pngcounter++);
+      //cairo_surface_write_to_png (shadowed->shadow_surface, pngname);
+      //g_free (pngname);
+
+      dst_point.x -= shadowed->shadow_window_x_offset;
+      dst_point.y -= shadowed->shadow_window_y_offset;
+      if (width > 0 && height > 0)
+      {
+        dst_size.cx += shadowed->shadow_window_x_offset;
+        dst_size.cy += shadowed->shadow_window_y_offset;
+      }
+      else
+      {
+        dst_size.cx = shadowed->shadow_width;
+        dst_size.cy = shadowed->shadow_height;
+      }
+    }
+
+  if (GDK_WINDOW_SHWND (shadowed))
+    {
+      if (movegroup != 0)
+      {
+        API_CALL (DeferWindowPos, (movegroup, GDK_WINDOW_SHWND (shadowed), GDK_WINDOW_HWND (shadowed), dst_point.x, dst_point.y, dst_size.cx, dst_size.cy, SWP_NOACTIVATE | SWP_NOSIZE | (flags & ~SWP_NOREDRAW)));
+        API_CALL (EndDeferWindowPos, (movegroup));
+      }
+      else
+        API_CALL (SetWindowPos, (GDK_WINDOW_SHWND (shadowed), GDK_WINDOW_HWND (shadowed), dst_point.x, dst_point.y, dst_size.cx, dst_size.cy, SWP_NOSIZE | SWP_NOACTIVATE | (flags & ~SWP_NOREDRAW)));
+
+      API_CALL (UpdateLayeredWindow, (GDK_WINDOW_SHWND (shadowed),
+                                  NULL,
+                                  NULL,//SWP_NOMOVE & flags ? NULL : &dst_point,
+                                  SWP_NOSIZE & flags ? NULL : &dst_size,
+                                  SWP_NOREDRAW & flags ? NULL : shadowed->shadow_surface == NULL ? NULL : cairo_win32_surface_get_dc (shadowed->shadow_surface),
+                                  SWP_NOREDRAW & flags ? NULL : shadowed->shadow_surface == NULL ? NULL : &src_point,
+                                  0, &alpha_blender, ULW_ALPHA));
+    }
+}
+
+
 static void
 adjust_drag (LONG *drag,
 	     LONG  curr,
@@ -1790,8 +1883,9 @@
       GDK_NOTE (EVENTS,
 		g_print (" restacking %p above %p",
 			 msg->hwnd, lowest_transient));
-      SetWindowPos (msg->hwnd, lowest_transient, 0, 0, 0, 0,
-		    SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+      API_CALL (SetWindowPos, (msg->hwnd, lowest_transient, 0, 0, 0, 0,
+		    SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
+      SetLayeredWindow (0, msg_window, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW);
     }
 }
 
@@ -1871,8 +1965,9 @@
       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);
+      API_CALL (SetWindowPos, (msg->hwnd, HWND_TOP, 0, 0, 0, 0,
+		    SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
+      SetLayeredWindow (0, window, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW);
       return;
     }
 
@@ -2032,7 +2127,11 @@
       else if (msg->message == WM_CREATE)
 	{
 	  window = (UNALIGNED GdkWindow*) (((LPCREATESTRUCTW) msg->lParam)->lpCreateParams);
-	  GDK_WINDOW_HWND (window) = msg->hwnd;
+          /* FIXME: this is kind of hacky, maybe set a gboolean to indicate which window is being created? */
+          if (GDK_WINDOW_HWND (window) == NULL)
+	    GDK_WINDOW_HWND (window) = msg->hwnd;
+	  else
+	    GDK_WINDOW_SHWND (window) = msg->hwnd;
 	}
       else
 	{
@@ -2940,6 +3039,8 @@
       if (_modal_operation_in_progress)
 	modal_timer_proc (0,0,0,0);
 
+      SetLayeredWindow (0, window, windowpos->x, windowpos->y, windowpos->cx, windowpos->cy, SWP_NOREDRAW);
+
       /* Claim as handled, so that WM_SIZE and WM_MOVE are avoided */
       return_val = TRUE;
       *ret_valp = 0;
@@ -3159,6 +3260,9 @@
 	  GDK_NOTE (EVENTS, g_print (" (handled ASPECT: %s)",
 				     _gdk_win32_rect_to_string (drag)));
 	}
+
+        SetLayeredWindow (0, window, drag->left, drag->top, drag->right - drag->left, drag->bottom - drag->top, 0);
+
       break;
 
     case WM_GETMINMAXINFO:
diff -ur gtk+-8bfbb2c/gdk/win32/gdkevents-win32.c.orig gtk+-8bfbb2c/gdk/win32/gdkevents-win32.c.orig
--- gtk+-8bfbb2c/gdk/win32/gdkevents-win32.c.orig	2015-12-28 18:46:56.960286700 +0000
+++ gtk+-8bfbb2c/gdk/win32/gdkevents-win32.c.orig	2015-12-27 14:38:45.137358700 +0000
@@ -721,7 +721,7 @@
     default: g_assert_not_reached ();
     }
 
-  g_print (" %p ", event->any.window ? GDK_WINDOW_HWND (event->any.window) : NULL);
+  g_print (" %p @ %ums ", event->any.window ? GDK_WINDOW_HWND (event->any.window) : NULL, gdk_event_get_time (event));
 
   switch (event->any.type)
     {
diff -ur gtk+-8bfbb2c/gdk/win32/gdkprivate-win32.h gtk+-8bfbb2c/gdk/win32/gdkprivate-win32.h
--- gtk+-8bfbb2c/gdk/win32/gdkprivate-win32.h	2015-12-27 02:42:10.000000000 +0000
+++ gtk+-8bfbb2c/gdk/win32/gdkprivate-win32.h	2015-12-28 18:28:50.288797000 +0000
@@ -556,4 +556,11 @@
 
 extern gboolean _is_win8_or_later;
 
+/*
+void SetLayeredWindow (HWND hwnd, HWND above, LONG x, LONG y, LONG width, LONG height, cairo_surface_t *content, UINT flags);
+*/
+//void SetLayeredWindow (GdkWindow *shadowed, LONG x, LONG y, UINT flags);
+void SetLayeredWindow (HDWP movegroup, GdkWindow *shadowed, LONG x, LONG y, LONG width, LONG height, UINT flags);
+
+
 #endif /* __GDK_PRIVATE_WIN32_H__ */
diff -ur gtk+-8bfbb2c/gdk/win32/gdkwin32misc.h gtk+-8bfbb2c/gdk/win32/gdkwin32misc.h
--- gtk+-8bfbb2c/gdk/win32/gdkwin32misc.h	2015-12-27 02:42:10.000000000 +0000
+++ gtk+-8bfbb2c/gdk/win32/gdkwin32misc.h	2015-12-27 21:04:01.620779300 +0000
@@ -45,9 +45,11 @@
 #include "gdkprivate-win32.h"
 
 #define GDK_WINDOW_HWND(win)          (GDK_WINDOW_IMPL_WIN32(win->impl)->handle)
+#define GDK_WINDOW_SHWND(win)         (GDK_WINDOW_IMPL_WIN32(win->impl)->shadow_handle)
 #else
 /* definition for exported 'internals' go here */
-#define GDK_WINDOW_HWND(d) (gdk_win32_window_get_handle (d))
+#define GDK_WINDOW_HWND(d)  (gdk_win32_window_get_handle (d))
+#define GDK_WINDOW_SHWND(d) (gdk_win32_window_get_shadow_handle (d))
 
 #endif /* INSIDE_GDK_WIN32 */
 
@@ -81,6 +83,9 @@
 GDK_AVAILABLE_IN_ALL
 HGDIOBJ       gdk_win32_window_get_handle (GdkWindow *window);
 
+GDK_AVAILABLE_IN_3_20
+HGDIOBJ       gdk_win32_window_get_shadow_handle (GdkWindow *window);
+
 GDK_AVAILABLE_IN_ALL
 void          gdk_win32_selection_add_targets (GdkWindow  *owner,
 					       GdkAtom     selection,
diff -ur gtk+-8bfbb2c/gdk/win32/gdkwindow-win32.c gtk+-8bfbb2c/gdk/win32/gdkwindow-win32.c
--- gtk+-8bfbb2c/gdk/win32/gdkwindow-win32.c	2015-12-28 18:46:56.407716500 +0000
+++ gtk+-8bfbb2c/gdk/win32/gdkwindow-win32.c	2015-12-28 18:32:34.350749200 +0000
@@ -51,6 +51,7 @@
 static GSList *modal_window_stack = NULL;
 
 static const cairo_user_data_key_t gdk_win32_cairo_key;
+static const cairo_user_data_key_t gdk_win32_cairo_shadow_key;
 typedef struct _FullscreenInfo FullscreenInfo;
 
 struct _FullscreenInfo
@@ -163,9 +164,7 @@
   wrapper = window_impl->wrapper;
 
   if (!GDK_WINDOW_DESTROYED (wrapper))
-    {
-      gdk_win32_handle_table_remove (window_impl->handle);
-    }
+    gdk_win32_handle_table_remove (window_impl->handle);
 
   g_clear_object (&window_impl->cursor);
 
@@ -658,6 +657,7 @@
 
   wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
 
+  GDK_WINDOW_HWND (window) = NULL;
   hwndNew = CreateWindowExW (dwExStyle,
 			     MAKEINTRESOURCEW (klass),
 			     wtitle,
@@ -691,6 +691,45 @@
 
     }
 
+  if (window->window_type != GDK_WINDOW_CHILD && hwndNew != NULL)
+    {
+      GDK_WINDOW_SHWND (window) = NULL;
+      hwndNew = CreateWindowExW (WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOACTIVATE,
+				 MAKEINTRESOURCEW (klass),
+				 NULL,
+				 WS_POPUP | WS_VISIBLE,
+				 x,
+				 y,
+				 window_width, window_height,
+				 hparent,
+				 NULL,
+				 _gdk_app_hmodule,
+				 window);
+    if (GDK_WINDOW_SHWND (window) != hwndNew)
+      {
+        g_warning ("gdk_window_new: gdk_event_translate::WM_CREATE (%p, %p) HWND mismatch.",
+		   GDK_WINDOW_SHWND (window),
+		   hwndNew);
+
+      /* HB: IHMO due to a race condition the handle was increased by
+       * one, which causes much trouble. Because I can't find the
+       * real bug, try to workaround it ...
+       * To reproduce: compile with MSVC 5, DEBUG=1
+       */
+# if 0
+      gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
+      GDK_WINDOW_HWND (window) = hwndNew;
+      gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
+# else
+      /* the old behaviour, but with warning */
+        impl->shadow_handle = hwndNew;
+# endif
+
+      }
+    }
+  else
+    impl->shadow_handle = NULL;
+
   if (window->window_type != GDK_WINDOW_CHILD)
     {
       GetWindowRect (GDK_WINDOW_HWND (window), &rect);
@@ -700,11 +739,20 @@
       /* Now we know the initial position, move to actually specified position */
       if (real_x != x || real_y != y)
 	{
-	  API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
+          HDWP move_group;
+
+          move_group = BeginDeferWindowPos (2);
+
+          if (move_group == NULL)
+            _gdk_win32_api_failed (G_STRLOC, "BeginDeferWindowPos");
+
+	  API_CALL (DeferWindowPos, (move_group, GDK_WINDOW_HWND (window),
 				   SWP_NOZORDER_SPECIFIED,
 				   real_x, real_y, 0, 0,
 				   SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
+          SetLayeredWindow (move_group, window, real_x, real_y, 0, 0, 0);
 	}
+
     }
 
   g_object_ref (window);
@@ -848,6 +896,9 @@
     {
       window->destroyed = TRUE;
       DestroyWindow (GDK_WINDOW_HWND (window));
+
+      if (GDK_WINDOW_SHWND (window) != NULL)
+        DestroyWindow (GDK_WINDOW_SHWND (window));
     }
 }
 
@@ -1105,10 +1156,20 @@
 	  y = center_on_rect.top + ((center_on_rect.bottom - center_on_rect.top) - (window_rect.bottom - window_rect.top)) / 2;
 	}
 
-      API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
+      {
+          HDWP move_group;
+
+          move_group = BeginDeferWindowPos (2);
+
+          if (move_group == NULL)
+            _gdk_win32_api_failed (G_STRLOC, "BeginDeferWindowPos");
+
+          API_CALL (DeferWindowPos, (move_group, GDK_WINDOW_HWND (window),
 			       SWP_NOZORDER_SPECIFIED,
 			       x, y, 0, 0,
 			       SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
+          SetLayeredWindow (move_group, window, x, y, 0, 0, 0);
+      }
     }
 
   if (!already_mapped &&
@@ -1155,10 +1216,20 @@
 	    }
 
 	  if (x != window_rect.left || y != window_rect.top)
-	    API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
-				     SWP_NOZORDER_SPECIFIED,
-				     window_rect.left, window_rect.top, 0, 0,
-				     SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
+            {
+              HDWP move_group;
+
+              move_group = BeginDeferWindowPos (2);
+
+              if (move_group == NULL)
+                _gdk_win32_api_failed (G_STRLOC, "BeginDeferWindowPos");
+
+	      API_CALL (DeferWindowPos, (move_group, GDK_WINDOW_HWND (window),
+				       SWP_NOZORDER_SPECIFIED,
+				       window_rect.left, window_rect.top, 0, 0,
+				       SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
+              SetLayeredWindow (move_group, window, window_rect.left, window_rect.top, 0, 0, 0);
+            }
 	}
     }
 
@@ -1241,6 +1312,8 @@
     {
       ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
     }
+
+  SetLayeredWindow (0, window, 0, 0, 0, 0, SWP_NOMOVE | SWP_HIDEWINDOW);
 }
 
 static void
@@ -1292,10 +1365,20 @@
                                GDK_WINDOW_HWND (window),
                                x - _gdk_offset_x, y - _gdk_offset_y));
 
-      API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
+      {
+          HDWP move_group;
+
+          move_group = BeginDeferWindowPos (2);
+
+          if (move_group == NULL)
+            _gdk_win32_api_failed (G_STRLOC, "BeginDeferWindowPos");
+
+          API_CALL (DeferWindowPos, (move_group, GDK_WINDOW_HWND (window),
 			       SWP_NOZORDER_SPECIFIED,
                                x - _gdk_offset_x, y - _gdk_offset_y, 0, 0,
                                SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
+          SetLayeredWindow (move_group, window, x - _gdk_offset_x, y - _gdk_offset_y, 0, 0, 0);
+      }
     }
 }
 
@@ -1341,6 +1424,7 @@
                                outer_rect.right - outer_rect.left,
                                outer_rect.bottom - outer_rect.top,
                                SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER));
+      SetLayeredWindow (0, window, 0, 0, outer_rect.right - outer_rect.left, outer_rect.bottom - outer_rect.top, SWP_NOMOVE);
       window->resize_count += 1;
     }
 }
@@ -1388,12 +1472,22 @@
                                outer_rect.right - outer_rect.left,
                                outer_rect.bottom - outer_rect.top));
 
-      API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
+      {
+          HDWP move_group;
+
+          move_group = BeginDeferWindowPos (2);
+
+          if (move_group == NULL)
+            _gdk_win32_api_failed (G_STRLOC, "BeginDeferWindowPos");
+
+          API_CALL (DeferWindowPos, (move_group, GDK_WINDOW_HWND (window),
 			       SWP_NOZORDER_SPECIFIED,
                                x - _gdk_offset_x, y - _gdk_offset_y,
                                outer_rect.right - outer_rect.left,
                                outer_rect.bottom - outer_rect.top,
                                SWP_NOACTIVATE | SWP_NOZORDER));
+          SetLayeredWindow (move_group, window, x - _gdk_offset_x, y - _gdk_offset_y, outer_rect.right - outer_rect.left, outer_rect.bottom - outer_rect.top, 0);
+      }
     }
 }
 
@@ -1484,8 +1578,18 @@
   API_CALL (SetParent, (GDK_WINDOW_HWND (window),
 			GDK_WINDOW_HWND (new_parent)));
 
-  API_CALL (MoveWindow, (GDK_WINDOW_HWND (window),
-			 x, y, window->width, window->height, TRUE));
+  {
+      HDWP move_group;
+
+      move_group = BeginDeferWindowPos (2);
+
+      if (move_group == NULL)
+        _gdk_win32_api_failed (G_STRLOC, "BeginDeferWindowPos");
+
+      API_CALL (DeferWindowPos, (move_group, GDK_WINDOW_HWND (window), HWND_NOTOPMOST, 
+			 x, y, window->width, window->height, 0));
+      SetLayeredWindow (move_group, window, x, y, window->width, window->height, 0);
+  }
 
   /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
    * the root window
@@ -1544,11 +1648,15 @@
          * fail when for example dragging a window belonging to a different
          * application at the time of a gtk_window_present() call due to focus
          * stealing prevention. */
-        SetForegroundWindow (GDK_WINDOW_HWND (window));
+        {
+          SetForegroundWindow (GDK_WINDOW_HWND (window));
+        }
       else
         API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
   			         0, 0, 0, 0,
 			         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
+
+      SetLayeredWindow (0, window, 0, 0, 0, 0, SWP_NOMOVE);
     }
 }
 
@@ -1566,6 +1674,7 @@
       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_BOTTOM,
 			       0, 0, 0, 0,
 			       SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
+      SetLayeredWindow (0, window, 0, 0, 0, 0, SWP_NOMOVE);
     }
 }
 
@@ -2521,6 +2630,7 @@
 		0, 0,
 		rect.right - rect.left, rect.bottom - rect.top,
 		flags);
+  SetLayeredWindow (0, window, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE);
 }
 
 static void
@@ -2923,9 +3033,19 @@
       SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE,
                      (fi->style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP);
 
-      API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP,
+      {
+          HDWP move_group;
+
+          move_group = BeginDeferWindowPos (2);
+
+          if (move_group == NULL)
+            _gdk_win32_api_failed (G_STRLOC, "BeginDeferWindowPos");
+
+          API_CALL (DeferWindowPos, (move_group, GDK_WINDOW_HWND (window), HWND_TOP,
 			       x, y, width, height,
 			       SWP_NOCOPYBITS | SWP_SHOWWINDOW));
+          SetLayeredWindow (move_group, window, x, y, width, height, SWP_SHOWWINDOW);
+      }
     }
 }
 
@@ -2945,10 +3065,21 @@
 
       impl->hint_flags = fi->hint_flags;
       SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, fi->style);
-      API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_NOTOPMOST,
+
+      {
+          HDWP move_group;
+
+          move_group = BeginDeferWindowPos (2);
+
+          if (move_group == NULL)
+            _gdk_win32_api_failed (G_STRLOC, "BeginDeferWindowPos");
+
+          API_CALL (DeferWindowPos, (move_group, GDK_WINDOW_HWND (window), HWND_NOTOPMOST,
 			       fi->r.left, fi->r.top,
 			       fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
 			       SWP_NOCOPYBITS | SWP_SHOWWINDOW));
+          SetLayeredWindow (move_group, window, fi->r.left, fi->r.top, fi->r.right - fi->r.left, fi->r.bottom - fi->r.top, SWP_SHOWWINDOW);
+      }
 
       g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL);
       g_free (fi);
@@ -2975,6 +3106,7 @@
 			       setting ? HWND_TOPMOST : HWND_NOTOPMOST,
 			       0, 0, 0, 0,
 			       SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
+      SetLayeredWindow (0, window, 0, 0, 0, 0, SWP_NOMOVE);
     }
 
   gdk_synthesize_window_state (window,
@@ -3001,6 +3133,7 @@
 			       setting ? HWND_BOTTOM : HWND_NOTOPMOST,
 			       0, 0, 0, 0,
 			       SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
+      SetLayeredWindow (0, window, 0, 0, 0, 0, SWP_NOMOVE);
     }
 
   gdk_synthesize_window_state (window,
@@ -3398,6 +3531,7 @@
 
   _gdk_win32_impl_release_dc (impl);
   impl->cairo_surface = NULL;
+
 }
 
 static cairo_surface_t *
@@ -3531,3 +3665,19 @@
 
   return GDK_WINDOW_HWND (window);
 }
+
+HGDIOBJ
+gdk_win32_window_get_shadow_handle (GdkWindow *window)
+{
+  /* Try to ensure the window has a native window */
+  if (!_gdk_window_has_impl (window))
+    gdk_window_ensure_native (window);
+
+  if (!GDK_WINDOW_IS_WIN32 (window))
+    {
+      g_warning (G_STRLOC " window is not a native Win32 window");
+      return NULL;
+    }
+
+  return GDK_WINDOW_SHWND (window);
+}
diff -ur gtk+-8bfbb2c/gdk/win32/gdkwindow-win32.h gtk+-8bfbb2c/gdk/win32/gdkwindow-win32.h
--- gtk+-8bfbb2c/gdk/win32/gdkwindow-win32.h	2015-12-27 02:42:10.000000000 +0000
+++ gtk+-8bfbb2c/gdk/win32/gdkwindow-win32.h	2015-12-28 01:39:38.358178300 +0000
@@ -83,6 +83,8 @@
   HDC              hdc;
   int              hdc_count;
   HBITMAP          saved_dc_bitmap; /* Original bitmap for dc */
+
+  HANDLE           shadow_handle;
 };
 
 struct _GdkWindowImplWin32Class
diff -ur gtk+-8bfbb2c/gtk/gtkwindow.c gtk+-8bfbb2c/gtk/gtkwindow.c
--- gtk+-8bfbb2c/gtk/gtkwindow.c	2015-12-28 18:46:56.376712600 +0000
+++ gtk+-8bfbb2c/gtk/gtkwindow.c	2015-12-28 16:55:51.604394000 +0000
@@ -75,6 +75,7 @@
 
 #ifdef GDK_WINDOWING_WIN32
 #include "win32/gdkwin32.h"
+#include <cairo-win32.h>
 #endif
 
 #ifdef GDK_WINDOWING_WAYLAND
@@ -256,6 +257,11 @@
 
   guint    use_subsurface            : 1;
 
+  guint    use_dedicated_shadow      : 1;
+  guint    is_shadow                 : 1;
+
+  cairo_surface_t *shadow_surface;
+
   GdkWindowTypeHint type_hint;
 
   GtkGesture *multipress_gesture;
@@ -495,7 +501,9 @@
 static void     gtk_window_unrealize_icon             (GtkWindow    *window);
 static void     update_window_buttons                 (GtkWindow    *window);
 static void     get_shadow_width                      (GtkWindow    *window,
-                                                       GtkBorder    *shadow_width);
+                                                       GtkBorder    *shadow_width,
+                                                       gboolean      without_shadow,
+                                                       gboolean      without_margin);
 
 static GtkKeyHash *gtk_window_get_key_hash        (GtkWindow   *window);
 static void        gtk_window_free_key_hash       (GtkWindow   *window);
@@ -4031,6 +4039,41 @@
 }
 
 static gboolean
+gtk_window_should_use_dedicated_shadow (GtkWindow *window)
+{
+#ifdef GDK_WINDOWING_WIN32
+  GdkDisplay *display;
+  GdkScreen *screen;
+  GdkVisual *visual;
+#endif
+
+  const gchar *ds_env = g_getenv ("GTK_DEDICATEDSHADOW");
+
+  if (window->priv->is_shadow)
+    return FALSE;
+
+#ifdef GDK_WINDOWING_WIN32
+  screen = _gtk_window_get_screen (window);
+  display = gdk_screen_get_display (screen);
+
+  if (GDK_IS_WIN32_DISPLAY (display))
+    {
+      if (!gdk_screen_is_composited (screen))
+        return FALSE;
+
+      /* We need a visual with alpha */
+      visual = gdk_screen_get_rgba_visual (screen);
+      if (!visual)
+        return FALSE;
+    }
+
+  return (g_strcmp0 (ds_env, "1") != 0);
+#else
+  return (g_strcmp0 (ds_env, "1") == 0);
+#endif
+}
+
+static gboolean
 gtk_window_supports_client_shadow (GtkWindow *window)
 {
   GdkDisplay *display;
@@ -4155,6 +4198,7 @@
     }
 
   priv->use_client_shadow = gtk_window_supports_client_shadow (window);
+  priv->use_dedicated_shadow = gtk_window_should_use_dedicated_shadow (window);
 
   gtk_window_enable_csd (window);
   priv->title_box = titlebar;
@@ -5081,7 +5125,7 @@
       priv->fullscreen)
     return;
 
-  get_shadow_width (window, &window_border);
+  get_shadow_width (window, &window_border, priv->use_dedicated_shadow, FALSE);
   w = *width + apply * (window_border.left + window_border.right);
   h = *height + apply * (window_border.top + window_border.bottom);
 
@@ -5459,7 +5503,8 @@
       gint dx;
       gint dy;
 
-      get_shadow_width (window, &window_border);
+      get_shadow_width (window, &window_border, priv->use_dedicated_shadow, FALSE);
+
       if (priv->title_box != NULL &&
           gtk_widget_get_visible (priv->title_box) &&
           gtk_widget_get_child_visible (priv->title_box))
@@ -6038,6 +6083,8 @@
   GtkWindowPrivate *priv = window->priv;
 
   priv->use_client_shadow = gtk_window_supports_client_shadow (window);
+  priv->use_dedicated_shadow = gtk_window_should_use_dedicated_shadow (window);
+
   if (!priv->use_client_shadow)
     return;
 
@@ -6512,7 +6559,8 @@
   gtk_widget_get_preferred_size (popover->widget, NULL, &req);
   _gtk_widget_get_allocation (GTK_WIDGET (window), &win_alloc);
 
-  get_shadow_width (window, &win_border);
+  get_shadow_width (window, &win_border, window->priv->use_dedicated_shadow, FALSE);
+
   win_alloc.x += win_border.left;
   win_alloc.y += win_border.top;
   win_alloc.width -= win_border.left + win_border.right;
@@ -6704,12 +6752,14 @@
 
 static void
 get_shadow_width (GtkWindow *window,
-                  GtkBorder *shadow_width)
+                  GtkBorder *shadow_width,
+                  gboolean   without_shadow,
+                  gboolean   without_margin)
 {
   GtkWindowPrivate *priv = window->priv;
   GtkBorder border = { 0 };
   GtkBorder d = { 0 };
-  GtkBorder margin;
+  GtkBorder margin = { 0 };
   GtkStyleContext *context;
   GtkStateFlags s;
   GtkCssValue *shadows;
@@ -6746,13 +6796,19 @@
   _gtk_css_shadows_value_get_extents (shadows, &border);
 
   if (priv->type != GTK_WINDOW_POPUP)
-    {
       /* ... and compare it to the margin size, which we use for resize grips */
       gtk_style_context_get_margin (context, s, &margin);
+
+  if (without_shadow && !without_margin)
+    sum_borders (&d, &margin);
+  else if (!without_shadow && without_margin)
+    sum_borders (&d, &border);
+  else if (!without_shadow && !without_margin)
+    {
       max_borders (&border, &margin);
+      sum_borders (&d, &border);
     }
 
-  sum_borders (&d, &border);
   *shadow_width = d;
 
   gtk_style_context_restore (context);
@@ -6815,7 +6871,8 @@
                         "decoration-resize-handle", &handle,
                         NULL);
   gtk_style_context_restore (context);
-  get_shadow_width (window, &window_border);
+
+  get_shadow_width (window, &window_border, window->priv->use_dedicated_shadow, FALSE);
 
   if (priv->border_window[0] == NULL)
     goto shape;
@@ -7378,7 +7435,7 @@
   child_allocation.width = allocation.width;
   child_allocation.height = allocation.height;
 
-  get_shadow_width (window, &window_border);
+  get_shadow_width (window, &window_border, priv->use_dedicated_shadow, FALSE);
 
   update_realized_window_properties (window, &child_allocation, &window_border);
 
@@ -7572,7 +7629,7 @@
   child_allocation.width = allocation->width;
   child_allocation.height = allocation->height;
 
-  get_shadow_width (window, &window_border);
+  get_shadow_width (window, &window_border, priv->use_dedicated_shadow, FALSE);
 
   if (_gtk_widget_get_realized (widget))
     update_realized_window_properties (window, &child_allocation, &window_border);
@@ -8538,7 +8595,7 @@
   if (priv->decorated &&
       !priv->fullscreen)
     {
-      get_shadow_width (window, &window_border);
+      get_shadow_width (window, &window_border, priv->use_dedicated_shadow, FALSE);
 
       if (priv->title_box != NULL &&
           gtk_widget_get_visible (priv->title_box) &&
@@ -8599,7 +8656,7 @@
   if (priv->decorated &&
       !priv->fullscreen)
     {
-      get_shadow_width (window, &window_border);
+      get_shadow_width (window, &window_border, priv->use_dedicated_shadow, FALSE);
 
       height -= window_border.top + window_border.bottom;
 
@@ -8668,7 +8725,7 @@
   if (priv->decorated &&
       !priv->fullscreen)
     {
-      get_shadow_width (window, &window_border);
+      get_shadow_width (window, &window_border, priv->use_dedicated_shadow, FALSE);
 
       if (priv->title_box != NULL &&
           gtk_widget_get_visible (priv->title_box) &&
@@ -8731,7 +8788,7 @@
   if (priv->decorated &&
       !priv->fullscreen)
     {
-      get_shadow_width (window, &window_border);
+      get_shadow_width (window, &window_border, priv->use_dedicated_shadow, FALSE);
 
       width -= window_border.left + window_border.right;
 
@@ -9914,6 +9971,54 @@
   new_geometry->win_gravity = priv->gravity;
 }
 
+static cairo_surface_t *
+gtk_cairo_create_shadow_surface (GtkWindow *window, gint width, gint height, gint window_x_offset, gint window_y_offset)
+{
+  cairo_surface_t *current_shadow;
+  gint current_width, current_height, current_window_x_offset, current_window_y_offset;
+  g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+
+  current_shadow = gdk_window_get_shadow_surface (_gtk_widget_get_window (GTK_WIDGET (window)),
+                                                  &current_width, &current_height,
+                                                  &current_window_x_offset, &current_window_y_offset);
+  if (current_shadow == NULL ||
+      current_width != width ||
+      current_height != height ||
+      current_window_x_offset != window_x_offset ||
+      current_window_y_offset != window_y_offset)
+    {
+      cairo_surface_destroy (window->priv->shadow_surface);
+      window->priv->shadow_surface = NULL;
+    }
+
+#ifdef GDK_WINDOWING_WIN32
+  window->priv->shadow_surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
+#else
+  window->priv->shadow_surface = gdk_window_create_similar_image_surface (_gtk_widget_get_window (GTK_WIDGET (window)), CAIRO_FORMAT_ARGB32, allocation.width, allocation.height, 0);
+#endif
+  gdk_window_set_shadow_surface (_gtk_widget_get_window (GTK_WIDGET (window)), window->priv->shadow_surface, width, height, window_x_offset, window_y_offset);
+
+  return cairo_surface_reference (window->priv->shadow_surface);
+}
+
+static cairo_t *
+gtk_cairo_create_shadow (GtkWindow *window, gint width, gint height, gint window_x_offset, gint window_y_offset)
+{
+  cairo_t *cr;
+  cairo_surface_t *surface;
+
+  g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+
+  surface = gtk_cairo_create_shadow_surface (window, width, height, window_x_offset, window_y_offset);
+
+  cr = cairo_create (surface);
+
+  cairo_surface_destroy (surface);
+
+  return cr;
+}
+
+
 /***********************
  * Redrawing functions *
  ***********************/
@@ -9927,11 +10032,13 @@
   gboolean ret = FALSE;
   GtkAllocation allocation;
   GtkBorder window_border;
+  GtkBorder shadow_window_border;
   gint title_height;
 
   context = gtk_widget_get_style_context (widget);
 
-  get_shadow_width (GTK_WINDOW (widget), &window_border);
+  get_shadow_width (GTK_WINDOW (widget), &window_border, priv->use_dedicated_shadow, FALSE);
+  get_shadow_width (GTK_WINDOW (widget), &shadow_window_border, FALSE, priv->use_dedicated_shadow);
   _gtk_widget_get_allocation (widget, &allocation);
 
   if (gtk_cairo_should_draw_window (cr, _gtk_widget_get_window (widget)))
@@ -9969,6 +10076,30 @@
                                 allocation.height);
             }
 
+          if (priv->use_dedicated_shadow)
+            {
+              cairo_t *crs = gtk_cairo_create_shadow (GTK_WINDOW (widget),
+                                                      allocation.width - (window_border.left + window_border.right) + (shadow_window_border.left + shadow_window_border.right),
+                                                      allocation.height - (window_border.top + window_border.bottom) + (shadow_window_border.top + shadow_window_border.bottom),
+                                                      shadow_window_border.left - window_border.left, shadow_window_border.top - window_border.top);
+
+              gtk_render_background (context, crs,
+                                     shadow_window_border.left, shadow_window_border.top,
+                                     allocation.width - (window_border.left + window_border.right) /*- (shadow_window_border.left + shadow_window_border.right)*/,
+                                     allocation.height - (window_border.top + window_border.bottom) /*- (shadow_window_border.top + shadow_window_border.bottom)*/);
+
+/*
+              gtk_render_frame (context, crs,
+                                window_border.left, window_border.top,
+                                allocation.width -
+                                (window_border.left + window_border.right),
+                                allocation.height -
+                                (window_border.top + window_border.bottom));
+*/
+
+              cairo_destroy (crs);
+            }
+
           gtk_style_context_restore (context);
         }
 
@@ -11975,7 +12106,7 @@
 _gtk_window_get_shadow_width (GtkWindow *window,
                               GtkBorder *border)
 {
-  get_shadow_width (window, border);
+  get_shadow_width (window, border, window->priv->use_dedicated_shadow, FALSE);
 }
 
 void
