From dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 12 Sep 2011 11:27:51 +0200 Subject: Synchronised line endinge with release branch --- xorg-server/hw/xwin/winmultiwindowicons.c | 1298 ++++++++++++++--------------- 1 file changed, 649 insertions(+), 649 deletions(-) (limited to 'xorg-server/hw/xwin/winmultiwindowicons.c') diff --git a/xorg-server/hw/xwin/winmultiwindowicons.c b/xorg-server/hw/xwin/winmultiwindowicons.c index 853d63864..d534cf0b7 100644 --- a/xorg-server/hw/xwin/winmultiwindowicons.c +++ b/xorg-server/hw/xwin/winmultiwindowicons.c @@ -1,649 +1,649 @@ -/* - *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. - * - *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 XFREE86 PROJECT 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. - * - *Except as contained in this notice, the name of the XFree86 Project - *shall not be used in advertising or otherwise to promote the sale, use - *or other dealings in this Software without prior written authorization - *from the XFree86 Project. - * - * Authors: Earle F. Philhower, III - */ - -#ifdef HAVE_XWIN_CONFIG_H -#include -#endif -#include "win.h" -#include "dixevents.h" -#include "winmultiwindowclass.h" -#include "winprefs.h" - -#include "propertyst.h" -#include "windowstr.h" - - -/* - * Prototypes for local functions - */ - -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) -{ - int row, column, effXBPP, effXDepth; - unsigned char *outPtr; - char *iconData = 0; - int stride, 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 = 16; - - if (pixmap->drawable.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); - 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); - - /* Keep aspect ratio */ - factX = ((float)pixmap->drawable.width) / ((float)iconSize); - factY = ((float)pixmap->drawable.height) / ((float)iconSize); - if (factX > factY) - factY = factX; - else - factX = factY; - - /* Out-of-bounds, fill icon with zero */ - zero = 0; - - for (row = 0; row < iconSize; row++) - { - outPtr = image + stride * row; - for (column = 0; column < iconSize; column++) - { - posX = factX * column; - posY = factY * row; - - ptr = (unsigned char*) iconData + posY*xStride; - if (effXBPP == 1) - { - ptr += posX / 8; - - /* Out of X icon bounds, leave space blank */ - if (posX >= pixmap->drawable.width - || posY >= pixmap->drawable.height) - ptr = (unsigned char *) &zero; - - if ((*ptr) & (1 << (posX & 7))) - switch (effBPP) - { - case 32: - *(outPtr++) = 0; - case 24: - *(outPtr++) = 0; - case 16: - *(outPtr++) = 0; - case 8: - *(outPtr++) = 0; - break; - case 1: - outPtr[column / 8] &= ~(1 << (7 - (column & 7))); - break; - } - else - switch (effBPP) - { - case 32: - *(outPtr++) = 255; - *(outPtr++) = 255; - *(outPtr++) = 255; - *(outPtr++) = 0; - break; - case 24: - *(outPtr++) = 255; - case 16: - *(outPtr++) = 255; - case 8: - *(outPtr++) = 255; - break; - case 1: - outPtr[column / 8] |= (1 << (7 - (column & 7))); - break; - } - } - else if (effXDepth == 24 || effXDepth == 32) - { - ptr += posX * (effXBPP / 8); - - /* Out of X icon bounds, leave space blank */ - if (posX >= pixmap->drawable.width - || posY >= pixmap->drawable.height) - ptr = (unsigned char *) &zero; - color = (((*ptr) << 16) - + ((*(ptr + 1)) << 8) - + ((*(ptr + 2)) << 0)); - switch (effBPP) - { - case 32: - *(outPtr++) = *(ptr++); /* b */ - *(outPtr++) = *(ptr++); /* g */ - *(outPtr++) = *(ptr++); /* r */ - *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */ - break; - case 24: - *(outPtr++) = *(ptr++); - *(outPtr++) = *(ptr++); - *(outPtr++) = *(ptr++); - break; - case 16: - color = ((((*ptr) >> 2) << 10) - + (((*(ptr + 1)) >> 2) << 5) - + (((*(ptr + 2)) >> 2))); - *(outPtr++) = (color >> 8); - *(outPtr++) = (color & 255); - break; - case 8: - color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2)))); - color /= 3; - *(outPtr++) = color; - break; - case 1: - if (color) - outPtr[column / 8] |= (1 << (7 - (column & 7))); - else - outPtr[column / 8] &= ~(1 << (7 - (column & 7))); - } - } - else if (effXDepth == 16) - { - ptr += posX * (effXBPP / 8); - - /* Out of X icon bounds, leave space blank */ - if (posX >= pixmap->drawable.width - || posY >= pixmap->drawable.height) - ptr = (unsigned char *) &zero; - color = ((*ptr) << 8) + (*(ptr + 1)); - switch (effBPP) - { - case 32: - *(outPtr++) = (color & 31) << 2; - *(outPtr++) = ((color >> 5) & 31) << 2; - *(outPtr++) = ((color >> 10) & 31) << 2; - *(outPtr++) = 0; /* resvd */ - break; - case 24: - *(outPtr++) = (color & 31) << 2; - *(outPtr++) = ((color >> 5) & 31) << 2; - *(outPtr++) = ((color >> 10) & 31) << 2; - break; - case 16: - *(outPtr++) = *(ptr++); - *(outPtr++) = *(ptr++); - break; - case 8: - *(outPtr++) = (((color & 31) - + ((color >> 5) & 31) - + ((color >> 10) & 31)) / 3) << 2; - break; - case 1: - if (color) - outPtr[column / 8] |= (1 << (7 - (column & 7))); - else - outPtr[column / 8] &= ~(1 << (7 - (column & 7))); - break; - } /* end switch(effbpp) */ - } /* end if effxbpp==16) */ - } /* end for column */ - } /* end for row */ - free (iconData); -} - -static HICON -NetWMToWinIconAlpha(uint32_t *icon) -{ - int width = icon[0]; - int height = icon[1]; - uint32_t *pixels = &icon[2]; - HICON result; - HDC hdc = GetDC(NULL); - uint32_t *DIB_pixels; - ICONINFO ii; - BITMAPV5HEADER bmh; - - /* Define an ARGB pixel format used for Color+Alpha icons */ - ZeroMemory(&bmh,sizeof(bmh)); - bmh.bV5Size = sizeof(bmh); - bmh.bV5Width = width; - bmh.bV5Height = -height; /* Invert the image */ - bmh.bV5Planes = 1; - bmh.bV5BitCount = 32; - bmh.bV5Compression = BI_BITFIELDS; - bmh.bV5AlphaMask = 0xFF000000; - bmh.bV5RedMask = 0x00FF0000; - bmh.bV5GreenMask = 0x0000FF00; - bmh.bV5BlueMask = 0x000000FF; - - ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO*)&bmh, - DIB_RGB_COLORS, (void**)&DIB_pixels, NULL, 0); - ReleaseDC(NULL, hdc); - ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL); - memcpy(DIB_pixels, pixels, height*width*4); - - /* CreateIconIndirect() traditionally required DDBitmaps */ - /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */ - /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */ - ii.fIcon = TRUE; - ii.xHotspot = 0; - ii.yHotspot = 0; - result = CreateIconIndirect(&ii); - - DeleteObject(ii.hbmColor); - DeleteObject(ii.hbmMask); - - winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result); - return result; -} - -static HICON -NetWMToWinIconThreshold(uint32_t *icon) -{ - int width = icon[0]; - int height = icon[1]; - uint32_t *pixels = &icon[2]; - int row, col; - HICON result; - ICONINFO ii; - - HDC hdc = GetDC(NULL); - HDC xorDC = CreateCompatibleDC(hdc); - HDC andDC = CreateCompatibleDC(hdc); - ii.hbmColor = CreateCompatibleBitmap(hdc, width, height); - ii.hbmMask = CreateCompatibleBitmap(hdc, width, height); - ReleaseDC(NULL, hdc); - SelectObject(xorDC, ii.hbmColor); - SelectObject(andDC, ii.hbmMask); - - for (row = 0; row < height; row++) { - for (col = 0; col < width; col++) { - if ((*pixels & 0xFF000000) > 31<<24) { /* 31 alpha threshold, i.e. opaque above, transparent below */ - SetPixelV(xorDC, col, row, RGB(((char*)pixels)[2], ((char*)pixels)[1], - ((char*)pixels)[0])); - SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */ - } - else { - SetPixelV(xorDC, col, row, RGB(0, 0, 0)); - SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */ - } - pixels++; - } - } - DeleteDC(xorDC); - DeleteDC(andDC); - - ii.fIcon = TRUE; - ii.xHotspot = 0; - ii.yHotspot = 0; - result = CreateIconIndirect(&ii); - - DeleteObject(ii.hbmColor); - DeleteObject(ii.hbmMask ); - - winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1], result); - return result; -} - -static HICON -NetWMToWinIcon(int bpp, uint32_t *icon) -{ - static Bool hasIconAlphaChannel = FALSE; - static BOOL versionChecked = FALSE; - - if (!versionChecked) - { - OSVERSIONINFOEX osvi = {0}; - ULONGLONG dwlConditionMask = 0; - - osvi.dwOSVersionInfoSize = sizeof (osvi); - osvi.dwMajorVersion = 5; - osvi.dwMinorVersion = 1; - - /* Windows versions later than XP have icon alpha channel suport, 2000 does not */ - VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); - VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); - hasIconAlphaChannel = VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask); - versionChecked = TRUE; - - winDebug("OS has icon alpha channel support: %s\n", hasIconAlphaChannel ? "yes" : "no"); - } - - if (hasIconAlphaChannel && (bpp==32)) - return NetWMToWinIconAlpha(icon); - else - 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) -{ - unsigned char *mask, *image, *imageMask; - unsigned char *dst, *src; - PixmapPtr iconPtr; - PixmapPtr maskPtr; - int planes, bpp, effBPP, stride, maskStride, i; - int biggest_size = 0; - HDC hDC; - ICONINFO ii; - WinXWMHints 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; - - hDC = GetDC (GetDesktopWindow ()); - planes = GetDeviceCaps (hDC, PLANES); - bpp = GetDeviceCaps (hDC, BITSPIXEL); - ReleaseDC (GetDesktopWindow (), hDC); - - if (generation != serverGeneration) { - generation = serverGeneration; - _XA_NET_WM_ICON = MakeAtom("_NET_WM_ICON", 12, TRUE); - } - - 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; - 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 */ - 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; - - dixLookupResourceByType((pointer) &iconPtr, hints.icon_pixmap, RT_PIXMAP, - NullClient, DixUnknownAccess); - - 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++; - } - - 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); - - return hIcon; -} - - - -/* - * Change the Windows window icon - */ - -#ifdef XWIN_MULTIWINDOW -void -winUpdateIcon (Window id) -{ - 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)); - } - } - - /* Set the large icon */ - hIconOld = (HICON) SendMessage (pWinPriv->hWnd, - WM_SETICON, ICON_BIG, (LPARAM) hIcon); - - /* 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); - } - } -} - -void winInitGlobalIcons (void) -{ - int sm_cx = GetSystemMetrics(SM_CXICON); - int sm_cxsm = GetSystemMetrics(SM_CXSMICON); - /* Load default X icon in case it's not ready yet */ - if (!g_hIconX) - { - g_hIconX = winOverrideDefaultIcon(sm_cx); - g_hSmallIconX = winOverrideDefaultIcon(sm_cxsm); - } - - if (!g_hIconX) - { - g_hIconX = (HICON)LoadImage (g_hInstance, - MAKEINTRESOURCE(IDI_XWIN), - IMAGE_ICON, - GetSystemMetrics(SM_CXICON), - GetSystemMetrics(SM_CYICON), - 0); - g_hSmallIconX = (HICON)LoadImage (g_hInstance, - MAKEINTRESOURCE(IDI_XWIN), - IMAGE_ICON, - GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), - LR_DEFAULTSIZE); - } -} - -void winSelectIcons(WindowPtr pWin, 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; - } - - if (pIcon) - *pIcon = hIcon; - else - winDestroyIcon(hIcon); - - if (pSmallIcon) - *pSmallIcon = hSmallIcon; - else - winDestroyIcon(hSmallIcon); -} - -void winDestroyIcon(HICON hIcon) -{ - /* Delete the icon if its not one of the application defaults or an override */ - if (hIcon && - hIcon != g_hIconX && - hIcon != g_hSmallIconX && - !winIconIsOverride((unsigned long)hIcon)) - DestroyIcon (hIcon); -} -#endif +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *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 XFREE86 PROJECT 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. + * + *Except as contained in this notice, the name of the XFree86 Project + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from the XFree86 Project. + * + * Authors: Earle F. Philhower, III + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include +#endif +#include "win.h" +#include "dixevents.h" +#include "winmultiwindowclass.h" +#include "winprefs.h" + +#include "propertyst.h" +#include "windowstr.h" + + +/* + * Prototypes for local functions + */ + +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) +{ + int row, column, effXBPP, effXDepth; + unsigned char *outPtr; + char *iconData = 0; + int stride, 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 = 16; + + if (pixmap->drawable.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); + 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); + + /* Keep aspect ratio */ + factX = ((float)pixmap->drawable.width) / ((float)iconSize); + factY = ((float)pixmap->drawable.height) / ((float)iconSize); + if (factX > factY) + factY = factX; + else + factX = factY; + + /* Out-of-bounds, fill icon with zero */ + zero = 0; + + for (row = 0; row < iconSize; row++) + { + outPtr = image + stride * row; + for (column = 0; column < iconSize; column++) + { + posX = factX * column; + posY = factY * row; + + ptr = (unsigned char*) iconData + posY*xStride; + if (effXBPP == 1) + { + ptr += posX / 8; + + /* Out of X icon bounds, leave space blank */ + if (posX >= pixmap->drawable.width + || posY >= pixmap->drawable.height) + ptr = (unsigned char *) &zero; + + if ((*ptr) & (1 << (posX & 7))) + switch (effBPP) + { + case 32: + *(outPtr++) = 0; + case 24: + *(outPtr++) = 0; + case 16: + *(outPtr++) = 0; + case 8: + *(outPtr++) = 0; + break; + case 1: + outPtr[column / 8] &= ~(1 << (7 - (column & 7))); + break; + } + else + switch (effBPP) + { + case 32: + *(outPtr++) = 255; + *(outPtr++) = 255; + *(outPtr++) = 255; + *(outPtr++) = 0; + break; + case 24: + *(outPtr++) = 255; + case 16: + *(outPtr++) = 255; + case 8: + *(outPtr++) = 255; + break; + case 1: + outPtr[column / 8] |= (1 << (7 - (column & 7))); + break; + } + } + else if (effXDepth == 24 || effXDepth == 32) + { + ptr += posX * (effXBPP / 8); + + /* Out of X icon bounds, leave space blank */ + if (posX >= pixmap->drawable.width + || posY >= pixmap->drawable.height) + ptr = (unsigned char *) &zero; + color = (((*ptr) << 16) + + ((*(ptr + 1)) << 8) + + ((*(ptr + 2)) << 0)); + switch (effBPP) + { + case 32: + *(outPtr++) = *(ptr++); /* b */ + *(outPtr++) = *(ptr++); /* g */ + *(outPtr++) = *(ptr++); /* r */ + *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */ + break; + case 24: + *(outPtr++) = *(ptr++); + *(outPtr++) = *(ptr++); + *(outPtr++) = *(ptr++); + break; + case 16: + color = ((((*ptr) >> 2) << 10) + + (((*(ptr + 1)) >> 2) << 5) + + (((*(ptr + 2)) >> 2))); + *(outPtr++) = (color >> 8); + *(outPtr++) = (color & 255); + break; + case 8: + color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2)))); + color /= 3; + *(outPtr++) = color; + break; + case 1: + if (color) + outPtr[column / 8] |= (1 << (7 - (column & 7))); + else + outPtr[column / 8] &= ~(1 << (7 - (column & 7))); + } + } + else if (effXDepth == 16) + { + ptr += posX * (effXBPP / 8); + + /* Out of X icon bounds, leave space blank */ + if (posX >= pixmap->drawable.width + || posY >= pixmap->drawable.height) + ptr = (unsigned char *) &zero; + color = ((*ptr) << 8) + (*(ptr + 1)); + switch (effBPP) + { + case 32: + *(outPtr++) = (color & 31) << 2; + *(outPtr++) = ((color >> 5) & 31) << 2; + *(outPtr++) = ((color >> 10) & 31) << 2; + *(outPtr++) = 0; /* resvd */ + break; + case 24: + *(outPtr++) = (color & 31) << 2; + *(outPtr++) = ((color >> 5) & 31) << 2; + *(outPtr++) = ((color >> 10) & 31) << 2; + break; + case 16: + *(outPtr++) = *(ptr++); + *(outPtr++) = *(ptr++); + break; + case 8: + *(outPtr++) = (((color & 31) + + ((color >> 5) & 31) + + ((color >> 10) & 31)) / 3) << 2; + break; + case 1: + if (color) + outPtr[column / 8] |= (1 << (7 - (column & 7))); + else + outPtr[column / 8] &= ~(1 << (7 - (column & 7))); + break; + } /* end switch(effbpp) */ + } /* end if effxbpp==16) */ + } /* end for column */ + } /* end for row */ + free (iconData); +} + +static HICON +NetWMToWinIconAlpha(uint32_t *icon) +{ + int width = icon[0]; + int height = icon[1]; + uint32_t *pixels = &icon[2]; + HICON result; + HDC hdc = GetDC(NULL); + uint32_t *DIB_pixels; + ICONINFO ii; + BITMAPV5HEADER bmh; + + /* Define an ARGB pixel format used for Color+Alpha icons */ + ZeroMemory(&bmh,sizeof(bmh)); + bmh.bV5Size = sizeof(bmh); + bmh.bV5Width = width; + bmh.bV5Height = -height; /* Invert the image */ + bmh.bV5Planes = 1; + bmh.bV5BitCount = 32; + bmh.bV5Compression = BI_BITFIELDS; + bmh.bV5AlphaMask = 0xFF000000; + bmh.bV5RedMask = 0x00FF0000; + bmh.bV5GreenMask = 0x0000FF00; + bmh.bV5BlueMask = 0x000000FF; + + ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO*)&bmh, + DIB_RGB_COLORS, (void**)&DIB_pixels, NULL, 0); + ReleaseDC(NULL, hdc); + ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL); + memcpy(DIB_pixels, pixels, height*width*4); + + /* CreateIconIndirect() traditionally required DDBitmaps */ + /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */ + /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */ + ii.fIcon = TRUE; + ii.xHotspot = 0; + ii.yHotspot = 0; + result = CreateIconIndirect(&ii); + + DeleteObject(ii.hbmColor); + DeleteObject(ii.hbmMask); + + winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result); + return result; +} + +static HICON +NetWMToWinIconThreshold(uint32_t *icon) +{ + int width = icon[0]; + int height = icon[1]; + uint32_t *pixels = &icon[2]; + int row, col; + HICON result; + ICONINFO ii; + + HDC hdc = GetDC(NULL); + HDC xorDC = CreateCompatibleDC(hdc); + HDC andDC = CreateCompatibleDC(hdc); + ii.hbmColor = CreateCompatibleBitmap(hdc, width, height); + ii.hbmMask = CreateCompatibleBitmap(hdc, width, height); + ReleaseDC(NULL, hdc); + SelectObject(xorDC, ii.hbmColor); + SelectObject(andDC, ii.hbmMask); + + for (row = 0; row < height; row++) { + for (col = 0; col < width; col++) { + if ((*pixels & 0xFF000000) > 31<<24) { /* 31 alpha threshold, i.e. opaque above, transparent below */ + SetPixelV(xorDC, col, row, RGB(((char*)pixels)[2], ((char*)pixels)[1], + ((char*)pixels)[0])); + SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */ + } + else { + SetPixelV(xorDC, col, row, RGB(0, 0, 0)); + SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */ + } + pixels++; + } + } + DeleteDC(xorDC); + DeleteDC(andDC); + + ii.fIcon = TRUE; + ii.xHotspot = 0; + ii.yHotspot = 0; + result = CreateIconIndirect(&ii); + + DeleteObject(ii.hbmColor); + DeleteObject(ii.hbmMask ); + + winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1], result); + return result; +} + +static HICON +NetWMToWinIcon(int bpp, uint32_t *icon) +{ + static Bool hasIconAlphaChannel = FALSE; + static BOOL versionChecked = FALSE; + + if (!versionChecked) + { + OSVERSIONINFOEX osvi = {0}; + ULONGLONG dwlConditionMask = 0; + + osvi.dwOSVersionInfoSize = sizeof (osvi); + osvi.dwMajorVersion = 5; + osvi.dwMinorVersion = 1; + + /* Windows versions later than XP have icon alpha channel suport, 2000 does not */ + VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); + hasIconAlphaChannel = VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask); + versionChecked = TRUE; + + winDebug("OS has icon alpha channel support: %s\n", hasIconAlphaChannel ? "yes" : "no"); + } + + if (hasIconAlphaChannel && (bpp==32)) + return NetWMToWinIconAlpha(icon); + else + 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) +{ + unsigned char *mask, *image, *imageMask; + unsigned char *dst, *src; + PixmapPtr iconPtr; + PixmapPtr maskPtr; + int planes, bpp, effBPP, stride, maskStride, i; + int biggest_size = 0; + HDC hDC; + ICONINFO ii; + WinXWMHints 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; + + hDC = GetDC (GetDesktopWindow ()); + planes = GetDeviceCaps (hDC, PLANES); + bpp = GetDeviceCaps (hDC, BITSPIXEL); + ReleaseDC (GetDesktopWindow (), hDC); + + if (generation != serverGeneration) { + generation = serverGeneration; + _XA_NET_WM_ICON = MakeAtom("_NET_WM_ICON", 12, TRUE); + } + + 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; + 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 */ + 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; + + dixLookupResourceByType((pointer) &iconPtr, hints.icon_pixmap, RT_PIXMAP, + NullClient, DixUnknownAccess); + + 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++; + } + + 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); + + return hIcon; +} + + + +/* + * Change the Windows window icon + */ + +#ifdef XWIN_MULTIWINDOW +void +winUpdateIcon (Window id) +{ + 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)); + } + } + + /* Set the large icon */ + hIconOld = (HICON) SendMessage (pWinPriv->hWnd, + WM_SETICON, ICON_BIG, (LPARAM) hIcon); + + /* 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); + } + } +} + +void winInitGlobalIcons (void) +{ + int sm_cx = GetSystemMetrics(SM_CXICON); + int sm_cxsm = GetSystemMetrics(SM_CXSMICON); + /* Load default X icon in case it's not ready yet */ + if (!g_hIconX) + { + g_hIconX = winOverrideDefaultIcon(sm_cx); + g_hSmallIconX = winOverrideDefaultIcon(sm_cxsm); + } + + if (!g_hIconX) + { + g_hIconX = (HICON)LoadImage (g_hInstance, + MAKEINTRESOURCE(IDI_XWIN), + IMAGE_ICON, + GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON), + 0); + g_hSmallIconX = (HICON)LoadImage (g_hInstance, + MAKEINTRESOURCE(IDI_XWIN), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTSIZE); + } +} + +void winSelectIcons(WindowPtr pWin, 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; + } + + if (pIcon) + *pIcon = hIcon; + else + winDestroyIcon(hIcon); + + if (pSmallIcon) + *pSmallIcon = hSmallIcon; + else + winDestroyIcon(hSmallIcon); +} + +void winDestroyIcon(HICON hIcon) +{ + /* Delete the icon if its not one of the application defaults or an override */ + if (hIcon && + hIcon != g_hIconX && + hIcon != g_hSmallIconX && + !winIconIsOverride((unsigned long)hIcon)) + DestroyIcon (hIcon); +} +#endif -- cgit v1.2.3