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@dronecode.org.uk>
Reviewed-by: Colin Harrison <colin.harrison@virgin.net>
This commit is contained in:
Jon TURNEY 2012-07-21 14:09:16 +01:00
parent 2677d89823
commit 527cf13135
11 changed files with 318 additions and 310 deletions

View File

@ -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

View File

@ -31,75 +31,65 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include "win.h"
#include "dixevents.h"
#include "winmultiwindowclass.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 "propertyst.h"
#include "windowstr.h"
#include "winmsg.h"
#include "winmultiwindowicons.h"
#include "winglobals.h"
/*
* global variables
*/
extern HINSTANCE g_hInstance;
/*
* Prototypes for local functions
* Scale an X icon ZPixmap into a Windoze icon bitmap
*/
static void
winScaleXBitmapToWindows(int iconSize, int effBPP,
PixmapPtr pixmap, unsigned char *image);
/*
* Scale an X icon bitmap 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);
dixLookupResourceByType((pointer) &iconPtr, hints.icon_pixmap, RT_PIXMAP,
NullClient, DixUnknownAccess);
hIcon = NetWMToWinIcon(bpp, biggest_icon);
}
if (!iconPtr)
return NULL;
/* 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;
/* Mask is 1-bit deep */
maskStride = ((iconSize * 1 + 15) & (~15)) / 8;
image = malloc(stride * iconSize);
imageMask = malloc(stride * iconSize);
/* Default to a completely black mask */
mask = calloc(maskStride, iconSize);
winScaleXBitmapToWindows(iconSize, effBPP, iconPtr, image);
dixLookupResourceByType((pointer) &maskPtr, hints.icon_mask, RT_PIXMAP,
NullClient, DixUnknownAccess);
if (maskPtr) {
winScaleXBitmapToWindows(iconSize, 1, maskPtr, mask);
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;
for (i = 0; i < (stride * iconSize); i++)
if ((*(src++)))
*(dst++) = 0;
else
dst++;
XFree(icon_data);
}
ii.fIcon = TRUE;
ii.xHotspot = 0; /* ignored */
ii.yHotspot = 0; /* ignored */
if (!hIcon) {
winDebug("winXIconToHICON: no suitable NetIcon\n");
/* Create Win32 mask from pixmap shape */
ii.hbmMask = CreateBitmap(iconSize, iconSize, planes, 1, mask);
hints = XGetWMHints(pDisplay, id);
if (hints) {
winDebug("winXIconToHICON: id 0x%x icon_pixmap hint %x\n", id,
hints->icon_pixmap);
/* Create Win32 bitmap from pixmap */
ii.hbmColor = CreateBitmap(iconSize, iconSize, planes, bpp, image);
if (hints->icon_pixmap) {
Window root;
int x, y;
unsigned int width, height, border_width, depth;
XImage *xImageIcon;
XImage *xImageMask = NULL;
/* Merge Win32 mask and bitmap into icon */
hIcon = CreateIconIndirect(&ii);
XGetGeometry(pDisplay, hints->icon_pixmap, &root, &x, &y,
&width, &height, &border_width, &depth);
/* Release Win32 mask and bitmap */
DeleteObject(ii.hbmMask);
DeleteObject(ii.hbmColor);
xImageIcon =
XGetImage(pDisplay, hints->icon_pixmap, 0, 0, width, height,
0xFFFFFFFF, ZPixmap);
winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%x\n", id,
xImageIcon);
/* Free X mask and bitmap */
free(mask);
free(image);
free(imageMask);
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;
/* Need 16-bit aligned rows for DDBitmaps */
stride = ((iconSize * effBPP + 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);
/* Default to a completely black mask */
memset(imageMask, 0, stride * iconSize);
memset(mask, 0, maskStride * iconSize);
winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
xImageIcon, image);
if (xImageMask) {
winScaleXImageToWindowsIcon(iconSize, 1, maskStride,
xImageMask, mask);
winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
xImageMask, 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++;
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 bitmap from pixmap */
ii.hbmColor =
CreateBitmap(iconSize, iconSize, planes, bpp, image);
/* Merge Win32 mask and bitmap into icon */
hIcon = CreateIconIndirect(&ii);
/* Release Win32 mask and bitmap */
DeleteObject(ii.hbmMask);
DeleteObject(ii.hbmColor);
/* 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

View File

@ -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 */

View File

@ -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);

View File

@ -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:

View File

@ -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;
}

View File

@ -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);

View File

@ -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));

View File

@ -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.
*/

View File

@ -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

View File

@ -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. */