]> Pileus Git - ~andy/gtk/blobdiff - gdk/win32/gdkwindow-win32.c
List the three theme gtkrc files separately, zip doesn't do anything if
[~andy/gtk] / gdk / win32 / gdkwindow-win32.c
index 640eaccf3ebabd5b4e44e1773f357b983122daec..5fe64b7e9f728fb73089e79486f537297a1ad564 100644 (file)
@@ -1,6 +1,7 @@
 /* GDK - The GIMP Drawing Kit
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 1998-2002 Tor Lillqvist
+ * Copyright (C) 1998-2004 Tor Lillqvist
+ * Copyright (C) 2001-2004 Hans Breuer
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -25,6 +26,7 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <config.h>
 #include <stdlib.h>
 
 #include "gdk.h" /* gdk_rectangle_intersect */
 #include "gdkprivate-win32.h"
 #include "gdkinput-win32.h"
 
+#if defined __MINGW32__ || (WINVER < 0x0500)
+typedef struct { 
+  DWORD        bV5Size; 
+  LONG         bV5Width; 
+  LONG         bV5Height; 
+  WORD         bV5Planes; 
+  WORD         bV5BitCount; 
+  DWORD        bV5Compression; 
+  DWORD        bV5SizeImage; 
+  LONG         bV5XPelsPerMeter; 
+  LONG         bV5YPelsPerMeter; 
+  DWORD        bV5ClrUsed; 
+  DWORD        bV5ClrImportant; 
+  DWORD        bV5RedMask; 
+  DWORD        bV5GreenMask; 
+  DWORD        bV5BlueMask; 
+  DWORD        bV5AlphaMask; 
+  DWORD        bV5CSType; 
+  CIEXYZTRIPLE bV5Endpoints; 
+  DWORD        bV5GammaRed; 
+  DWORD        bV5GammaGreen; 
+  DWORD        bV5GammaBlue; 
+  DWORD        bV5Intent; 
+  DWORD        bV5ProfileData; 
+  DWORD        bV5ProfileSize; 
+  DWORD        bV5Reserved; 
+} BITMAPV5HEADER;
+
+#endif
+
+#if 0
 #include <gdk-pixbuf/gdk-pixbuf.h>
-#include <stdio.h> /* sprintf */
+#include <stdio.h>
+#endif
 
 static GdkColormap* gdk_window_impl_win32_get_colormap (GdkDrawable *drawable);
 static void         gdk_window_impl_win32_set_colormap (GdkDrawable *drawable,
@@ -92,7 +126,8 @@ gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
   impl->height = 1;
 
   impl->hcursor = NULL;
-  impl->hicon = NULL;
+  impl->hicon_big = NULL;
+  impl->hicon_small = NULL;
   impl->hint_flags = 0;
   impl->extension_events_selected = FALSE;
 }
@@ -142,10 +177,15 @@ gdk_window_impl_win32_finalize (GObject *object)
       GDI_CALL (DestroyCursor, (window_impl->hcursor));
       window_impl->hcursor = NULL;
     }
-  if (window_impl->hicon != NULL)
+  if (window_impl->hicon_big != NULL)
     {
-      GDI_CALL (DestroyIcon, (window_impl->hicon));
-      window_impl->hicon = NULL;
+      GDI_CALL (DestroyIcon, (window_impl->hicon_big));
+      window_impl->hicon_big = NULL;
+    }
+  if (window_impl->hicon_small != NULL)
+    {
+      GDI_CALL (DestroyIcon, (window_impl->hicon_small));
+      window_impl->hicon_small = NULL;
     }
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -182,7 +222,8 @@ gdk_window_impl_win32_get_colormap (GdkDrawable *drawable)
   if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only && 
       drawable_impl->colormap == NULL)
     {
-      drawable_impl->colormap = gdk_colormap_get_system ();
+      drawable_impl->colormap = 
+        gdk_screen_get_system_colormap (gdk_drawable_get_screen (drawable));
       g_object_ref (drawable_impl->colormap);
     }
   
@@ -229,6 +270,7 @@ gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable)
 {
   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (drawable);
   GdkRectangle result_rect;
+  HDC hdc;
 
   result_rect.x = 0;
   result_rect.y = 0;
@@ -237,23 +279,54 @@ gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable)
 
   gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
 
+  /* take this win32 specific part into account (smaller when obscured) */
+  hdc = GetDC (GDK_DRAWABLE_IMPL_WIN32_HANDLE (impl));
+  if (hdc)
+    {
+      RECT r;
+      if (SIMPLEREGION == GetClipBox (hdc, &r))
+        {
+          GdkRectangle gr;
+
+          gr.x = r.left;
+          gr.y = r.top;
+          gr.width = r.right - r.left;
+          gr.height = r.bottom - r.top;
+
+          gdk_rectangle_intersect (&result_rect, &gr, &result_rect);
+        }
+      ReleaseDC (GDK_DRAWABLE_IMPL_WIN32_HANDLE (drawable), hdc);
+    }
+
   return gdk_region_rectangle (&result_rect);
 }
 
+void
+_gdk_root_window_size_init (void)
+{
+  GdkWindowImplWin32 *impl;
+  GdkRectangle rect;
+  int i;
+
+  impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) _gdk_parent_root)->impl);
+  rect = _gdk_monitors[0];
+  for (i = 1; i < _gdk_num_monitors; i++)
+    gdk_rectangle_union (&rect, _gdk_monitors+i, &rect);
+
+  impl->width = rect.width;
+  impl->height = rect.height;
+}
+
 void
 _gdk_windowing_window_init (void)
 {
   GdkWindowObject *private;
-  GdkWindowImplWin32 *impl;
   GdkDrawableImplWin32 *draw_impl;
-  GdkRectangle rect;
-  gint i;
 
   g_assert (_gdk_parent_root == NULL);
   
   _gdk_parent_root = g_object_new (GDK_TYPE_WINDOW, NULL);
   private = (GdkWindowObject *)_gdk_parent_root;
-  impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
   
   draw_impl->handle = _gdk_root_window;
@@ -264,13 +337,8 @@ _gdk_windowing_window_init (void)
   private->window_type = GDK_WINDOW_ROOT;
   private->depth = gdk_visual_get_system ()->depth;
 
-  rect = _gdk_monitors[0];
-  for (i = 1; i < _gdk_num_monitors; i++)
-    gdk_rectangle_union (&rect, _gdk_monitors+i, &rect);
-
-  impl->width = rect.width;
-  impl->height = rect.height;
-
+  _gdk_root_window_size_init ();
   _gdk_window_init_position (GDK_WINDOW (private));
 
   gdk_win32_handle_table_insert (&_gdk_root_window, _gdk_parent_root);
@@ -409,10 +477,11 @@ RegisterGdkClass (GdkWindowType wtype)
   return klass;
 }
 
-GdkWindow*
-gdk_window_new (GdkWindow     *parent,
-               GdkWindowAttr *attributes,
-               gint           attributes_mask)
+static GdkWindow*
+gdk_window_new_internal (GdkWindow     *parent,
+                        GdkWindowAttr *attributes,
+                        gint           attributes_mask,
+                        gboolean       from_set_skip_taskbar_hint)
 {
   HANDLE hparent;
   ATOM klass = 0;
@@ -468,6 +537,9 @@ gdk_window_new (GdkWindow     *parent,
   
   private->parent = (GdkWindowObject *)parent;
 
+  private->accept_focus = TRUE;
+  private->focus_on_map = TRUE;
+
   if (attributes_mask & GDK_WA_X)
     private->x = attributes->x;
   else
@@ -488,7 +560,19 @@ gdk_window_new (GdkWindow     *parent,
   impl->width = (attributes->width > 1) ? (attributes->width) : (1);
   impl->height = (attributes->height > 1) ? (attributes->height) : (1);
   impl->extension_events_selected = FALSE;
-  private->window_type = attributes->window_type;
+  if (attributes->wclass == GDK_INPUT_ONLY)
+    {
+      /* Backwards compatiblity - we've always ignored
+       * attributes->window_type for input-only windows
+       * before
+       */
+      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
+       private->window_type = GDK_WINDOW_TEMP;
+      else
+       private->window_type = GDK_WINDOW_CHILD;
+    }
+  else
+    private->window_type = attributes->window_type;
 
   if (attributes->wclass == GDK_INPUT_OUTPUT)
     {
@@ -513,7 +597,7 @@ gdk_window_new (GdkWindow     *parent,
       dwExStyle = WS_EX_TRANSPARENT;
       private->depth = 0;
       private->input_only = TRUE;
-      draw_impl->colormap = gdk_colormap_get_system ();
+      draw_impl->colormap = gdk_screen_get_system_colormap (screen);
       g_object_ref (draw_impl->colormap);
       GDK_NOTE (MISC, g_print ("...GDK_INPUT_ONLY, system colormap"));
     }
@@ -601,21 +685,6 @@ gdk_window_new (GdkWindow     *parent,
 
   mbtitle = g_locale_from_utf8 (title, -1, NULL, NULL, NULL);
   
-#ifdef WITHOUT_WM_CREATE
-  draw_impl->handle =
-    CreateWindowEx (dwExStyle,
-                   MAKEINTRESOURCE(klass),
-                   mbtitle,
-                   dwStyle,
-                   ((attributes_mask & GDK_WA_X) ?
-                    impl->position_info.x - offset_x : CW_USEDEFAULT),
-                   impl->position_info.y - offset_y, 
-                   window_width, window_height,
-                   hparent,
-                   NULL,
-                   _gdk_app_hmodule,
-                   NULL);
-#else
   {
   HWND hwndNew =
     CreateWindowEx (dwExStyle,
@@ -654,7 +723,6 @@ gdk_window_new (GdkWindow     *parent,
   }
   g_object_ref (window);
   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
-#endif
 
   GDK_NOTE (MISC, g_print ("... \"%s\" %dx%d@+%d+%d %p = %p\n",
                           mbtitle,
@@ -674,10 +742,8 @@ gdk_window_new (GdkWindow     *parent,
       return NULL;
     }
 
-#ifdef WITHOUT_WM_CREATE
-  g_object_ref (window);
-  gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
-#endif
+  if (!from_set_skip_taskbar_hint && private->window_type == GDK_WINDOW_TEMP)
+    gdk_window_set_skip_taskbar_hint (window, TRUE);
 
   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
                                  (attributes->cursor) :
@@ -686,6 +752,14 @@ gdk_window_new (GdkWindow     *parent,
   return window;
 }
 
+GdkWindow*
+gdk_window_new (GdkWindow     *parent,
+               GdkWindowAttr *attributes,
+               gint           attributes_mask)
+{
+  return gdk_window_new_internal (parent, attributes, attributes_mask, FALSE);
+}
+
 GdkWindow *
 gdk_window_foreign_new_for_display (GdkDisplay      *display,
                                     GdkNativeWindow  anid)
@@ -769,30 +843,31 @@ _gdk_windowing_window_destroy (GdkWindow *window,
   if (private->extension_events != 0)
     _gdk_input_window_destroy (window);
 
-  if (private->window_type == GDK_WINDOW_FOREIGN)
-    {
-      if (!foreign_destroy && (private->parent != NULL))
-       {
-         /* It's somebody else's window, but in our hierarchy,
-          * so reparent it to the root window, and then call
-          * DestroyWindow() on it.
-          */
-         gdk_window_hide (window);
-         gdk_window_reparent (window, NULL, 0, 0);
-         
-         /* Is this too drastic? Many (most?) applications
-          * quit if any window receives WM_QUIT I think.
-          * OTOH, I don't think foreign windows are much
-          * used, so the question is maybe academic.
-          */
-         PostMessage (GDK_WINDOW_HWND (window), WM_QUIT, 0, 0);
-       }
-    }
-  else if (!recursing && !foreign_destroy)
+
+  if (!recursing && !foreign_destroy)
     {
       private->destroyed = TRUE;
       DestroyWindow (GDK_WINDOW_HWND (window));
     }
+  gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window));
+}
+
+void
+_gdk_windowing_window_destroy_foreign (GdkWindow *window)
+{
+  /* It's somebody else's window, but in our hierarchy,
+   * so reparent it to the root window, and then call
+   * DestroyWindow() on it.
+   */
+  gdk_window_hide (window);
+  gdk_window_reparent (window, NULL, 0, 0);
+  
+  /* Is this too drastic? Many (most?) applications
+   * quit if any window receives WM_QUIT I think.
+   * OTOH, I don't think foreign windows are much
+   * used, so the question is maybe academic.
+   */
+  PostMessage (GDK_WINDOW_HWND (window), WM_QUIT, 0, 0);
 }
 
 /* This function is called when the window really gone.
@@ -911,7 +986,8 @@ show_window_internal (GdkWindow *window,
 {
   GdkWindowObject *private;
   HWND old_active_window;
-  
+  gboolean focus_on_map = TRUE;
+
   private = (GdkWindowObject *) window;
 
   if (private->destroyed)
@@ -954,9 +1030,27 @@ show_window_internal (GdkWindow *window,
   /* Other cases */
   
   if (!GDK_WINDOW_IS_MAPPED (window))
-    gdk_synthesize_window_state (window,
-                                GDK_WINDOW_STATE_WITHDRAWN,
-                                0);
+    {
+      gdk_synthesize_window_state (window,
+                                  GDK_WINDOW_STATE_WITHDRAWN,
+                                  0);
+      focus_on_map = private->focus_on_map;
+    }
+
+  /* Use SetWindowPos to show transparent windows so automatic redraws
+   * in other windows can be suppressed.
+   */
+  if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
+    {
+      UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE;
+      if (!raise)
+       flags |= SWP_NOZORDER;
+      if (!raise || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
+       flags |= SWP_NOACTIVATE;
+
+      SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOP, 0, 0, 0, 0, flags);
+      return;
+    }
 
   old_active_window = GetActiveWindow ();
 
@@ -979,17 +1073,22 @@ show_window_internal (GdkWindow *window,
     ShowWindow (GDK_WINDOW_HWND (window), SW_MAXIMIZE);
   else if (private->state & GDK_WINDOW_STATE_ICONIFIED)
     ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE);
-  else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
+  else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNOACTIVATE);
   else
     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL);
 
   if (raise)
-    if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
-      SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOPMOST, 0, 0, 0, 0,
-                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
-    else
-      BringWindowToTop (GDK_WINDOW_HWND (window));
+    {
+      if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
+        SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOPMOST, 0, 0, 0, 0,
+                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+      else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL
+              || GDK_WINDOW_TYPE (window) == GDK_WINDOW_DIALOG)
+        SetForegroundWindow (GDK_WINDOW_HWND (window));
+      else
+        BringWindowToTop (GDK_WINDOW_HWND (window));
+    }
   else if (old_active_window != GDK_WINDOW_HWND (window))
     SetActiveWindow (old_active_window);
 }
@@ -1037,8 +1136,8 @@ gdk_window_hide (GdkWindow *window)
   
   if (GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
     {
-      SetWindowPos(GDK_WINDOW_HWND (window), HWND_BOTTOM, 0, 0, 0, 0,
-                  SWP_HIDEWINDOW | SWP_NOREDRAW | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
+      SetWindowPos (GDK_WINDOW_HWND (window), HWND_BOTTOM, 0, 0, 0, 0,
+                   SWP_HIDEWINDOW | SWP_NOREDRAW | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
     }
   else
     {
@@ -1209,6 +1308,12 @@ gdk_window_reparent (GdkWindow *window,
   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
 
+  if (GDK_WINDOW_DESTROYED (window) ||
+      (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
+    {
+      return;
+    }
+
   if (!new_parent)
     new_parent = _gdk_parent_root;
 
@@ -1609,8 +1714,8 @@ gdk_window_set_transient_for (GdkWindow *window,
 }
 
 void
-gdk_window_set_background (GdkWindow *window,
-                          GdkColor  *color)
+gdk_window_set_background (GdkWindow      *window,
+                          const GdkColor *color)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   
@@ -2151,121 +2256,316 @@ gdk_window_set_override_redirect (GdkWindow *window,
   g_warning ("gdk_window_set_override_redirect not implemented");
 }
 
-void          
-gdk_window_set_icon_list (GdkWindow *window,
-                         GList     *pixbufs)
+void
+gdk_window_set_accept_focus (GdkWindow *window,
+                            gboolean accept_focus)
 {
+  GdkWindowObject *private;
+  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
+  private = (GdkWindowObject *)window;  
+  
+  accept_focus = accept_focus != FALSE;
 
-  /* We could convert it to a hIcon and DrawIcon () it when getting
-   * a WM_PAINT with IsIconic, but is it worth it ? Same probably
-   * goes for gdk_window_set_icon (). Patches accepted :-)  --hb
-   * Or do we only need to deliver the Icon on WM_GETICON ?
+  if (private->accept_focus != accept_focus)
+    private->accept_focus = accept_focus;
+}
+
+void
+gdk_window_set_focus_on_map (GdkWindow *window,
+                            gboolean focus_on_map)
+{
+  GdkWindowObject *private;
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *)window;  
+  
+  focus_on_map = focus_on_map != FALSE;
+
+  if (private->focus_on_map != focus_on_map)
+    private->focus_on_map = focus_on_map;
+}
+
+static HICON
+pixbuf_to_hicon_alpha_winxp (GdkWindow *window,
+                            GdkPixbuf *pixbuf)
+{
+  /* Based on code from
+   * http://www.dotnet247.com/247reference/msgs/13/66301.aspx
    */
+  HDC hdc;
+  BITMAPV5HEADER bi;
+  HBITMAP hBitmap, hMonoBitmap;
+  guchar *indata, *inrow;
+  guchar *outdata, *outrow;
+  HICON hAlphaIcon = NULL;
+  ICONINFO ii;
+  gint width, height, i, j, rowstride;
+
+  if (pixbuf == NULL)
+    return NULL;
+
+  width = gdk_pixbuf_get_width (pixbuf); /* width of icon */
+  height = gdk_pixbuf_get_height (pixbuf); /* height of icon */
+
+  ZeroMemory (&bi, sizeof (BITMAPV5HEADER));
+  bi.bV5Size = sizeof (BITMAPV5HEADER);
+  bi.bV5Width = width;
+  bi.bV5Height = height;
+  bi.bV5Planes = 1;
+  bi.bV5BitCount = 32;
+  bi.bV5Compression = BI_BITFIELDS;
+  /* The following mask specification specifies a supported 32 BPP
+   * alpha format for Windows XP (BGRA format).
+   */
+  bi.bV5RedMask   = 0x00FF0000;
+  bi.bV5GreenMask = 0x0000FF00;
+  bi.bV5BlueMask  = 0x000000FF;
+  bi.bV5AlphaMask = 0xFF000000;
+
+  /* Create the DIB section with an alpha channel. */
+  hdc = GetDC (NULL);
+  hBitmap = CreateDIBSection (hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS,
+                             (void **)&outdata, NULL, (DWORD)0);
+  ReleaseDC (NULL, hdc);
+
+  /* Draw something on the DIB section */
+  indata = gdk_pixbuf_get_pixels (pixbuf);
+  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+  for (j=0; j<height; j++)
+    {
+      outrow = outdata + 4*j*width;
+      inrow  = indata  + (height-j-1)*rowstride;
+      for (i=0; i<width; i++)
+       {
+         outrow[4*i+0] = inrow[4*i+2];
+         outrow[4*i+1] = inrow[4*i+1];
+         outrow[4*i+2] = inrow[4*i+0];
+         outrow[4*i+3] = inrow[4*i+3];
+       }
+    }
+
+  /* Create an empty mask bitmap */
+  hMonoBitmap = CreateBitmap (width, height, 1, 1, NULL);
+
+  ii.fIcon = TRUE;
+  ii.xHotspot = 0;
+  ii.yHotspot = 0;
+  ii.hbmMask = hMonoBitmap;
+  ii.hbmColor = hBitmap;
+
+  /* Create the alpha cursor with the alpha DIB section */
+  hAlphaIcon = CreateIconIndirect (&ii);
+
+  GDI_CALL (DeleteObject, (hBitmap));
+  GDI_CALL (DeleteObject, (hMonoBitmap));
+
+  return hAlphaIcon;
 }
 
-void          
-gdk_window_set_icon (GdkWindow *window, 
-                    GdkWindow *icon_window,
-                    GdkPixmap *pixmap,
-                    GdkBitmap *mask)
+static HICON
+pixbuf_to_hicon_normal (GdkWindow *window,
+                       GdkPixbuf *pixbuf)
 {
+  GdkPixmap *pixmap;
+  GdkBitmap *mask;
+  HBITMAP hbmmask = NULL;
   ICONINFO ii;
   HICON hIcon;
   gint w = 0, h = 0;
-  GdkWindowImplWin32 *impl;
-
-  g_return_if_fail (window != NULL);
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
 
-  impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
+  if (pixbuf == NULL)
+    return NULL;
 
-  if (pixmap)
-    {
-      static int num = 0;
-      HBITMAP hbmmask = NULL;
+  /* create a normal icon with a bitmap mask */
+  w = gdk_pixbuf_get_width (pixbuf);
+  h = gdk_pixbuf_get_height (pixbuf);
+  gdk_pixbuf_render_pixmap_and_mask_for_colormap (pixbuf, 
+                                                 gdk_drawable_get_colormap (window),
+                                                 &pixmap,
+                                                 &mask,
+                                                 128);
 
-      gdk_drawable_get_size (GDK_DRAWABLE(pixmap), &w, &h);
+  /* we need the inverted mask for the XOR op */
+  {
+    HDC hdc1 = CreateCompatibleDC (NULL);
+    HBITMAP hbmold1;
 
-      /* we need the inverted mask for the XOR op */
+    hbmmask = CreateCompatibleBitmap (hdc1, w, h);
+    hbmold1 = SelectObject (hdc1, hbmmask);
+    if (mask)
       {
-        HDC hdc1 = CreateCompatibleDC (NULL);
-        HBITMAP hbmold1;
-
-        hbmmask = CreateCompatibleBitmap (hdc1, w, h);
-        hbmold1 = SelectObject (hdc1, hbmmask);
-        if (mask)
-          {
-            HDC hdc2 = CreateCompatibleDC (NULL);
-            HBITMAP hbmold2 = SelectObject (hdc2, GDK_PIXMAP_HBITMAP (mask));
-            GDI_CALL (BitBlt, (hdc1, 0,0,w,h, hdc2, 0,0, NOTSRCCOPY));
-            GDI_CALL (SelectObject, (hdc2, hbmold2));
-            GDI_CALL (DeleteDC, (hdc2));
-          }
-        else
-          {
-            RECT rect;
-            GetClipBox (hdc1, &rect);
-            GDI_CALL (FillRect, (hdc1, &rect, GetStockObject (WHITE_BRUSH)));
-          }
-        GDI_CALL (SelectObject, (hdc1, hbmold1));
-        GDI_CALL (DeleteDC, (hdc1));
+       HDC hdc2 = CreateCompatibleDC (NULL);
+       HBITMAP hbmold2 = SelectObject (hdc2, GDK_PIXMAP_HBITMAP (mask));
+       GDI_CALL (BitBlt, (hdc1, 0,0,w,h, hdc2, 0,0, NOTSRCCOPY));
+       GDI_CALL (SelectObject, (hdc2, hbmold2));
+       GDI_CALL (DeleteDC, (hdc2));
       }
+    else
+      {
+       RECT rect;
+       GetClipBox (hdc1, &rect);
+       GDI_CALL (FillRect, (hdc1, &rect, GetStockObject (BLACK_BRUSH)));
+      }
+    GDI_CALL (SelectObject, (hdc1, hbmold1));
+    GDI_CALL (DeleteDC, (hdc1));
+  }
+
+  ii.fIcon = TRUE;
+  ii.xHotspot = ii.yHotspot = 0; /* ignored for icons */
+  ii.hbmMask = hbmmask;
+  ii.hbmColor = GDK_PIXMAP_HBITMAP (pixmap);
+  hIcon = CreateIconIndirect (&ii);
+  if (!hIcon)
+    WIN32_API_FAILED ("CreateIconIndirect");
+  GDI_CALL (DeleteObject, (hbmmask));
 
-      ii.fIcon = TRUE;
-      ii.xHotspot = ii.yHotspot = 0; /* ignored for icons */
-      ii.hbmMask = hbmmask;
-      ii.hbmColor = GDK_PIXMAP_HBITMAP (pixmap); 
-      hIcon = CreateIconIndirect (&ii);
-      if (!hIcon)
-        WIN32_API_FAILED ("CreateIconIndirect");
-      GDI_CALL (DeleteObject, (hbmmask));
 #if 0 /* to debug pixmap and mask setting */
+  {
+    static int num = 0;
+    GdkPixbuf* pixbuf = NULL;
+    char name[256];
+
+    pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0, w, h);
+    if (pixbuf)
       {
-        GdkPixbuf* pixbuf = NULL;
-        char name[256];
-
-        pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0, w, h);
-       if (pixbuf)
-          {
-            num = (num + 1) % 999; /* restrict maximim number */
-            sprintf (name, "c:\\temp\\ico%03dpixm.png", num); 
-            gdk_pixbuf_save (pixbuf, name, "png", NULL, NULL);
-            gdk_pixbuf_unref (pixbuf);
-          }
-        pixbuf = !mask ? NULL : gdk_pixbuf_get_from_drawable (NULL, mask, NULL, 0, 0, 0, 0, w, h);
-       if (pixbuf)
-          {
-            sprintf (name, "c:\\temp\\ico%03dmask.png", num); 
-            gdk_pixbuf_save (pixbuf, name, "png", NULL, NULL);
-            gdk_pixbuf_unref (pixbuf);
-          }
+       num = (num + 1) % 999; /* restrict maximim number */
+       sprintf (name, "c:\\temp\\ico%03dpixm.png", num); 
+       gdk_pixbuf_save (pixbuf, name, "png", NULL, NULL);
+       gdk_pixbuf_unref (pixbuf);
       }
+  }
 #endif
 
-      SendMessage (GDK_WINDOW_HWND (window), WM_SETICON, ICON_BIG, (LPARAM)hIcon);
-      if (impl->hicon)
-        GDI_CALL (DestroyIcon, (impl->hicon));
-      impl->hicon = hIcon;
+  if (pixmap)
+    g_object_unref (G_OBJECT (pixmap));
+  if (mask)
+    g_object_unref (G_OBJECT (mask));
+
+  return hIcon;
+}
+
+static HICON
+pixbuf_to_hicon (GdkWindow *window,
+                GdkPixbuf *pixbuf)
+{
+  static gboolean is_win_xp=FALSE, is_win_xp_checked=FALSE;
+
+  if (!is_win_xp_checked)
+    {
+      OSVERSIONINFO version;
+
+      is_win_xp_checked = TRUE;
+      memset (&version, 0, sizeof (version));
+      version.dwOSVersionInfoSize = sizeof (version);
+      is_win_xp = GetVersionEx (&version)
+       && version.dwPlatformId == VER_PLATFORM_WIN32_NT
+       && (version.dwMajorVersion > 5
+           || (version.dwMajorVersion == 5 && version.dwMinorVersion >= 1));
     }
+
+  if (pixbuf == NULL)
+    return NULL;
+
+  if (is_win_xp && gdk_pixbuf_get_has_alpha (pixbuf))
+    return pixbuf_to_hicon_alpha_winxp (window, pixbuf);
   else
-    {
-      /* reseting to default icon */
-      if (impl->hicon)
-        {
-          SendMessage (GDK_WINDOW_HWND (window), WM_SETICON, ICON_BIG, 0);
-          GDI_CALL (DestroyIcon, (impl->hicon));
-          impl->hicon = NULL;
-        }
+    return pixbuf_to_hicon_normal (window, pixbuf);
+}
+
+void          
+gdk_window_set_icon_list (GdkWindow *window,
+                         GList     *pixbufs)
+{
+  GdkPixbuf *pixbuf, *big_pixbuf, *small_pixbuf;
+  gint big_diff, small_diff;
+  gint big_w, big_h, small_w, small_h;
+  gint w, h;
+  gint dw, dh, diff;
+  HICON small_hicon, big_hicon;
+  GdkWindowImplWin32 *impl;
+  gint i, big_i, small_i;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
+
+  /* ideal sizes for small and large icons */
+  big_w = GetSystemMetrics (SM_CXICON);
+  big_h = GetSystemMetrics (SM_CYICON);
+  small_w = GetSystemMetrics (SM_CXSMICON);
+  small_h = GetSystemMetrics (SM_CYSMICON);
+
+  /* find closest sized icons in the list */
+  big_pixbuf = NULL;
+  small_pixbuf = NULL;
+  big_diff = 0;
+  small_diff = 0;
+  i = 0;
+  while (pixbufs)
+    {
+      pixbuf = (GdkPixbuf*) pixbufs->data;
+      w = gdk_pixbuf_get_width (pixbuf);
+      h = gdk_pixbuf_get_height (pixbuf);
+
+      dw = ABS (w - big_w);
+      dh = ABS (h - big_h);
+      diff = dw*dw + dh*dh;
+      if (big_pixbuf == NULL || diff < big_diff)
+       {
+         big_pixbuf = pixbuf;
+         big_diff = diff;
+         big_i = i;
+       }
+
+      dw = ABS(w - small_w);
+      dh = ABS(h - small_h);
+      diff = dw*dw + dh*dh;
+      if (small_pixbuf == NULL || diff < small_diff)
+       {
+         small_pixbuf = pixbuf;
+         small_diff = diff;
+         small_i = i;
+       }
+
+      pixbufs = g_list_next (pixbufs);
+      i++;
     }
 
-  GDK_NOTE (MISC, g_print ("gdk_window_set_icon: %p: %p %dx%d\n", GDK_WINDOW_HWND (window), impl->hicon, w, h));
+  /* Create the icons */
+  big_hicon = pixbuf_to_hicon (window, big_pixbuf);
+  small_hicon = pixbuf_to_hicon (window, small_pixbuf);
+
+  /* Set the icons */
+  SendMessage (GDK_WINDOW_HWND (window), WM_SETICON, ICON_BIG,
+              (LPARAM)big_hicon);
+  SendMessage (GDK_WINDOW_HWND (window), WM_SETICON, ICON_SMALL,
+              (LPARAM)small_hicon);
+
+  /* Store the icons, destroying any previous icons */
+  if (impl->hicon_big)
+    GDI_CALL (DestroyIcon, (impl->hicon_big));
+  impl->hicon_big = big_hicon;
+  if (impl->hicon_small)
+    GDI_CALL (DestroyIcon, (impl->hicon_small));
+  impl->hicon_small = small_hicon;
+}
+
+void          
+gdk_window_set_icon (GdkWindow *window, 
+                    GdkWindow *icon_window,
+                    GdkPixmap *pixmap,
+                    GdkBitmap *mask)
+{
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  /* do nothing, use gdk_window_set_icon_list instead */
 }
 
 void
@@ -2281,6 +2581,20 @@ gdk_window_set_icon_name (GdkWindow   *window,
   API_CALL (SetWindowText, (GDK_WINDOW_HWND (window), name));
 }
 
+GdkWindow *
+gdk_window_get_group (GdkWindow *window)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+  g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return NULL;
+  
+  g_warning ("gdk_window_get_group not yet implemented");
+
+  return NULL;
+}
+
 void          
 gdk_window_set_group (GdkWindow *window, 
                      GdkWindow *leader)
@@ -2528,6 +2842,38 @@ gdk_window_set_static_gravities (GdkWindow *window,
   return TRUE;
 }
 
+void
+gdk_window_begin_resize_drag (GdkWindow     *window,
+                              GdkWindowEdge  edge,
+                              gint           button,
+                              gint           root_x,
+                              gint           root_y,
+                              guint32        timestamp)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  /* XXX: isn't all this default on win32 ... */  
+}
+
+void
+gdk_window_begin_move_drag (GdkWindow *window,
+                            gint       button,
+                            gint       root_x,
+                            gint       root_y,
+                            guint32    timestamp)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  /* XXX: isn't all this default on win32 ... */  
+}
+
+
 /*
  * Setting window states
  */
@@ -2732,7 +3078,7 @@ gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
   if (GDK_WINDOW_IS_MAPPED (window))
     {
       if (!SetWindowPos(GDK_WINDOW_HWND (window), setting ? HWND_TOPMOST : HWND_NOTOPMOST,
-                        0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE))
+                        0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE))
          WIN32_API_FAILED ("SetWindowPos");
     }
   else
@@ -2752,7 +3098,7 @@ gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
   if (GDK_WINDOW_IS_MAPPED (window))
     {
       if (!SetWindowPos(GDK_WINDOW_HWND (window), setting ? HWND_BOTTOM : HWND_NOTOPMOST,
-                        0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE))
+                        0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE))
          WIN32_API_FAILED ("SetWindowPos");
     }
   else
@@ -2807,7 +3153,8 @@ void
 gdk_window_set_skip_taskbar_hint (GdkWindow *window,
                                  gboolean   skips_taskbar)
 {
-  LONG extended_style;
+  static GdkWindow *owner = NULL;
+  GdkWindowAttr wa;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -2815,14 +3162,32 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
                           GDK_WINDOW_HWND (window),
                           skips_taskbar ? "TRUE" : "FALSE"));
 
-  extended_style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
-
   if (skips_taskbar)
-    extended_style |= WS_EX_TOOLWINDOW;
-  else
-    extended_style &= ~WS_EX_TOOLWINDOW;
+    {
+      if (owner == NULL)
+       {
+         wa.window_type = GDK_WINDOW_TEMP;
+         wa.wclass = GDK_INPUT_OUTPUT;
+         wa.width = wa.height = 1;
+         wa.event_mask = 0;
+         owner = gdk_window_new_internal (NULL, &wa, 0, TRUE);
+       }
+
+      SetWindowLong (GDK_WINDOW_HWND (window), GWL_HWNDPARENT,
+                    (long) GDK_WINDOW_HWND (owner));
 
-  SetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE, extended_style);
+#if 0 /* Should we also turn off the minimize and maximize buttons? */
+      SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE,
+                    GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE) & ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU));
+      SetWindowPos (GDK_WINDOW_HWND (window), NULL, 0, 0, 0, 0,
+                   SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
+                   SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
+#endif
+    }
+  else
+    {
+      SetWindowLong (GDK_WINDOW_HWND (window), GWL_HWNDPARENT, 0);
+    }
 }
 
 void
@@ -2861,6 +3226,12 @@ gdk_window_set_type_hint (GdkWindow        *window,
     case GDK_WINDOW_TYPE_HINT_UTILITY:
       break;
     case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
+      gdk_window_set_decorations (window,
+                                 GDK_DECOR_ALL |
+                                 GDK_DECOR_RESIZEH |
+                                 GDK_DECOR_MENU |
+                                 GDK_DECOR_MINIMIZE |
+                                 GDK_DECOR_MAXIMIZE);
       break;
     case GDK_WINDOW_TYPE_HINT_DOCK:
       break;
@@ -2888,41 +3259,20 @@ gdk_window_shape_combine_region (GdkWindow *window,
   /* XXX: even on X implemented conditional ... */  
 }
 
-void
-gdk_window_begin_resize_drag (GdkWindow     *window,
-                              GdkWindowEdge  edge,
-                              gint           button,
-                              gint           root_x,
-                              gint           root_y,
-                              guint32        timestamp)
+GdkWindow *
+gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
+  g_return_val_if_fail (display == gdk_display_get_default(), NULL);
 
-  /* XXX: isn't all this default on win32 ... */  
+  return gdk_window_lookup (anid);
 }
 
 void
-gdk_window_begin_move_drag (GdkWindow *window,
-                            gint       button,
-                            gint       root_x,
-                            gint       root_y,
-                            guint32    timestamp)
+gdk_window_enable_synchronized_configure (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-
-  /* XXX: isn't all this default on win32 ... */  
 }
 
-GdkWindow *
-gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
+void
+gdk_window_configure_finished (GdkWindow *window)
 {
-  g_return_val_if_fail (display == gdk_display_get_default(), NULL);
-
-  return gdk_window_lookup (anid);
 }