xserver: Branch 'master' - 11 commits

Keith Packard keithp at kemper.freedesktop.org
Mon Aug 6 15:11:47 PDT 2012


 glx/extension_string.c           |    2 
 glx/glxscreens.c                 |    2 
 hw/xwin/glx/indirect.c           |   70 ++++--
 hw/xwin/win.h                    |    9 
 hw/xwin/winclipboardwndproc.c    |   29 ++
 hw/xwin/winmultiwindowicons.c    |  392 +++++++++++++++++++--------------------
 hw/xwin/winmultiwindowicons.h    |   42 ++++
 hw/xwin/winmultiwindowwindow.c   |   18 -
 hw/xwin/winmultiwindowwm.c       |  202 ++++++++++++--------
 hw/xwin/winprefs.c               |   48 +---
 hw/xwin/winprefs.h               |    2 
 hw/xwin/winwin32rootless.c       |    2 
 hw/xwin/winwin32rootlesswindow.c |   31 ---
 hw/xwin/winwindow.h              |   15 -
 hw/xwin/winwindowswm.c           |    2 
 os/utils.c                       |    2 
 16 files changed, 462 insertions(+), 406 deletions(-)

New commits:
commit 7d87545ba7395ade507cca7bdca7052b26ed18d8
Merge: ad707a7... 988d7ac...
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Aug 6 15:11:13 2012 -0700

    Merge remote-tracking branch 'jturney/master'

commit 988d7ace19a009991a4528e783d1a94c2444c66a
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Thu Jul 5 09:38:44 2012 +0100

    glx: Do not report the GLX_INTEL_swap_event extension for indirect swrast
    
    Commit 84956ca4 bogusly adds GLX_INTEL_swap_event to the extensions reported
    by swrast.
    
    "DRI2 supports this now - and already enables it explicitly - but drisw does
    not and should not. Otherwise toolkits like clutter will only ever SwapBuffers
    once and wait forever for an event that's not coming."
    
    (A similar bug for direct swrast is already fixed in mesa commit 25620eb1)
    
    (Note that this may be papering over the cracks somewhat, as if we do report
    GLX_INTEL_swap_event, some clutter apps fail with GLXBadDrawable calling
    GLXChangeDrawableAttributes to change the setting of GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK
    in the GLX_EVENT_MASK, apparently after the drawable is destroyed, which suggests
    a bug with GLXDrawable lifetimes)
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Jeremy Huddleston Sequoia <jeremyhu at apple.com>

diff --git a/glx/glxscreens.c b/glx/glxscreens.c
index 386987e..037b037 100644
--- a/glx/glxscreens.c
+++ b/glx/glxscreens.c
@@ -174,7 +174,7 @@ static char GLXServerExtensions[] =
     "GLX_SGIS_multisample "
 #endif
     "GLX_SGIX_fbconfig "
-    "GLX_SGIX_pbuffer " "GLX_MESA_copy_sub_buffer " "GLX_INTEL_swap_event";
+    "GLX_SGIX_pbuffer " "GLX_MESA_copy_sub_buffer ";
 
 static Bool
 glxCloseScreen(ScreenPtr pScreen)
commit fd3d45c137bb849aa9030d732ea9277292e01d3d
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Thu Jul 5 09:34:24 2012 +0100

    glx: Don't note GLX_INTEL_swap_event as being required by GLX 1.4, it isn't.
    
    Don't note GLX_INTEL_swap_event as being required by GLX 1.4, it isn't.
    (This data is not currently used in the server)
    
    (A similar change is made in mesa commit d3f7597bc9f6d5)
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Jeremy Huddleston Sequoia <jeremyhu at apple.com>

diff --git a/glx/extension_string.c b/glx/extension_string.c
index ee9864e..544ca1f 100644
--- a/glx/extension_string.c
+++ b/glx/extension_string.c
@@ -87,7 +87,7 @@ static const struct extension_info known_glx_extensions[] = {
     { GLX(SGIX_fbconfig),               VER(1,3), Y, },
     { GLX(SGIX_pbuffer),                VER(1,3), Y, },
     { GLX(SGIX_visual_select_group),    VER(0,0), Y, },
-    { GLX(INTEL_swap_event),            VER(1,4), N, },
+    { GLX(INTEL_swap_event),            VER(0,0), N, },
     { NULL }
     /* *INDENT-ON* */
 };
commit a8464dfa28dea78201e3e4398eb3bcb745e10087
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Sun Jul 22 13:15:02 2012 +0100

    os: Fix TMP fall-back in Win32TempDir()
    
    Fix Win32TempDir() in the case where we fell back to checking the TMP
    environment variable. It looks like this has been wrong since forever.
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/os/utils.c b/os/utils.c
index d902523..cdf5fd8 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -1583,7 +1583,7 @@ Win32TempDir()
     if (getenv("TEMP") != NULL)
         return getenv("TEMP");
     else if (getenv("TMP") != NULL)
-        return getenv("TEMP");
+        return getenv("TMP");
     else
         return "/tmp";
 }
commit f6e7b82acadfca8239edc0f7e72cd0f3f9cfc2c4
Author: Marc Haesen <marha at users.sourceforge.net>
Date:   Sat Jul 21 21:18:44 2012 +0100

    hw/xwin: Fixes to pixelFormat <-> fbConfig conversion in WGL mode
    
    Fix FIXME in fbConfigToPixelFormat() to correctly populate RGBA-mask shift
    parameters.  Also request colourindex pixelFormats correctly.
    
    Now that they are requested correctly, don't skip colorindex visuals when
    converting pixelFormats to fbConfigs.
    
    Populate transparent colour information when converting pixelFormat from
    DescribePixelFormats() to a fbConfig.
    
    Signed-off-by: Marc Haesen <marha at users.sourceforge.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/glx/indirect.c b/hw/xwin/glx/indirect.c
index 3f34146..97b6045 100644
--- a/hw/xwin/glx/indirect.c
+++ b/hw/xwin/glx/indirect.c
@@ -1626,6 +1626,18 @@ glxWinCreateContext(__GLXscreen * screen,
  */
 
 static int
+GetShift(int Mask)
+{
+    int Shift = 0;
+
+    while ((Mask &1) == 0) {
+        Shift++;
+        Mask >>=1;
+    }
+    return Shift;
+}
+
+static int
 fbConfigToPixelFormat(__GLXconfig * mode, PIXELFORMATDESCRIPTOR * pfdret,
                       int drawableTypeOverride)
 {
@@ -1661,16 +1673,26 @@ fbConfigToPixelFormat(__GLXconfig * mode, PIXELFORMATDESCRIPTOR * pfdret,
         pfd.dwFlags |= PFD_DOUBLEBUFFER;
     }
 
-    pfd.iPixelType = PFD_TYPE_RGBA;
     pfd.cColorBits = mode->redBits + mode->greenBits + mode->blueBits;
     pfd.cRedBits = mode->redBits;
-    pfd.cRedShift = 0;          /* FIXME */
+    pfd.cRedShift = GetShift(mode->redMask);
     pfd.cGreenBits = mode->greenBits;
-    pfd.cGreenShift = 0;        /* FIXME  */
+    pfd.cGreenShift = GetShift(mode->greenMask);
     pfd.cBlueBits = mode->blueBits;
-    pfd.cBlueShift = 0;         /* FIXME */
+    pfd.cBlueShift = GetShift(mode->blueMask);
     pfd.cAlphaBits = mode->alphaBits;
-    pfd.cAlphaShift = 0;        /* FIXME */
+    pfd.cAlphaShift = GetShift(mode->alphaMask);
+
+    if (mode->visualType == GLX_TRUE_COLOR) {
+        pfd.iPixelType = PFD_TYPE_RGBA;
+        pfd.dwVisibleMask =
+            (pfd.cRedBits << pfd.cRedShift) | (pfd.cGreenBits << pfd.cGreenShift) |
+            (pfd.cBlueBits << pfd.cBlueShift) | (pfd.cAlphaBits << pfd.cAlphaShift);
+    }
+    else {
+        pfd.iPixelType = PFD_TYPE_COLORINDEX;
+        pfd.dwVisibleMask = mode->transparentIndex;
+    }
 
     pfd.cAccumBits =
         mode->accumRedBits + mode->accumGreenBits + mode->accumBlueBits +
@@ -1910,25 +1932,27 @@ glxWinCreateConfigs(HDC hdc, glxWinScreen * screen)
         /* EXT_visual_info / GLX 1.2 */
         if (pfd.iPixelType == PFD_TYPE_COLORINDEX) {
             c->base.visualType = GLX_STATIC_COLOR;
-
-            if (!getenv("GLWIN_ENABLE_COLORINDEX_FBCONFIGS")) {
-                GLWIN_DEBUG_MSG
-                    ("pixelFormat %d is PFD_TYPE_COLORINDEX, skipping", i + 1);
-                continue;
-            }
+            c->base.transparentRed = GLX_NONE;
+            c->base.transparentGreen = GLX_NONE;
+            c->base.transparentBlue = GLX_NONE;
+            c->base.transparentAlpha = GLX_NONE;
+            c->base.transparentIndex = pfd.dwVisibleMask;
+            c->base.transparentPixel = GLX_TRANSPARENT_INDEX;
         }
         else {
             c->base.visualType = GLX_TRUE_COLOR;
+            c->base.transparentRed =
+                (pfd.dwVisibleMask & c->base.redMask) >> pfd.cRedShift;
+            c->base.transparentGreen =
+                (pfd.dwVisibleMask & c->base.greenMask) >> pfd.cGreenShift;
+            c->base.transparentBlue =
+                (pfd.dwVisibleMask & c->base.blueMask) >> pfd.cBlueShift;
+            c->base.transparentAlpha =
+                (pfd.dwVisibleMask & c->base.alphaMask) >> pfd.cAlphaShift;
+            c->base.transparentIndex = GLX_NONE;
+            c->base.transparentPixel = GLX_TRANSPARENT_RGB;
         }
 
-        // pfd.dwVisibleMask; ???
-        c->base.transparentPixel = GLX_NONE;
-        c->base.transparentRed = GLX_NONE;
-        c->base.transparentGreen = GLX_NONE;
-        c->base.transparentBlue = GLX_NONE;
-        c->base.transparentAlpha = GLX_NONE;
-        c->base.transparentIndex = GLX_NONE;
-
         /* ARB_multisample / SGIS_multisample */
         c->base.sampleBuffers = 0;
         c->base.samples = 0;
@@ -2180,14 +2204,6 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen)
             c->base.indexBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
             c->base.rgbBits = 0;
             c->base.visualType = GLX_STATIC_COLOR;
-
-            if (!getenv("GLWIN_ENABLE_COLORINDEX_FBCONFIGS")) {
-                GLWIN_DEBUG_MSG
-                    ("pixelFormat %d is WGL_TYPE_COLORINDEX_ARB, skipping",
-                     i + 1);
-                continue;
-            }
-
             break;
 
         case WGL_TYPE_RGBA_FLOAT_ARB:
commit 45c432871d6a244e9e558a6a4e7c36e90764135e
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Sat Jul 21 14:13:37 2012 +0100

    hw/xwin: Introduce winProcessXEventsTimeout() to the concept of fractions of a second
    
    Oh this is terrible.
    
    Currently we only compute the select timeout in whole seconds.  This means if we
    have less than 1 second remaining, we select with a timeout of 0 (i.e. poll)
    which causes the task to spin, burning 100% CPU for the remaining timeout (and
    possibly preventing the process we are waiting for from running :S)
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboardwndproc.c b/hw/xwin/winclipboardwndproc.c
index cbe6599..e19f678 100644
--- a/hw/xwin/winclipboardwndproc.c
+++ b/hw/xwin/winclipboardwndproc.c
@@ -74,10 +74,10 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
     int iConnNumber;
     struct timeval tv;
     int iReturn;
-    DWORD dwStopTime = (GetTickCount() / 1000) + iTimeoutSec;
+    DWORD dwStopTime = GetTickCount() + iTimeoutSec * 1000;
 
-    /* We need to ensure that all pending events are processed */
-    XSync(pDisplay, FALSE);
+    winDebug("winProcessXEventsTimeout () - pumping X events for %d seconds\n",
+             iTimeoutSec);
 
     /* Get our connection number */
     iConnNumber = ConnectionNumber(pDisplay);
@@ -85,17 +85,24 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
     /* Loop for X events */
     while (1) {
         fd_set fdsRead;
+        long remainingTime;
+
+        /* We need to ensure that all pending events are processed */
+        XSync(pDisplay, FALSE);
 
         /* Setup the file descriptor set */
         FD_ZERO(&fdsRead);
         FD_SET(iConnNumber, &fdsRead);
 
         /* Adjust timeout */
-        tv.tv_sec = dwStopTime - (GetTickCount() / 1000);
-        tv.tv_usec = 0;
+        remainingTime = dwStopTime - GetTickCount();
+        tv.tv_sec = remainingTime / 1000;
+        tv.tv_usec = (remainingTime % 1000) * 1000;
+        winDebug("winProcessXEventsTimeout () - %d milliseconds left\n",
+                 remainingTime);
 
         /* Break out if no time left */
-        if (tv.tv_sec < 0)
+        if (remainingTime <= 0)
             return WIN_XEVENTS_SUCCESS;
 
         /* Wait for an X event */
@@ -103,7 +110,7 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
                          &fdsRead,      /* Read mask */
                          NULL,  /* No write mask */
                          NULL,  /* No exception mask */
-                         &tv);  /* No timeout */
+                         &tv);  /* Timeout */
         if (iReturn < 0) {
             ErrorF("winProcessXEventsTimeout - Call to select () failed: %d.  "
                    "Bailing.\n", iReturn);
@@ -116,11 +123,19 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
             /* Exit when we see that server is shutting down */
             iReturn = winClipboardFlushXEvents(hwnd,
                                                iWindow, pDisplay, fUseUnicode);
+
+            winDebug
+                ("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n",
+                 iReturn);
+
             if (WIN_XEVENTS_NOTIFY == iReturn) {
                 /* Bail out if notify processed */
                 return iReturn;
             }
         }
+        else {
+            winDebug("winProcessXEventsTimeout - Spurious wake\n");
+        }
     }
 
     return WIN_XEVENTS_SUCCESS;
commit 23cd4d0174194e10721d2e465fd1a1c52f001520
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Sat Jul 21 12:33:05 2012 +0100

    hw/xwin: Fix winUpdateWindowPosition() not to assume WS_EX_APPWINDOW style
    
    Also improve it's debug output a bit
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index 82c32aa..ffb7c2d 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -1743,13 +1743,11 @@ winUpdateWindowPosition(HWND hWnd, Bool reshape, HWND * zstyle)
     /* Setup a rectangle with the X window position and size */
     SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight);
 
-#if 0
-    ErrorF("winUpdateWindowPosition - (%d, %d)-(%d, %d)\n",
-           rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
-#endif
+    winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n",
+             rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
 
     AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE,
-                       WS_EX_APPWINDOW);
+                       GetWindowLongPtr(hWnd, GWL_EXSTYLE));
 
     /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */
     if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) {
@@ -1764,10 +1762,8 @@ winUpdateWindowPosition(HWND hWnd, Bool reshape, HWND * zstyle)
         rcNew.bottom += iDy;
     }
 
-#if 0
-    ErrorF("winUpdateWindowPosition - (%d, %d)-(%d, %d)\n",
-           rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
-#endif
+    winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n",
+             rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
 
     /* Position the Windows window */
     SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top,
commit 527cf13135cfd279733060e0028bbfbe02be5167
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Sat Jul 21 14:09:16 2012 +0100

    hw/xwin: Make winOverrideIcon() thread-safe for icon data access
    
    winOverrideIcon() is called from the internal WM client thread.
    
    Accessing server-internal data structures to get icon data or window hints is
    not safe, as there is no lock to ensure we do not collide with these data
    structures being updated in the server thread.
    
    Rewrite so the internal client thread uses X client calls to obtain this data
    safely
    
    We used to also set the icon inside the server when the window was initially
    created.  For simplicity, we simply send a message to the internal WM to update
    the icon when the window is created (rather than writing different icon update
    code which can work in the server thread for that one case...)
    
    extwm mode used to do the icon update in the server. I'm not sure that actually
    made much sense.  Let's assume the external WM client can do it instead...
    
    v2
    Make sure that WM_WM_ICON_EVENT does nothing for override-redirect windows
    
    v3
    Reinstate check that native window actually has expected properties for an X
    window before trying to update it's icon; some auxiliary windows owned by the
    XWin process don't, which would cause a crash
    
    v4
    Various fixes to pixmap icon conversion:
    - remove left-over malloc in winScaleXimageToWindowsIcon causing a memory leak
    - don't recalculate DDBitmap stride in winScaleXimageToWindowsIcon, when we already have worked it out
    - properly check that XGetWindowProperty(NET_WM_ICON) returned some data
    - don't try to retrieve WM_HINTS icon_mask if it isn't set
    - restore accidentally dropped calculation of effBpp, stride, maskStride of output DDBitmap
    - make sure imageMask is zero-initalized before we use it to mask the DDBitmap
    
    v5
    Remove a left-over unused variable
    
    v6
    Avoid XDestroyImage(NULL) crash if XGetImage failed for icon_pixmap
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/win.h b/hw/xwin/win.h
index 38d6bde..89e2a38 100644
--- a/hw/xwin/win.h
+++ b/hw/xwin/win.h
@@ -1174,15 +1174,6 @@ Bool
 void
  winSetShapeRootless(WindowPtr pWindow, int kind);
 
-/*
- * winmultiwindowicons.c - Used by both multi-window and Win32Rootless
- */
-
-HICON winXIconToHICON(WindowPtr pWin, int iconSize);
-
-void
- winSelectIcons(WindowPtr pWin, HICON * pIcon, HICON * pSmallIcon);
-
 #ifdef XWIN_MULTIWINDOW
 /*
  * winmultiwindowshape.c
diff --git a/hw/xwin/winmultiwindowicons.c b/hw/xwin/winmultiwindowicons.c
index df59f60..b8357e7 100644
--- a/hw/xwin/winmultiwindowicons.c
+++ b/hw/xwin/winmultiwindowicons.c
@@ -31,75 +31,65 @@
 #ifdef HAVE_XWIN_CONFIG_H
 #include <xwin-config.h>
 #endif
-#include "win.h"
-#include "dixevents.h"
-#include "winmultiwindowclass.h"
-#include "winprefs.h"
 
-#include "propertyst.h"
-#include "windowstr.h"
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
+
+#include <X11/Xwindows.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
 
+#include "winresource.h"
+#include "winprefs.h"
+#include "winmsg.h"
+#include "winmultiwindowicons.h"
+#include "winglobals.h"
 /*
- * Prototypes for local functions
+ * global variables
  */
-
-static void
-
-winScaleXBitmapToWindows(int iconSize, int effBPP,
-                         PixmapPtr pixmap, unsigned char *image);
+extern HINSTANCE g_hInstance;
 
 /*
- * Scale an X icon bitmap into a Windoze icon bitmap
+ * Scale an X icon ZPixmap into a Windoze icon bitmap
  */
 
 static void
-winScaleXBitmapToWindows(int iconSize,
-                         int effBPP, PixmapPtr pixmap, unsigned char *image)
+winScaleXImageToWindowsIcon(int iconSize,
+                            int effBPP,
+                            int stride, XImage * pixmap, unsigned char *image)
 {
     int row, column, effXBPP, effXDepth;
     unsigned char *outPtr;
-    char *iconData = 0;
-    int stride, xStride;
+    unsigned char *iconData = 0;
+    int xStride;
     float factX, factY;
     int posX, posY;
     unsigned char *ptr;
     unsigned int zero;
     unsigned int color;
 
-    effXBPP = BitsPerPixel(pixmap->drawable.depth);
-    effXDepth = pixmap->drawable.depth;
-
-    if (pixmap->drawable.bitsPerPixel == 15)
+    effXBPP = pixmap->bits_per_pixel;
+    if (pixmap->bits_per_pixel == 15)
         effXBPP = 16;
 
-    if (pixmap->drawable.depth == 15)
+    effXDepth = pixmap->depth;
+    if (pixmap->depth == 15)
         effXDepth = 16;
 
-    /* Need 16-bit aligned rows for DDBitmaps */
-    stride = ((iconSize * effBPP + 15) & (~15)) / 8;
-    xStride = PixmapBytePad(pixmap->drawable.width, pixmap->drawable.depth);
+    xStride = pixmap->bytes_per_line;
     if (stride == 0 || xStride == 0) {
         ErrorF("winScaleXBitmapToWindows - stride or xStride is zero.  "
                "Bailing.\n");
         return;
     }
 
-    /* Allocate memory for icon data */
-    iconData = malloc(xStride * pixmap->drawable.height);
-    if (!iconData) {
-        ErrorF("winScaleXBitmapToWindows - malloc failed for iconData.  "
-               "Bailing.\n");
-        return;
-    }
-
     /* Get icon data */
-    miGetImage((DrawablePtr) &(pixmap->drawable), 0, 0,
-               pixmap->drawable.width, pixmap->drawable.height,
-               ZPixmap, 0xffffffff, iconData);
+    iconData = (unsigned char *) pixmap->data;
 
     /* Keep aspect ratio */
-    factX = ((float) pixmap->drawable.width) / ((float) iconSize);
-    factY = ((float) pixmap->drawable.height) / ((float) iconSize);
+    factX = ((float) pixmap->width) / ((float) iconSize);
+    factY = ((float) pixmap->height) / ((float) iconSize);
     if (factX > factY)
         factY = factX;
     else
@@ -119,8 +109,7 @@ winScaleXBitmapToWindows(int iconSize,
                 ptr += posX / 8;
 
                 /* Out of X icon bounds, leave space blank */
-                if (posX >= pixmap->drawable.width
-                    || posY >= pixmap->drawable.height)
+                if (posX >= pixmap->width || posY >= pixmap->height)
                     ptr = (unsigned char *) &zero;
 
                 if ((*ptr) & (1 << (posX & 7)))
@@ -162,8 +151,7 @@ winScaleXBitmapToWindows(int iconSize,
                 ptr += posX * (effXBPP / 8);
 
                 /* Out of X icon bounds, leave space blank */
-                if (posX >= pixmap->drawable.width
-                    || posY >= pixmap->drawable.height)
+                if (posX >= pixmap->width || posY >= pixmap->height)
                     ptr = (unsigned char *) &zero;
                 color = (((*ptr) << 16)
                          + ((*(ptr + 1)) << 8)
@@ -203,8 +191,7 @@ winScaleXBitmapToWindows(int iconSize,
                 ptr += posX * (effXBPP / 8);
 
                 /* Out of X icon bounds, leave space blank */
-                if (posX >= pixmap->drawable.width
-                    || posY >= pixmap->drawable.height)
+                if (posX >= pixmap->width || posY >= pixmap->height)
                     ptr = (unsigned char *) &zero;
                 color = ((*ptr) << 8) + (*(ptr + 1));
                 switch (effBPP) {
@@ -238,7 +225,6 @@ winScaleXBitmapToWindows(int iconSize,
             }                   /* end if effxbpp==16) */
         }                       /* end for column */
     }                           /* end for row */
-    free(iconData);
 }
 
 static HICON
@@ -250,7 +236,7 @@ NetWMToWinIconAlpha(uint32_t * icon)
     HICON result;
     HDC hdc = GetDC(NULL);
     uint32_t *DIB_pixels;
-    ICONINFO ii = { TRUE };
+    ICONINFO ii;
     BITMAPV4HEADER bmh = { sizeof(bmh) };
 
     /* Define an ARGB pixel format used for Color+Alpha icons */
@@ -264,6 +250,9 @@ NetWMToWinIconAlpha(uint32_t * icon)
     bmh.bV4GreenMask = 0x0000FF00;
     bmh.bV4BlueMask = 0x000000FF;
 
+    ii.fIcon = TRUE;
+    ii.xHotspot = 0;            /* ignored */
+    ii.yHotspot = 0;            /* ignored */
     ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) & bmh,
                                    DIB_RGB_COLORS, (void **) &DIB_pixels, NULL,
                                    0);
@@ -291,12 +280,15 @@ NetWMToWinIconThreshold(uint32_t * icon)
     uint32_t *pixels = &icon[2];
     int row, col;
     HICON result;
-    ICONINFO ii = { TRUE };
+    ICONINFO ii;
 
     HDC hdc = GetDC(NULL);
     HDC xorDC = CreateCompatibleDC(hdc);
     HDC andDC = CreateCompatibleDC(hdc);
 
+    ii.fIcon = TRUE;
+    ii.xHotspot = 0;            /* ignored */
+    ii.yHotspot = 0;            /* ignored */
     ii.hbmColor = CreateCompatibleBitmap(hdc, width, height);
     ii.hbmMask = CreateCompatibleBitmap(hdc, width, height);
     ReleaseDC(NULL, hdc);
@@ -365,202 +357,220 @@ NetWMToWinIcon(int bpp, uint32_t * icon)
         return NetWMToWinIconThreshold(icon);
 }
 
-static pointer
-GetWindowProp(WindowPtr pWin, Atom name, long int *size_return)
-{
-    struct _Window *pwin;
-    struct _Property *prop;
-
-    if (!pWin || !name) {
-        ErrorF("GetWindowProp - pWin or name was NULL\n");
-        return 0;
-    }
-    pwin = (struct _Window *) pWin;
-    if (!pwin->optional)
-        return NULL;
-    for (prop = (struct _Property *) pwin->optional->userProps;
-         prop; prop = prop->next) {
-        if (prop->propertyName == name) {
-            *size_return = prop->size;
-            return prop->data;
-        }
-    }
-    return NULL;
-}
-
 /*
  * Attempt to create a custom icon from the WM_HINTS bitmaps
  */
 
-HICON
-winXIconToHICON(WindowPtr pWin, int iconSize)
+static
+ HICON
+winXIconToHICON(Display * pDisplay, Window id, int iconSize)
 {
-    unsigned char *mask, *image, *imageMask;
+    unsigned char *mask, *image = NULL, *imageMask;
     unsigned char *dst, *src;
-    PixmapPtr iconPtr;
-    PixmapPtr maskPtr;
-    int planes, bpp, effBPP, stride, maskStride, i;
+    int planes, bpp, i;
     int biggest_size = 0;
     HDC hDC;
     ICONINFO ii;
-    WinXWMHints hints;
+    XWMHints *hints;
     HICON hIcon = NULL;
     uint32_t *biggest_icon = NULL;
 
-    /* Try to get _NET_WM_ICON icons first */
     static Atom _XA_NET_WM_ICON;
     static int generation;
     uint32_t *icon, *icon_data = NULL;
-    long int size = 0;
+    unsigned long int size;
+    unsigned long int type;
+    int format;
+    unsigned long int left;
 
     hDC = GetDC(GetDesktopWindow());
     planes = GetDeviceCaps(hDC, PLANES);
     bpp = GetDeviceCaps(hDC, BITSPIXEL);
     ReleaseDC(GetDesktopWindow(), hDC);
 
+    /* Always prefer _NET_WM_ICON icons */
     if (generation != serverGeneration) {
         generation = serverGeneration;
-        _XA_NET_WM_ICON = MakeAtom("_NET_WM_ICON", 12, TRUE);
+        _XA_NET_WM_ICON = XInternAtom(pDisplay, "_NET_WM_ICON", FALSE);
     }
 
-    if (_XA_NET_WM_ICON)
-        icon_data = GetWindowProp(pWin, _XA_NET_WM_ICON, &size);
-    if (icon_data) {
-        for (icon = icon_data;
-             icon < &icon_data[size] && *icon;
+    if ((XGetWindowProperty(pDisplay, id, _XA_NET_WM_ICON,
+                            0, MAXINT, FALSE,
+                            AnyPropertyType, &type, &format, &size, &left,
+                            (unsigned char **) &icon_data) == Success) &&
+        (icon_data != NULL)) {
+        for (icon = icon_data; icon < &icon_data[size] && *icon;
              icon = &icon[icon[0] * icon[1] + 2]) {
-            if (icon[0] == iconSize && icon[1] == iconSize)
-                return NetWMToWinIcon(bpp, icon);
-            /* Find the biggest icon and let Windows scale the size */
+            /* Find an exact match to the size we require...  */
+            if (icon[0] == iconSize && icon[1] == iconSize) {
+                winDebug("winXIconToHICON: found %lu x %lu NetIcon\n", icon[0],
+                         icon[1]);
+                hIcon = NetWMToWinIcon(bpp, icon);
+                break;
+            }
+            /* Otherwise, find the biggest icon and let Windows scale the size */
             else if (biggest_size < icon[0]) {
                 biggest_icon = icon;
                 biggest_size = icon[0];
             }
         }
-        if (biggest_icon)
-            return NetWMToWinIcon(bpp, biggest_icon);
-    }
-    winDebug("winXIconToHICON - pWin %x: no suitable NetIcon\n", (int) pWin,
-             iconSize);
 
-    winMultiWindowGetWMHints(pWin, &hints);
-    if (!hints.icon_pixmap)
-        return NULL;
+        if (!hIcon && biggest_icon) {
+            winDebug
+                ("winXIconToHICON: selected %lu x %lu NetIcon for scaling to %u x %u\n",
+                 biggest_icon[0], biggest_icon[1], iconSize, iconSize);
+
+            hIcon = NetWMToWinIcon(bpp, biggest_icon);
+        }
 
-    dixLookupResourceByType((pointer) &iconPtr, hints.icon_pixmap, RT_PIXMAP,
-                            NullClient, DixUnknownAccess);
+        XFree(icon_data);
+    }
 
-    if (!iconPtr)
-        return NULL;
+    if (!hIcon) {
+        winDebug("winXIconToHICON: no suitable NetIcon\n");
+
+        hints = XGetWMHints(pDisplay, id);
+        if (hints) {
+            winDebug("winXIconToHICON: id 0x%x icon_pixmap hint %x\n", id,
+                     hints->icon_pixmap);
+
+            if (hints->icon_pixmap) {
+                Window root;
+                int x, y;
+                unsigned int width, height, border_width, depth;
+                XImage *xImageIcon;
+                XImage *xImageMask = NULL;
+
+                XGetGeometry(pDisplay, hints->icon_pixmap, &root, &x, &y,
+                             &width, &height, &border_width, &depth);
+
+                xImageIcon =
+                    XGetImage(pDisplay, hints->icon_pixmap, 0, 0, width, height,
+                              0xFFFFFFFF, ZPixmap);
+                winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%x\n", id,
+                         xImageIcon);
+
+                if (hints->icon_mask)
+                    xImageMask =
+                        XGetImage(pDisplay, hints->icon_mask, 0, 0, width,
+                                  height, 0xFFFFFFFF, ZPixmap);
+
+                if (xImageIcon) {
+                    int effBPP, stride, maskStride;
+
+                    /* 15 BPP is really 16BPP as far as we care */
+                    if (bpp == 15)
+                        effBPP = 16;
+                    else
+                        effBPP = bpp;
 
-    /* 15 BPP is really 16BPP as far as we care */
-    if (bpp == 15)
-        effBPP = 16;
-    else
-        effBPP = bpp;
+                    /* Need 16-bit aligned rows for DDBitmaps */
+                    stride = ((iconSize * effBPP + 15) & (~15)) / 8;
 
-    /* Need 16-bit aligned rows for DDBitmaps */
-    stride = ((iconSize * effBPP + 15) & (~15)) / 8;
+                    /* Mask is 1-bit deep */
+                    maskStride = ((iconSize * 1 + 15) & (~15)) / 8;
 
-    /* Mask is 1-bit deep */
-    maskStride = ((iconSize * 1 + 15) & (~15)) / 8;
+                    image = malloc(stride * iconSize);
+                    imageMask = malloc(stride * iconSize);
+                    mask = malloc(maskStride * iconSize);
 
-    image = malloc(stride * iconSize);
-    imageMask = malloc(stride * iconSize);
-    /* Default to a completely black mask */
-    mask = calloc(maskStride, iconSize);
+                    /* Default to a completely black mask */
+                    memset(imageMask, 0, stride * iconSize);
+                    memset(mask, 0, maskStride * iconSize);
 
-    winScaleXBitmapToWindows(iconSize, effBPP, iconPtr, image);
-    dixLookupResourceByType((pointer) &maskPtr, hints.icon_mask, RT_PIXMAP,
-                            NullClient, DixUnknownAccess);
+                    winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
+                                                xImageIcon, image);
 
-    if (maskPtr) {
-        winScaleXBitmapToWindows(iconSize, 1, maskPtr, mask);
+                    if (xImageMask) {
+                        winScaleXImageToWindowsIcon(iconSize, 1, maskStride,
+                                                    xImageMask, mask);
+                        winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
+                                                    xImageMask, imageMask);
+                    }
 
-        winScaleXBitmapToWindows(iconSize, effBPP, maskPtr, imageMask);
+                    /* Now we need to set all bits of the icon which are not masked */
+                    /* on to 0 because Color is really an XOR, not an OR function */
+                    dst = image;
+                    src = imageMask;
 
-        /* Now we need to set all bits of the icon which are not masked */
-        /* on to 0 because Color is really an XOR, not an OR function */
-        dst = image;
-        src = imageMask;
+                    for (i = 0; i < (stride * iconSize); i++)
+                        if ((*(src++)))
+                            *(dst++) = 0;
+                        else
+                            dst++;
 
-        for (i = 0; i < (stride * iconSize); i++)
-            if ((*(src++)))
-                *(dst++) = 0;
-            else
-                dst++;
-    }
+                    ii.fIcon = TRUE;
+                    ii.xHotspot = 0;    /* ignored */
+                    ii.yHotspot = 0;    /* ignored */
 
-    ii.fIcon = TRUE;
-    ii.xHotspot = 0;            /* ignored */
-    ii.yHotspot = 0;            /* ignored */
+                    /* Create Win32 mask from pixmap shape */
+                    ii.hbmMask =
+                        CreateBitmap(iconSize, iconSize, planes, 1, mask);
 
-    /* Create Win32 mask from pixmap shape */
-    ii.hbmMask = CreateBitmap(iconSize, iconSize, planes, 1, mask);
+                    /* Create Win32 bitmap from pixmap */
+                    ii.hbmColor =
+                        CreateBitmap(iconSize, iconSize, planes, bpp, image);
 
-    /* Create Win32 bitmap from pixmap */
-    ii.hbmColor = CreateBitmap(iconSize, iconSize, planes, bpp, image);
+                    /* Merge Win32 mask and bitmap into icon */
+                    hIcon = CreateIconIndirect(&ii);
 
-    /* Merge Win32 mask and bitmap into icon */
-    hIcon = CreateIconIndirect(&ii);
+                    /* Release Win32 mask and bitmap */
+                    DeleteObject(ii.hbmMask);
+                    DeleteObject(ii.hbmColor);
 
-    /* Release Win32 mask and bitmap */
-    DeleteObject(ii.hbmMask);
-    DeleteObject(ii.hbmColor);
+                    /* Free X mask and bitmap */
+                    free(mask);
+                    free(image);
+                    free(imageMask);
 
-    /* Free X mask and bitmap */
-    free(mask);
-    free(image);
-    free(imageMask);
+                    if (xImageMask)
+                        XDestroyImage(xImageMask);
 
+                    XDestroyImage(xImageIcon);
+                }
+            }
+            XFree(hints);
+        }
+    }
     return hIcon;
 }
 
 /*
- * Change the Windows window icon 
+ * Change the Windows window icon
  */
 
 #ifdef XWIN_MULTIWINDOW
 void
-winUpdateIcon(Window id)
+winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew)
 {
-    WindowPtr pWin;
     HICON hIcon, hIconSmall = NULL, hIconOld;
 
-    dixLookupResourceByType((pointer) &pWin, id, RT_WINDOW, NullClient,
-                            DixUnknownAccess);
-    if (pWin) {
-        winWindowPriv(pWin);
-        if (pWinPriv->hWnd) {
-            hIcon = winOverrideIcon((unsigned long) pWin);
-            if (!hIcon) {
-                hIcon = winXIconToHICON(pWin, GetSystemMetrics(SM_CXICON));
-                if (!hIcon) {
-                    hIcon = g_hIconX;
-                    hIconSmall = g_hSmallIconX;
-                }
-                else {
-                    /* Leave undefined if not found */
-                    hIconSmall =
-                        winXIconToHICON(pWin, GetSystemMetrics(SM_CXSMICON));
-                }
-            }
+    /* Start with the icon from preferences, if any */
+    hIcon = hIconNew;
+    hIconSmall = hIconNew;
 
-            /* Set the large icon */
-            hIconOld = (HICON) SendMessage(pWinPriv->hWnd,
-                                           WM_SETICON, ICON_BIG,
-                                           (LPARAM) hIcon);
+    /* If we still need an icon, try and get the icon from WM_HINTS */
+    if (!hIcon)
+        hIcon = winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXICON));
+    if (!hIconSmall)
+        hIconSmall =
+            winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXSMICON));
 
-            /* Delete the icon if its not the default */
-            winDestroyIcon(hIconOld);
-
-            /* Same for the small icon */
-            hIconOld = (HICON) SendMessage(pWinPriv->hWnd,
-                                           WM_SETICON, ICON_SMALL,
-                                           (LPARAM) hIconSmall);
-            winDestroyIcon(hIconOld);
-        }
+    /* If we got the small, but not the large one swap them */
+    if (!hIcon && hIconSmall) {
+        hIcon = hIconSmall;
+        hIconSmall = NULL;
     }
+
+    /* Set the large icon */
+    hIconOld = (HICON) SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
+    /* Delete the old icon if its not the default */
+    winDestroyIcon(hIconOld);
+
+    /* Same for the small icon */
+    hIconOld =
+        (HICON) SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
+    winDestroyIcon(hIconOld);
 }
 
 void
@@ -591,37 +601,21 @@ winInitGlobalIcons(void)
 }
 
 void
-winSelectIcons(WindowPtr pWin, HICON * pIcon, HICON * pSmallIcon)
+winSelectIcons(HICON * pIcon, HICON * pSmallIcon)
 {
     HICON hIcon, hSmallIcon;
 
     winInitGlobalIcons();
 
-    /* Try and get the icon from WM_HINTS */
-    hIcon = winXIconToHICON(pWin, GetSystemMetrics(SM_CXICON));
-    hSmallIcon = winXIconToHICON(pWin, GetSystemMetrics(SM_CXSMICON));
-
-    /* If we got the small, but not the large one swap them */
-    if (!hIcon && hSmallIcon) {
-        hIcon = hSmallIcon;
-        hSmallIcon = NULL;
-    }
-
-    /* Use default X icon if no icon loaded from WM_HINTS */
-    if (!hIcon) {
-        hIcon = g_hIconX;
-        hSmallIcon = g_hSmallIconX;
-    }
+    /* Use default X icon */
+    hIcon = g_hIconX;
+    hSmallIcon = g_hSmallIconX;
 
     if (pIcon)
         *pIcon = hIcon;
-    else
-        winDestroyIcon(hIcon);
 
     if (pSmallIcon)
         *pSmallIcon = hSmallIcon;
-    else
-        winDestroyIcon(hSmallIcon);
 }
 
 void
diff --git a/hw/xwin/winmultiwindowicons.h b/hw/xwin/winmultiwindowicons.h
new file mode 100644
index 0000000..bf7f6ed
--- /dev/null
+++ b/hw/xwin/winmultiwindowicons.h
@@ -0,0 +1,42 @@
+/*
+ * File: winmultiwindowicons.h
+ * Purpose: interface for multiwindow mode icon functions
+ *
+ * Copyright (c) Jon TURNEY 2012
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WINMULTIWINDOWICONS_H
+#define WINMULTIWINDOWICONS_H
+
+void
+ winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew);
+
+void
+ winInitGlobalIcons(void);
+
+void
+ winDestroyIcon(HICON hIcon);
+
+void
+ winSelectIcons(HICON * pIcon, HICON * pSmallIcon);
+
+#endif                          /* WINMULTIWINDOWICONS_H */
diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c
index 0093fcb..c0c7db2 100644
--- a/hw/xwin/winmultiwindowwindow.c
+++ b/hw/xwin/winmultiwindowwindow.c
@@ -63,6 +63,11 @@ winInitMultiWindowClass(void)
     WNDCLASSEX wcx;
 
     if (atomXWinClass == 0) {
+        HICON hIcon, hIconSmall;
+
+        /* Load the default icons */
+        winSelectIcons(&hIcon, &hIconSmall);
+
         /* Setup our window class */
         wcx.cbSize = sizeof(WNDCLASSEX);
         wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0);
@@ -70,12 +75,12 @@ winInitMultiWindowClass(void)
         wcx.cbClsExtra = 0;
         wcx.cbWndExtra = 0;
         wcx.hInstance = g_hInstance;
-        wcx.hIcon = g_hIconX;
+        wcx.hIcon = hIcon;
         wcx.hCursor = 0;
         wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
         wcx.lpszMenuName = NULL;
         wcx.lpszClassName = WINDOW_CLASS_X;
-        wcx.hIconSm = g_hSmallIconX;
+        wcx.hIconSm = hIconSmall;
 
 #if CYGMULTIWINDOW_DEBUG
         ErrorF("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X);
@@ -479,8 +484,6 @@ winCreateWindowsWindow(WindowPtr pWin)
     HWND hFore = NULL;
 
     winWindowPriv(pWin);
-    HICON hIcon;
-    HICON hIconSmall;
     winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv;
     WinXSizeHints hints;
     WindowPtr pDaddy;
@@ -574,13 +577,6 @@ winCreateWindowsWindow(WindowPtr pWin)
     }
     pWinPriv->hWnd = hWnd;
 
-    /* Set application or .XWinrc defined Icons */
-    winSelectIcons(pWin, &hIcon, &hIconSmall);
-    if (hIcon)
-        SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
-    if (hIconSmall)
-        SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
-
     /* Change style back to popup, already placed... */
     SetWindowLongPtr(hWnd, GWL_STYLE,
                      WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index b7909cc..82c32aa 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -553,7 +553,6 @@ UpdateName(WMInfoPtr pWMInfo, Window iWindow)
 
             /* Set the Windows window name */
             SetWindowTextW(hWnd, pwszWideWindowName);
-            winUpdateIcon(iWindow);
 
             free(pwszWideWindowName);
             free(pszWindowName);
@@ -561,6 +560,46 @@ UpdateName(WMInfoPtr pWMInfo, Window iWindow)
     }
 }
 
+/*
+ * Updates the icon of a HWND according to its X icon properties
+ */
+
+static void
+UpdateIcon(WMInfoPtr pWMInfo, Window iWindow)
+{
+    HWND hWnd;
+    HICON hIconNew = NULL;
+    XWindowAttributes attr;
+
+    hWnd = getHwnd(pWMInfo, iWindow);
+    if (!hWnd)
+        return;
+
+    /* If window isn't override-redirect */
+    XGetWindowAttributes(pWMInfo->pDisplay, iWindow, &attr);
+    if (!attr.override_redirect) {
+        XClassHint class_hint = { 0, 0 };
+        char *window_name = 0;
+
+        if (XGetClassHint(pWMInfo->pDisplay, iWindow, &class_hint)) {
+            XFetchName(pWMInfo->pDisplay, iWindow, &window_name);
+
+            hIconNew =
+                (HICON) winOverrideIcon(class_hint.res_name,
+                                        class_hint.res_class, window_name);
+
+            if (class_hint.res_name)
+                XFree(class_hint.res_name);
+            if (class_hint.res_class)
+                XFree(class_hint.res_class);
+            if (window_name)
+                XFree(window_name);
+        }
+    }
+
+    winUpdateIcon(hWnd, pWMInfo->pDisplay, iWindow, hIconNew);
+}
+
 #if 0
 /*
  * Fix up any differences between the X11 and Win32 window stacks
@@ -684,7 +723,7 @@ winMultiWindowWMProc(void *pArg)
                             PropModeReplace,
                             (unsigned char *) &(pNode->msg.hwndWindow), 1);
             UpdateName(pWMInfo, pNode->msg.iWindow);
-            winUpdateIcon(pNode->msg.iWindow);
+            UpdateIcon(pWMInfo, pNode->msg.iWindow);
             break;
 
         case WM_WM_MAP2:
@@ -707,7 +746,7 @@ winMultiWindowWMProc(void *pArg)
                             PropModeReplace,
                             (unsigned char *) &(pNode->msg.hwndWindow), 1);
             UpdateName(pWMInfo, pNode->msg.iWindow);
-            winUpdateIcon(pNode->msg.iWindow);
+            UpdateIcon(pWMInfo, pNode->msg.iWindow);
             {
                 HWND zstyle = HWND_NOTOPMOST;
 
@@ -770,7 +809,7 @@ winMultiWindowWMProc(void *pArg)
             break;
 
         case WM_WM_ICON_EVENT:
-            winUpdateIcon(pNode->msg.iWindow);
+            UpdateIcon(pWMInfo, pNode->msg.iWindow);
             break;
 
         case WM_WM_CHANGE_STATE:
diff --git a/hw/xwin/winprefs.c b/hw/xwin/winprefs.c
index 86a7882..faa97c3 100644
--- a/hw/xwin/winprefs.c
+++ b/hw/xwin/winprefs.c
@@ -148,7 +148,6 @@ static wBOOL CALLBACK
 ReloadEnumWindowsProc(HWND hwnd, LPARAM lParam)
 {
     HICON hicon;
-    Window wid;
 
     if (!hwnd) {
         ErrorF("ReloadEnumWindowsProc: hwnd==NULL!\n");
@@ -173,10 +172,23 @@ ReloadEnumWindowsProc(HWND hwnd, LPARAM lParam)
         /* This window is now clean of our taint (but with undefined icons) */
     }
     else {
-        /* winUpdateIcon() will set the icon default, dynamic, or from xwinrc */
-        wid = (Window) GetProp(hwnd, WIN_WID_PROP);
-        if (wid)
-            winUpdateIcon(wid);
+        /* Send a message to WM thread telling it re-evaluate the icon for this window */
+        {
+            winWMMessageRec wmMsg;
+
+            WindowPtr pWin = GetProp(hwnd, WIN_WINDOW_PROP);
+
+            if (pWin) {
+                winPrivWinPtr pWinPriv = winGetWindowPriv(pWin);
+                winPrivScreenPtr s_pScreenPriv = pWinPriv->pScreenPriv;
+
+                wmMsg.msg = WM_WM_ICON_EVENT;
+                wmMsg.hwndWindow = hwnd;
+                wmMsg.iWindow = (Window) GetProp(hwnd, WIN_WID_PROP);
+
+                winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
+            }
+        }
 
         /* Update the system menu for this window */
         SetupSysMenu((unsigned long) hwnd);
@@ -577,31 +589,15 @@ LoadImageComma(char *fname, int sx, int sy, int flags)
  * ICONS{} section in the prefs file, and load the icon from a file
  */
 HICON
-winOverrideIcon(unsigned long longWin)
+winOverrideIcon(char *res_name, char *res_class, char *wmName)
 {
-    WindowPtr pWin = (WindowPtr) longWin;
-    char *res_name, *res_class;
     int i;
     HICON hicon;
-    char *wmName;
-
-    if (pWin == NULL)
-        return 0;
-
-    /* If we can't find the class, we can't override from default! */
-    if (!winMultiWindowGetClassHint(pWin, &res_name, &res_class))
-        return 0;
-
-    winMultiWindowGetWMName(pWin, &wmName);
 
     for (i = 0; i < pref.iconItems; i++) {
-        if (!strcmp(pref.icon[i].match, res_name) ||
-            !strcmp(pref.icon[i].match, res_class) ||
+        if ((res_name && !strcmp(pref.icon[i].match, res_name)) ||
+            (res_class && !strcmp(pref.icon[i].match, res_class)) ||
             (wmName && strstr(wmName, pref.icon[i].match))) {
-            free(res_name);
-            free(res_class);
-            free(wmName);
-
             if (pref.icon[i].hicon)
                 return pref.icon[i].hicon;
 
@@ -616,10 +612,6 @@ winOverrideIcon(unsigned long longWin)
     }
 
     /* Didn't find the icon, fail gracefully */
-    free(res_name);
-    free(res_class);
-    free(wmName);
-
     return 0;
 }
 
diff --git a/hw/xwin/winprefs.h b/hw/xwin/winprefs.h
index fcce8d8..5de5719 100644
--- a/hw/xwin/winprefs.h
+++ b/hw/xwin/winprefs.h
@@ -164,7 +164,7 @@ Bool
 int
  winIconIsOverride(unsigned hiconIn);
 
-HICON winOverrideIcon(unsigned long longpWin);
+HICON winOverrideIcon(char *res_name, char *res_class, char *wmName);
 
 unsigned long
  winOverrideStyle(char *res_name, char *res_class, char *wmName);
diff --git a/hw/xwin/winwin32rootless.c b/hw/xwin/winwin32rootless.c
index cef49b5..5bf7102 100644
--- a/hw/xwin/winwin32rootless.c
+++ b/hw/xwin/winwin32rootless.c
@@ -231,7 +231,7 @@ winMWExtWMCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
     // Store the implementation private frame ID
     pFrame->wid = (RootlessFrameID) pRLWinPriv;
 
-    winSelectIcons(pFrame->win, &hIcon, &hIconSmall);
+    winSelectIcons(&hIcon, &hIconSmall);
 
     /* Set standard class name prefix so we can identify window easily */
     strncpy(pszClass, WINDOW_CLASS_X, sizeof(pszClass));
diff --git a/hw/xwin/winwin32rootlesswindow.c b/hw/xwin/winwin32rootlesswindow.c
index bfba1bf..f2d68cb 100644
--- a/hw/xwin/winwin32rootlesswindow.c
+++ b/hw/xwin/winwin32rootlesswindow.c
@@ -147,39 +147,8 @@ winMWExtWMMoveResizeXWindow(WindowPtr pWin, int x, int y, int w, int h)
 }
 
 /*
- * winMWExtWMUpdateIcon
- * Change the Windows window icon
- */
-
-void
-winMWExtWMUpdateIcon(Window id)
-{
-    WindowPtr pWin;
-    HICON hIcon, hiconOld;
-
-    dixLookupResourceByType((pointer) &pWin, id, RT_WINDOW, NullClient,
-                            DixUnknownAccess);
-    hIcon = winOverrideIcon((unsigned long) pWin);
-
-    if (!hIcon)
-        hIcon = winXIconToHICON(pWin, GetSystemMetrics(SM_CXICON));
 
-    if (hIcon) {
-        win32RootlessWindowPtr pRLWinPriv
-            = (win32RootlessWindowPtr) RootlessFrameForWindow(pWin, FALSE);
 
-        if (pRLWinPriv->hWnd) {
-
-            hiconOld = (HICON) SendMessage(pRLWinPriv->hWnd,
-                                           WM_SETICON, ICON_BIG,
-                                           (LPARAM) hIcon);
-            winDestroyIcon(hiconOld);
-        }
-        hIcon = NULL;
-    }
-}
-
-/*
  * winMWExtWMDecorateWindow - Update window style. Called by EnumWindows.
  */
 
diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h
index 9f2ab45..a5919ee 100644
--- a/hw/xwin/winwindow.h
+++ b/hw/xwin/winwindow.h
@@ -157,18 +157,5 @@ void
 void
  winMinimizeWindow(Window id);
 
-/*
- * winmultiwindowicons.c
- */
-
-void
- winUpdateIcon(Window id);
-
-void
- winInitGlobalIcons(void);
-
-void
- winDestroyIcon(HICON hIcon);
-
 #endif                          /* XWIN_MULTIWINDOW */
 #endif
diff --git a/hw/xwin/winwindowswm.c b/hw/xwin/winwindowswm.c
index 77c997a..5d513a8 100644
--- a/hw/xwin/winwindowswm.c
+++ b/hw/xwin/winwindowswm.c
@@ -439,8 +439,6 @@ ProcWindowsWMFrameDraw(ClientPtr client)
 
     ShowWindow(pRLWinPriv->hWnd, nCmdShow);
 
-    winMWExtWMUpdateIcon(pWin->drawable.id);
-
     if (wBoundingShape(pWin) != NULL) {
         /* wBoundingShape is relative to *inner* origin of window.
            Translate by borderWidth to get the outside-relative position. */
commit 2677d89823b851fea31036f51589985bb86864b7
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Sun Jul 22 17:38:55 2012 +0100

    hw/xwin: Also update icon when _NET_WM_ICON property changes
    
    _NET_WM_ICON property is also considered to decide on the window icon, so also
    send a WM_WM_ICON_EVENT message to the WM if the PropertyNotify event is for
    _NET_WM_ICON property
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index c30efa9..b7909cc 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -821,6 +821,7 @@ winMultiWindowXMsgProc(void *pArg)
     Atom atmWmName;
     Atom atmWmHints;
     Atom atmWmChange;
+    Atom atmNetWmIcon;
     int iReturn;
     XIconSize *xis;
 
@@ -946,6 +947,7 @@ winMultiWindowXMsgProc(void *pArg)
     atmWmName = XInternAtom(pProcArg->pDisplay, "WM_NAME", False);
     atmWmHints = XInternAtom(pProcArg->pDisplay, "WM_HINTS", False);
     atmWmChange = XInternAtom(pProcArg->pDisplay, "WM_CHANGE_STATE", False);
+    atmNetWmIcon = XInternAtom(pProcArg->pDisplay, "_NET_WM_ICON", False);
 
     /*
        iiimxcf had a bug until 2009-04-27, assuming that the
@@ -1073,25 +1075,25 @@ winMultiWindowXMsgProc(void *pArg)
                            True, StructureNotifyMask, &event_send);
             }
         }
-        else if (event.type == PropertyNotify
-                 && event.xproperty.atom == atmWmName) {
-            memset(&msg, 0, sizeof(msg));
-
-            msg.msg = WM_WM_NAME_EVENT;
-            msg.iWindow = event.xproperty.window;
+        else if (event.type == PropertyNotify) {
+            if (event.xproperty.atom == atmWmName) {
+                memset(&msg, 0, sizeof(msg));
 
-            /* Other fields ignored */
-            winSendMessageToWM(pProcArg->pWMInfo, &msg);
-        }
-        else if (event.type == PropertyNotify
-                 && event.xproperty.atom == atmWmHints) {
-            memset(&msg, 0, sizeof(msg));
+                msg.msg = WM_WM_NAME_EVENT;
+                msg.iWindow = event.xproperty.window;
 
-            msg.msg = WM_WM_ICON_EVENT;
-            msg.iWindow = event.xproperty.window;
-
-            /* Other fields ignored */
-            winSendMessageToWM(pProcArg->pWMInfo, &msg);
+                /* Other fields ignored */
+                winSendMessageToWM(pProcArg->pWMInfo, &msg);
+            }
+            else if ((event.xproperty.atom == atmWmHints) ||
+                     (event.xproperty.atom == atmNetWmIcon)) {
+                memset(&msg, 0, sizeof(msg));
+                msg.msg = WM_WM_ICON_EVENT;
+                msg.iWindow = event.xproperty.window;
+
+                /* Other fields ignored */
+                winSendMessageToWM(pProcArg->pWMInfo, &msg);
+            }
         }
         else if (event.type == ClientMessage
                  && event.xclient.message_type == atmWmChange
commit a07541f1ffc28c57a762beefb96c7bf0ac40b0a4
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Sun Jul 22 16:15:12 2012 +0100

    hw/xwin: Rename WM_WM_HINTS_EVENT to WM_WM_ICON_EVENT
    
    WM_WM_HINTS_EVENT only updates the icon, so rename it to WM_WM_ICON_EVENT
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index 754b530..c30efa9 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -769,7 +769,7 @@ winMultiWindowWMProc(void *pArg)
             UpdateName(pWMInfo, pNode->msg.iWindow);
             break;
 
-        case WM_WM_HINTS_EVENT:
+        case WM_WM_ICON_EVENT:
             winUpdateIcon(pNode->msg.iWindow);
             break;
 
@@ -1087,7 +1087,7 @@ winMultiWindowXMsgProc(void *pArg)
                  && event.xproperty.atom == atmWmHints) {
             memset(&msg, 0, sizeof(msg));
 
-            msg.msg = WM_WM_HINTS_EVENT;
+            msg.msg = WM_WM_ICON_EVENT;
             msg.iWindow = event.xproperty.window;
 
             /* Other fields ignored */
diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h
index c357f8d..9f2ab45 100644
--- a/hw/xwin/winwindow.h
+++ b/hw/xwin/winwindow.h
@@ -115,7 +115,7 @@ typedef struct _winWMMessageRec {
 #define		WM_WM_KILL		(WM_USER + 7)
 #define		WM_WM_ACTIVATE		(WM_USER + 8)
 #define		WM_WM_NAME_EVENT	(WM_USER + 9)
-#define		WM_WM_HINTS_EVENT	(WM_USER + 10)
+#define		WM_WM_ICON_EVENT	(WM_USER + 10)
 #define		WM_WM_CHANGE_STATE	(WM_USER + 11)
 #define		WM_WM_MAP2		(WM_USER + 12)
 #define		WM_WM_MAP3		(WM_USER + 13)
commit 2a47c91eb382d1ff0fb009a39efa7dc9c6fd5112
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Fri Jul 20 13:51:35 2012 +0100

    hw/xwin: Refactor Xutf8TextPropertyToString() from GetWindowName() as a separate utility function
    
    Simplify GetWindowName() by moving UTF-8 to wchar conversion out to it's call
    site.  This allows us to do extra processing on the window name in future.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index 76b4683..754b530 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -151,7 +151,7 @@ static Bool
  InitQueue(WMMsgQueuePtr pQueue);
 
 static void
- GetWindowName(Display * pDpy, Window iWin, wchar_t ** ppName);
+ GetWindowName(Display * pDpy, Window iWin, char **ppWindowName);
 
 static int
  SendXMessage(Display * pDisplay, Window iWin, Atom atmType, long nData);
@@ -399,38 +399,19 @@ InitQueue(WMMsgQueuePtr pQueue)
     return TRUE;
 }
 
-/*
- * GetWindowName - Retrieve the title of an X Window
- */
-
-static void
-GetWindowName(Display * pDisplay, Window iWin, wchar_t ** ppName)
+static
+char *
+Xutf8TextPropertyToString(Display * pDisplay, XTextProperty * xtp)
 {
-    int nResult, nNum;
+    int nNum;
     char **ppList;
     char *pszReturnData;
-    int iLen, i;
-    XTextProperty xtpName;
-
-#if CYGMULTIWINDOW_DEBUG
-    ErrorF("GetWindowName\n");
-#endif
 
-    /* Intialize ppName to NULL */
-    *ppName = NULL;
+    if (Xutf8TextPropertyToTextList(pDisplay, xtp, &ppList, &nNum) >= Success &&
+        nNum > 0 && *ppList) {
+        int i;
+        int iLen = 0;
 
-    /* Try to get --- */
-    nResult = XGetWMName(pDisplay, iWin, &xtpName);
-    if (!nResult || !xtpName.value || !xtpName.nitems) {
-#if CYGMULTIWINDOW_DEBUG
-        ErrorF("GetWindowName - XGetWMName failed.  No name.\n");
-#endif
-        return;
-    }
-
-    if (Xutf8TextPropertyToTextList(pDisplay, &xtpName, &ppList, &nNum) >=
-        Success && nNum > 0 && *ppList) {
-        iLen = 0;
         for (i = 0; i < nNum; i++)
             iLen += strlen(ppList[i]);
         pszReturnData = (char *) malloc(iLen + 1);
@@ -444,15 +425,40 @@ GetWindowName(Display * pDisplay, Window iWin, wchar_t ** ppName)
         pszReturnData = (char *) malloc(1);
         pszReturnData[0] = '\0';
     }
-    iLen = MultiByteToWideChar(CP_UTF8, 0, pszReturnData, -1, NULL, 0);
-    *ppName = (wchar_t *) malloc(sizeof(wchar_t) * (iLen + 1));
-    MultiByteToWideChar(CP_UTF8, 0, pszReturnData, -1, *ppName, iLen);
-    XFree(xtpName.value);
-    free(pszReturnData);
 
+    return pszReturnData;
+}
+
+/*
+ * GetWindowName - Retrieve the title of an X Window
+ */
+
+static void
+GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
+{
+    int nResult;
+    XTextProperty xtpWindowName;
+    char *pszWindowName;
+
+#if CYGMULTIWINDOW_DEBUG
+    ErrorF("GetWindowName\n");
+#endif
+
+    /* Intialize ppWindowName to NULL */
+    *ppWindowName = NULL;
+
+    /* Try to get window name */
+    nResult = XGetWMName(pDisplay, iWin, &xtpWindowName);
+    if (!nResult || !xtpWindowName.value || !xtpWindowName.nitems) {
 #if CYGMULTIWINDOW_DEBUG
-    ErrorF("GetWindowName - Returning\n");
+        ErrorF("GetWindowName - XGetWMName failed.  No name.\n");
 #endif
+        return;
+    }
+
+    pszWindowName = Xutf8TextPropertyToString(pDisplay, &xtpWindowName);
+    XFree(xtpWindowName.value);
+    *ppWindowName = pszWindowName;
 }
 
 /*
@@ -528,17 +534,30 @@ UpdateName(WMInfoPtr pWMInfo, Window iWindow)
     if (!hWnd)
         return;
 
-    /* Set the Windows window name */
-    GetWindowName(pWMInfo->pDisplay, iWindow, &pszName);
-    if (pszName) {
-        /* Get the window attributes */
-        XGetWindowAttributes(pWMInfo->pDisplay, iWindow, &attr);
-        if (!attr.override_redirect) {
-            SetWindowTextW(hWnd, pszName);
+    /* If window isn't override-redirect */
+    XGetWindowAttributes(pWMInfo->pDisplay, iWindow, &attr);
+    if (!attr.override_redirect) {
+        char *pszWindowName;
+
+        /* Get the X windows window name */
+        GetWindowName(pWMInfo->pDisplay, iWindow, &pszWindowName);
+
+        if (pszWindowName) {
+            /* Convert from UTF-8 to wide char */
+            int iLen =
+                MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1, NULL, 0);
+            wchar_t *pwszWideWindowName =
+                (wchar_t *) malloc(sizeof(wchar_t) * (iLen + 1));
+            MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1,
+                                pwszWideWindowName, iLen);
+
+            /* Set the Windows window name */
+            SetWindowTextW(hWnd, pwszWideWindowName);
             winUpdateIcon(iWindow);
-        }
 
-        free(pszName);
+            free(pwszWideWindowName);
+            free(pszWindowName);
+        }
     }
 }
 


More information about the xorg-commit mailing list