winmultiwindowicons.c revision 35c4bbdf
105b261ecSmrg/* 205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 305b261ecSmrg * 405b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining 505b261ecSmrg * a copy of this software and associated documentation files (the 605b261ecSmrg *"Software"), to deal in the Software without restriction, including 705b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish, 805b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to 905b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to 1005b261ecSmrg *the following conditions: 1105b261ecSmrg * 1205b261ecSmrg *The above copyright notice and this permission notice shall be 1305b261ecSmrg *included in all copies or substantial portions of the Software. 1405b261ecSmrg * 1505b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1605b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1705b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1805b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 1905b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 2005b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2105b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2205b261ecSmrg * 2305b261ecSmrg *Except as contained in this notice, the name of the XFree86 Project 2405b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use 2505b261ecSmrg *or other dealings in this Software without prior written authorization 2605b261ecSmrg *from the XFree86 Project. 2705b261ecSmrg * 2805b261ecSmrg * Authors: Earle F. Philhower, III 2905b261ecSmrg */ 3005b261ecSmrg 3105b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H 3205b261ecSmrg#include <xwin-config.h> 3305b261ecSmrg#endif 346747b715Smrg 3535c4bbdfSmrg#ifndef WINVER 3635c4bbdfSmrg#define WINVER 0x0500 3735c4bbdfSmrg#endif 3805b261ecSmrg 3935c4bbdfSmrg#include <X11/Xwindows.h> 4035c4bbdfSmrg#include <X11/Xlib.h> 4135c4bbdfSmrg#include <X11/Xutil.h> 4205b261ecSmrg 4335c4bbdfSmrg#include "winresource.h" 4435c4bbdfSmrg#include "winprefs.h" 4535c4bbdfSmrg#include "winmsg.h" 4635c4bbdfSmrg#include "winmultiwindowicons.h" 4735c4bbdfSmrg#include "winglobals.h" 4805b261ecSmrg/* 4935c4bbdfSmrg * global variables 5005b261ecSmrg */ 5135c4bbdfSmrgextern HINSTANCE g_hInstance; 5205b261ecSmrg 5305b261ecSmrg/* 5435c4bbdfSmrg * Scale an X icon ZPixmap into a Windoze icon bitmap 5505b261ecSmrg */ 5605b261ecSmrg 5705b261ecSmrgstatic void 5835c4bbdfSmrgwinScaleXImageToWindowsIcon(int iconSize, 5935c4bbdfSmrg int effBPP, 6035c4bbdfSmrg int stride, XImage * pixmap, unsigned char *image) 6105b261ecSmrg{ 6235c4bbdfSmrg int row, column, effXBPP, effXDepth; 6335c4bbdfSmrg unsigned char *outPtr; 6435c4bbdfSmrg unsigned char *iconData = 0; 6535c4bbdfSmrg int xStride; 6635c4bbdfSmrg float factX, factY; 6735c4bbdfSmrg int posX, posY; 6835c4bbdfSmrg unsigned char *ptr; 6935c4bbdfSmrg unsigned int zero; 7035c4bbdfSmrg unsigned int color; 7135c4bbdfSmrg 7235c4bbdfSmrg effXBPP = pixmap->bits_per_pixel; 7335c4bbdfSmrg if (pixmap->bits_per_pixel == 15) 7435c4bbdfSmrg effXBPP = 16; 7535c4bbdfSmrg 7635c4bbdfSmrg effXDepth = pixmap->depth; 7735c4bbdfSmrg if (pixmap->depth == 15) 7835c4bbdfSmrg effXDepth = 16; 7935c4bbdfSmrg 8035c4bbdfSmrg xStride = pixmap->bytes_per_line; 8135c4bbdfSmrg if (stride == 0 || xStride == 0) { 8235c4bbdfSmrg ErrorF("winScaleXBitmapToWindows - stride or xStride is zero. " 8335c4bbdfSmrg "Bailing.\n"); 8435c4bbdfSmrg return; 8505b261ecSmrg } 8605b261ecSmrg 8735c4bbdfSmrg /* Get icon data */ 8835c4bbdfSmrg iconData = (unsigned char *) pixmap->data; 8935c4bbdfSmrg 9035c4bbdfSmrg /* Keep aspect ratio */ 9135c4bbdfSmrg factX = ((float) pixmap->width) / ((float) iconSize); 9235c4bbdfSmrg factY = ((float) pixmap->height) / ((float) iconSize); 9335c4bbdfSmrg if (factX > factY) 9435c4bbdfSmrg factY = factX; 9535c4bbdfSmrg else 9635c4bbdfSmrg factX = factY; 9735c4bbdfSmrg 9835c4bbdfSmrg /* Out-of-bounds, fill icon with zero */ 9935c4bbdfSmrg zero = 0; 10035c4bbdfSmrg 10135c4bbdfSmrg for (row = 0; row < iconSize; row++) { 10235c4bbdfSmrg outPtr = image + stride * row; 10335c4bbdfSmrg for (column = 0; column < iconSize; column++) { 10435c4bbdfSmrg posX = factX * column; 10535c4bbdfSmrg posY = factY * row; 10635c4bbdfSmrg 10735c4bbdfSmrg ptr = (unsigned char *) iconData + posY * xStride; 10835c4bbdfSmrg if (effXBPP == 1) { 10935c4bbdfSmrg ptr += posX / 8; 11035c4bbdfSmrg 11135c4bbdfSmrg /* Out of X icon bounds, leave space blank */ 11235c4bbdfSmrg if (posX >= pixmap->width || posY >= pixmap->height) 11335c4bbdfSmrg ptr = (unsigned char *) &zero; 11435c4bbdfSmrg 11535c4bbdfSmrg if ((*ptr) & (1 << (posX & 7))) 11635c4bbdfSmrg switch (effBPP) { 11735c4bbdfSmrg case 32: 11835c4bbdfSmrg *(outPtr++) = 0; 11935c4bbdfSmrg case 24: 12035c4bbdfSmrg *(outPtr++) = 0; 12135c4bbdfSmrg case 16: 12235c4bbdfSmrg *(outPtr++) = 0; 12335c4bbdfSmrg case 8: 12435c4bbdfSmrg *(outPtr++) = 0; 12535c4bbdfSmrg break; 12635c4bbdfSmrg case 1: 12735c4bbdfSmrg outPtr[column / 8] &= ~(1 << (7 - (column & 7))); 12835c4bbdfSmrg break; 12935c4bbdfSmrg } 13035c4bbdfSmrg else 13135c4bbdfSmrg switch (effBPP) { 13235c4bbdfSmrg case 32: 13335c4bbdfSmrg *(outPtr++) = 255; 13435c4bbdfSmrg *(outPtr++) = 255; 13535c4bbdfSmrg *(outPtr++) = 255; 13635c4bbdfSmrg *(outPtr++) = 0; 13735c4bbdfSmrg break; 13835c4bbdfSmrg case 24: 13935c4bbdfSmrg *(outPtr++) = 255; 14035c4bbdfSmrg case 16: 14135c4bbdfSmrg *(outPtr++) = 255; 14235c4bbdfSmrg case 8: 14335c4bbdfSmrg *(outPtr++) = 255; 14435c4bbdfSmrg break; 14535c4bbdfSmrg case 1: 14635c4bbdfSmrg outPtr[column / 8] |= (1 << (7 - (column & 7))); 14735c4bbdfSmrg break; 14835c4bbdfSmrg } 14935c4bbdfSmrg } 15035c4bbdfSmrg else if (effXDepth == 24 || effXDepth == 32) { 15135c4bbdfSmrg ptr += posX * (effXBPP / 8); 15235c4bbdfSmrg 15335c4bbdfSmrg /* Out of X icon bounds, leave space blank */ 15435c4bbdfSmrg if (posX >= pixmap->width || posY >= pixmap->height) 15535c4bbdfSmrg ptr = (unsigned char *) &zero; 15635c4bbdfSmrg color = (((*ptr) << 16) 15735c4bbdfSmrg + ((*(ptr + 1)) << 8) 15835c4bbdfSmrg + ((*(ptr + 2)) << 0)); 15935c4bbdfSmrg switch (effBPP) { 16035c4bbdfSmrg case 32: 16135c4bbdfSmrg *(outPtr++) = *(ptr++); /* b */ 16235c4bbdfSmrg *(outPtr++) = *(ptr++); /* g */ 16335c4bbdfSmrg *(outPtr++) = *(ptr++); /* r */ 16435c4bbdfSmrg *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */ 16535c4bbdfSmrg break; 16635c4bbdfSmrg case 24: 16735c4bbdfSmrg *(outPtr++) = *(ptr++); 16835c4bbdfSmrg *(outPtr++) = *(ptr++); 16935c4bbdfSmrg *(outPtr++) = *(ptr++); 17035c4bbdfSmrg break; 17135c4bbdfSmrg case 16: 17235c4bbdfSmrg color = ((((*ptr) >> 2) << 10) 17335c4bbdfSmrg + (((*(ptr + 1)) >> 2) << 5) 17435c4bbdfSmrg + (((*(ptr + 2)) >> 2))); 17535c4bbdfSmrg *(outPtr++) = (color >> 8); 17635c4bbdfSmrg *(outPtr++) = (color & 255); 17735c4bbdfSmrg break; 17835c4bbdfSmrg case 8: 17935c4bbdfSmrg color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2)))); 18035c4bbdfSmrg color /= 3; 18135c4bbdfSmrg *(outPtr++) = color; 18235c4bbdfSmrg break; 18335c4bbdfSmrg case 1: 18435c4bbdfSmrg if (color) 18535c4bbdfSmrg outPtr[column / 8] |= (1 << (7 - (column & 7))); 18635c4bbdfSmrg else 18735c4bbdfSmrg outPtr[column / 8] &= ~(1 << (7 - (column & 7))); 18835c4bbdfSmrg } 18935c4bbdfSmrg } 19035c4bbdfSmrg else if (effXDepth == 16) { 19135c4bbdfSmrg ptr += posX * (effXBPP / 8); 19235c4bbdfSmrg 19335c4bbdfSmrg /* Out of X icon bounds, leave space blank */ 19435c4bbdfSmrg if (posX >= pixmap->width || posY >= pixmap->height) 19535c4bbdfSmrg ptr = (unsigned char *) &zero; 19635c4bbdfSmrg color = ((*ptr) << 8) + (*(ptr + 1)); 19735c4bbdfSmrg switch (effBPP) { 19835c4bbdfSmrg case 32: 19935c4bbdfSmrg *(outPtr++) = (color & 31) << 2; 20035c4bbdfSmrg *(outPtr++) = ((color >> 5) & 31) << 2; 20135c4bbdfSmrg *(outPtr++) = ((color >> 10) & 31) << 2; 20235c4bbdfSmrg *(outPtr++) = 0; /* resvd */ 20335c4bbdfSmrg break; 20435c4bbdfSmrg case 24: 20535c4bbdfSmrg *(outPtr++) = (color & 31) << 2; 20635c4bbdfSmrg *(outPtr++) = ((color >> 5) & 31) << 2; 20735c4bbdfSmrg *(outPtr++) = ((color >> 10) & 31) << 2; 20835c4bbdfSmrg break; 20935c4bbdfSmrg case 16: 21035c4bbdfSmrg *(outPtr++) = *(ptr++); 21135c4bbdfSmrg *(outPtr++) = *(ptr++); 21235c4bbdfSmrg break; 21335c4bbdfSmrg case 8: 21435c4bbdfSmrg *(outPtr++) = (((color & 31) 21535c4bbdfSmrg + ((color >> 5) & 31) 21635c4bbdfSmrg + ((color >> 10) & 31)) / 3) << 2; 21735c4bbdfSmrg break; 21835c4bbdfSmrg case 1: 21935c4bbdfSmrg if (color) 22035c4bbdfSmrg outPtr[column / 8] |= (1 << (7 - (column & 7))); 22135c4bbdfSmrg else 22235c4bbdfSmrg outPtr[column / 8] &= ~(1 << (7 - (column & 7))); 22335c4bbdfSmrg break; 22435c4bbdfSmrg } /* end switch(effbpp) */ 22535c4bbdfSmrg } /* end if effxbpp==16) */ 22635c4bbdfSmrg } /* end for column */ 22735c4bbdfSmrg } /* end for row */ 22805b261ecSmrg} 22905b261ecSmrg 2306747b715Smrgstatic HICON 23135c4bbdfSmrgNetWMToWinIconAlpha(uint32_t * icon) 2326747b715Smrg{ 23335c4bbdfSmrg int width = icon[0]; 23435c4bbdfSmrg int height = icon[1]; 23535c4bbdfSmrg uint32_t *pixels = &icon[2]; 23635c4bbdfSmrg HICON result; 23735c4bbdfSmrg HDC hdc = GetDC(NULL); 23835c4bbdfSmrg uint32_t *DIB_pixels; 23935c4bbdfSmrg ICONINFO ii; 24035c4bbdfSmrg BITMAPV4HEADER bmh = { sizeof(bmh) }; 24135c4bbdfSmrg 24235c4bbdfSmrg /* Define an ARGB pixel format used for Color+Alpha icons */ 24335c4bbdfSmrg bmh.bV4Width = width; 24435c4bbdfSmrg bmh.bV4Height = -height; /* Invert the image */ 24535c4bbdfSmrg bmh.bV4Planes = 1; 24635c4bbdfSmrg bmh.bV4BitCount = 32; 24735c4bbdfSmrg bmh.bV4V4Compression = BI_BITFIELDS; 24835c4bbdfSmrg bmh.bV4AlphaMask = 0xFF000000; 24935c4bbdfSmrg bmh.bV4RedMask = 0x00FF0000; 25035c4bbdfSmrg bmh.bV4GreenMask = 0x0000FF00; 25135c4bbdfSmrg bmh.bV4BlueMask = 0x000000FF; 25235c4bbdfSmrg 25335c4bbdfSmrg ii.fIcon = TRUE; 25435c4bbdfSmrg ii.xHotspot = 0; /* ignored */ 25535c4bbdfSmrg ii.yHotspot = 0; /* ignored */ 25635c4bbdfSmrg ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) &bmh, 25735c4bbdfSmrg DIB_RGB_COLORS, (void **) &DIB_pixels, NULL, 25835c4bbdfSmrg 0); 25935c4bbdfSmrg ReleaseDC(NULL, hdc); 26035c4bbdfSmrg 26135c4bbdfSmrg if (!ii.hbmColor) 26235c4bbdfSmrg return NULL; 26335c4bbdfSmrg 26435c4bbdfSmrg ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL); 26535c4bbdfSmrg memcpy(DIB_pixels, pixels, height * width * 4); 26635c4bbdfSmrg 26735c4bbdfSmrg /* CreateIconIndirect() traditionally required DDBitmaps */ 26835c4bbdfSmrg /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */ 26935c4bbdfSmrg /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */ 27035c4bbdfSmrg result = CreateIconIndirect(&ii); 27135c4bbdfSmrg 27235c4bbdfSmrg DeleteObject(ii.hbmColor); 27335c4bbdfSmrg DeleteObject(ii.hbmMask); 27435c4bbdfSmrg 27535c4bbdfSmrg winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result); 27635c4bbdfSmrg return result; 2776747b715Smrg} 2786747b715Smrg 2796747b715Smrgstatic HICON 28035c4bbdfSmrgNetWMToWinIconThreshold(uint32_t * icon) 2816747b715Smrg{ 28235c4bbdfSmrg int width = icon[0]; 28335c4bbdfSmrg int height = icon[1]; 28435c4bbdfSmrg uint32_t *pixels = &icon[2]; 28535c4bbdfSmrg int row, col; 28635c4bbdfSmrg HICON result; 28735c4bbdfSmrg ICONINFO ii; 28835c4bbdfSmrg 28935c4bbdfSmrg HDC hdc = GetDC(NULL); 29035c4bbdfSmrg HDC xorDC = CreateCompatibleDC(hdc); 29135c4bbdfSmrg HDC andDC = CreateCompatibleDC(hdc); 29235c4bbdfSmrg 29335c4bbdfSmrg ii.fIcon = TRUE; 29435c4bbdfSmrg ii.xHotspot = 0; /* ignored */ 29535c4bbdfSmrg ii.yHotspot = 0; /* ignored */ 29635c4bbdfSmrg ii.hbmColor = CreateCompatibleBitmap(hdc, width, height); 29735c4bbdfSmrg ii.hbmMask = CreateCompatibleBitmap(hdc, width, height); 29835c4bbdfSmrg ReleaseDC(NULL, hdc); 29935c4bbdfSmrg SelectObject(xorDC, ii.hbmColor); 30035c4bbdfSmrg SelectObject(andDC, ii.hbmMask); 30135c4bbdfSmrg 30235c4bbdfSmrg for (row = 0; row < height; row++) { 30335c4bbdfSmrg for (col = 0; col < width; col++) { 30435c4bbdfSmrg if ((*pixels & 0xFF000000) > 31 << 24) { /* 31 alpha threshold, i.e. opaque above, transparent below */ 30535c4bbdfSmrg SetPixelV(xorDC, col, row, 30635c4bbdfSmrg RGB(((char *) pixels)[2], ((char *) pixels)[1], 30735c4bbdfSmrg ((char *) pixels)[0])); 30835c4bbdfSmrg SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */ 30935c4bbdfSmrg } 31035c4bbdfSmrg else { 31135c4bbdfSmrg SetPixelV(xorDC, col, row, RGB(0, 0, 0)); 31235c4bbdfSmrg SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */ 31335c4bbdfSmrg } 31435c4bbdfSmrg pixels++; 31535c4bbdfSmrg } 3166747b715Smrg } 31735c4bbdfSmrg DeleteDC(xorDC); 31835c4bbdfSmrg DeleteDC(andDC); 3196747b715Smrg 32035c4bbdfSmrg result = CreateIconIndirect(&ii); 3216747b715Smrg 32235c4bbdfSmrg DeleteObject(ii.hbmColor); 32335c4bbdfSmrg DeleteObject(ii.hbmMask); 3246747b715Smrg 32535c4bbdfSmrg winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1], 32635c4bbdfSmrg result); 32735c4bbdfSmrg return result; 3286747b715Smrg} 3296747b715Smrg 3306747b715Smrgstatic HICON 33135c4bbdfSmrgNetWMToWinIcon(int bpp, uint32_t * icon) 3326747b715Smrg{ 33335c4bbdfSmrg static Bool hasIconAlphaChannel = FALSE; 33435c4bbdfSmrg static BOOL versionChecked = FALSE; 33535c4bbdfSmrg 33635c4bbdfSmrg if (!versionChecked) { 33735c4bbdfSmrg OSVERSIONINFOEX osvi = { 0 }; 33835c4bbdfSmrg ULONGLONG dwlConditionMask = 0; 33935c4bbdfSmrg 34035c4bbdfSmrg osvi.dwOSVersionInfoSize = sizeof(osvi); 34135c4bbdfSmrg osvi.dwMajorVersion = 5; 34235c4bbdfSmrg osvi.dwMinorVersion = 1; 34335c4bbdfSmrg 34435c4bbdfSmrg /* Windows versions later than XP have icon alpha channel suport, 2000 does not */ 34535c4bbdfSmrg VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, 34635c4bbdfSmrg VER_GREATER_EQUAL); 34735c4bbdfSmrg VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, 34835c4bbdfSmrg VER_GREATER_EQUAL); 34935c4bbdfSmrg hasIconAlphaChannel = 35035c4bbdfSmrg VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, 35135c4bbdfSmrg dwlConditionMask); 35235c4bbdfSmrg versionChecked = TRUE; 35335c4bbdfSmrg 35435c4bbdfSmrg ErrorF("OS has icon alpha channel support: %s\n", 35535c4bbdfSmrg hasIconAlphaChannel ? "yes" : "no"); 3566747b715Smrg } 3576747b715Smrg 35835c4bbdfSmrg if (hasIconAlphaChannel && (bpp == 32)) 35935c4bbdfSmrg return NetWMToWinIconAlpha(icon); 36035c4bbdfSmrg else 36135c4bbdfSmrg return NetWMToWinIconThreshold(icon); 3626747b715Smrg} 36305b261ecSmrg 36405b261ecSmrg/* 36505b261ecSmrg * Attempt to create a custom icon from the WM_HINTS bitmaps 36605b261ecSmrg */ 36705b261ecSmrg 36835c4bbdfSmrgstatic 36935c4bbdfSmrg HICON 37035c4bbdfSmrgwinXIconToHICON(Display * pDisplay, Window id, int iconSize) 37105b261ecSmrg{ 37235c4bbdfSmrg unsigned char *mask, *image = NULL, *imageMask; 37335c4bbdfSmrg unsigned char *dst, *src; 37435c4bbdfSmrg int planes, bpp, i; 37535c4bbdfSmrg unsigned int biggest_size = 0; 37635c4bbdfSmrg HDC hDC; 37735c4bbdfSmrg ICONINFO ii; 37835c4bbdfSmrg XWMHints *hints; 37935c4bbdfSmrg HICON hIcon = NULL; 38035c4bbdfSmrg uint32_t *biggest_icon = NULL; 38135c4bbdfSmrg static Atom _XA_NET_WM_ICON; 38235c4bbdfSmrg static int generation; 38335c4bbdfSmrg uint32_t *icon, *icon_data = NULL; 38435c4bbdfSmrg unsigned long int size; 38535c4bbdfSmrg Atom type; 38635c4bbdfSmrg int format; 38735c4bbdfSmrg unsigned long int left; 38835c4bbdfSmrg 38935c4bbdfSmrg hDC = GetDC(GetDesktopWindow()); 39035c4bbdfSmrg planes = GetDeviceCaps(hDC, PLANES); 39135c4bbdfSmrg bpp = GetDeviceCaps(hDC, BITSPIXEL); 39235c4bbdfSmrg ReleaseDC(GetDesktopWindow(), hDC); 39335c4bbdfSmrg 39435c4bbdfSmrg /* Always prefer _NET_WM_ICON icons */ 39535c4bbdfSmrg if (generation != serverGeneration) { 39635c4bbdfSmrg generation = serverGeneration; 39735c4bbdfSmrg _XA_NET_WM_ICON = XInternAtom(pDisplay, "_NET_WM_ICON", FALSE); 39805b261ecSmrg } 39905b261ecSmrg 40035c4bbdfSmrg if ((XGetWindowProperty(pDisplay, id, _XA_NET_WM_ICON, 40135c4bbdfSmrg 0, MAXINT, FALSE, 40235c4bbdfSmrg AnyPropertyType, &type, &format, &size, &left, 40335c4bbdfSmrg (unsigned char **) &icon_data) == Success) && 40435c4bbdfSmrg (icon_data != NULL)) { 40535c4bbdfSmrg for (icon = icon_data; icon < &icon_data[size] && *icon; 40635c4bbdfSmrg icon = &icon[icon[0] * icon[1] + 2]) { 40735c4bbdfSmrg winDebug("winXIconToHICON: %u x %u NetIcon\n", icon[0], icon[1]); 40835c4bbdfSmrg 40935c4bbdfSmrg /* Icon data size will overflow an int and thus is bigger than the 41035c4bbdfSmrg property can possibly be */ 41135c4bbdfSmrg if ((INT_MAX/icon[0]) < icon[1]) { 41235c4bbdfSmrg winDebug("winXIconToHICON: _NET_WM_ICON icon data size overflow\n"); 41335c4bbdfSmrg break; 41435c4bbdfSmrg } 41535c4bbdfSmrg 41635c4bbdfSmrg /* Icon data size is bigger than amount of data remaining */ 41735c4bbdfSmrg if (&icon[icon[0] * icon[1] + 2] > &icon_data[size]) { 41835c4bbdfSmrg winDebug("winXIconToHICON: _NET_WM_ICON data is malformed\n"); 41935c4bbdfSmrg break; 42035c4bbdfSmrg } 42135c4bbdfSmrg 42235c4bbdfSmrg /* Found an exact match to the size we require... */ 42335c4bbdfSmrg if (icon[0] == iconSize && icon[1] == iconSize) { 42435c4bbdfSmrg winDebug("winXIconToHICON: selected %d x %d NetIcon\n", 42535c4bbdfSmrg iconSize, iconSize); 42635c4bbdfSmrg hIcon = NetWMToWinIcon(bpp, icon); 42735c4bbdfSmrg break; 42835c4bbdfSmrg } 42935c4bbdfSmrg /* Otherwise, find the biggest icon and let Windows scale the size */ 43035c4bbdfSmrg else if (biggest_size < icon[0]) { 43135c4bbdfSmrg biggest_icon = icon; 43235c4bbdfSmrg biggest_size = icon[0]; 43335c4bbdfSmrg } 43435c4bbdfSmrg } 43505b261ecSmrg 43635c4bbdfSmrg if (!hIcon && biggest_icon) { 43735c4bbdfSmrg winDebug 43835c4bbdfSmrg ("winXIconToHICON: selected %u x %u NetIcon for scaling to %d x %d\n", 43935c4bbdfSmrg biggest_icon[0], biggest_icon[1], iconSize, iconSize); 44035c4bbdfSmrg 44135c4bbdfSmrg hIcon = NetWMToWinIcon(bpp, biggest_icon); 44235c4bbdfSmrg } 44335c4bbdfSmrg 44435c4bbdfSmrg XFree(icon_data); 44535c4bbdfSmrg } 44635c4bbdfSmrg 44735c4bbdfSmrg if (!hIcon) { 44835c4bbdfSmrg winDebug("winXIconToHICON: no suitable NetIcon\n"); 44935c4bbdfSmrg 45035c4bbdfSmrg hints = XGetWMHints(pDisplay, id); 45135c4bbdfSmrg if (hints) { 45235c4bbdfSmrg winDebug("winXIconToHICON: id 0x%x icon_pixmap hint 0x%x\n", 45335c4bbdfSmrg (unsigned int)id, 45435c4bbdfSmrg (unsigned int)hints->icon_pixmap); 45535c4bbdfSmrg 45635c4bbdfSmrg if (hints->icon_pixmap) { 45735c4bbdfSmrg Window root; 45835c4bbdfSmrg int x, y; 45935c4bbdfSmrg unsigned int width, height, border_width, depth; 46035c4bbdfSmrg XImage *xImageIcon; 46135c4bbdfSmrg XImage *xImageMask = NULL; 46235c4bbdfSmrg 46335c4bbdfSmrg XGetGeometry(pDisplay, hints->icon_pixmap, &root, &x, &y, 46435c4bbdfSmrg &width, &height, &border_width, &depth); 46535c4bbdfSmrg 46635c4bbdfSmrg xImageIcon = 46735c4bbdfSmrg XGetImage(pDisplay, hints->icon_pixmap, 0, 0, width, height, 46835c4bbdfSmrg 0xFFFFFFFF, ZPixmap); 46935c4bbdfSmrg winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%p\n", 47035c4bbdfSmrg (unsigned int)id, xImageIcon); 47135c4bbdfSmrg 47235c4bbdfSmrg if (hints->icon_mask) 47335c4bbdfSmrg xImageMask = 47435c4bbdfSmrg XGetImage(pDisplay, hints->icon_mask, 0, 0, width, 47535c4bbdfSmrg height, 0xFFFFFFFF, ZPixmap); 47635c4bbdfSmrg 47735c4bbdfSmrg if (xImageIcon) { 47835c4bbdfSmrg int effBPP, stride, maskStride; 47935c4bbdfSmrg 48035c4bbdfSmrg /* 15 BPP is really 16BPP as far as we care */ 48135c4bbdfSmrg if (bpp == 15) 48235c4bbdfSmrg effBPP = 16; 48335c4bbdfSmrg else 48435c4bbdfSmrg effBPP = bpp; 48535c4bbdfSmrg 48635c4bbdfSmrg /* Need 16-bit aligned rows for DDBitmaps */ 48735c4bbdfSmrg stride = ((iconSize * effBPP + 15) & (~15)) / 8; 48835c4bbdfSmrg 48935c4bbdfSmrg /* Mask is 1-bit deep */ 49035c4bbdfSmrg maskStride = ((iconSize * 1 + 15) & (~15)) / 8; 49135c4bbdfSmrg 49235c4bbdfSmrg image = malloc(stride * iconSize); 49335c4bbdfSmrg imageMask = malloc(stride * iconSize); 49435c4bbdfSmrg mask = malloc(maskStride * iconSize); 49535c4bbdfSmrg 49635c4bbdfSmrg /* Default to a completely black mask */ 49735c4bbdfSmrg memset(imageMask, 0, stride * iconSize); 49835c4bbdfSmrg memset(mask, 0, maskStride * iconSize); 49935c4bbdfSmrg 50035c4bbdfSmrg winScaleXImageToWindowsIcon(iconSize, effBPP, stride, 50135c4bbdfSmrg xImageIcon, image); 50235c4bbdfSmrg 50335c4bbdfSmrg if (xImageMask) { 50435c4bbdfSmrg winScaleXImageToWindowsIcon(iconSize, 1, maskStride, 50535c4bbdfSmrg xImageMask, mask); 50635c4bbdfSmrg winScaleXImageToWindowsIcon(iconSize, effBPP, stride, 50735c4bbdfSmrg xImageMask, imageMask); 50835c4bbdfSmrg } 50935c4bbdfSmrg 51035c4bbdfSmrg /* Now we need to set all bits of the icon which are not masked */ 51135c4bbdfSmrg /* on to 0 because Color is really an XOR, not an OR function */ 51235c4bbdfSmrg dst = image; 51335c4bbdfSmrg src = imageMask; 51435c4bbdfSmrg 51535c4bbdfSmrg for (i = 0; i < (stride * iconSize); i++) 51635c4bbdfSmrg if ((*(src++))) 51735c4bbdfSmrg *(dst++) = 0; 51835c4bbdfSmrg else 51935c4bbdfSmrg dst++; 52035c4bbdfSmrg 52135c4bbdfSmrg ii.fIcon = TRUE; 52235c4bbdfSmrg ii.xHotspot = 0; /* ignored */ 52335c4bbdfSmrg ii.yHotspot = 0; /* ignored */ 52435c4bbdfSmrg 52535c4bbdfSmrg /* Create Win32 mask from pixmap shape */ 52635c4bbdfSmrg ii.hbmMask = 52735c4bbdfSmrg CreateBitmap(iconSize, iconSize, planes, 1, mask); 52835c4bbdfSmrg 52935c4bbdfSmrg /* Create Win32 bitmap from pixmap */ 53035c4bbdfSmrg ii.hbmColor = 53135c4bbdfSmrg CreateBitmap(iconSize, iconSize, planes, bpp, image); 53235c4bbdfSmrg 53335c4bbdfSmrg /* Merge Win32 mask and bitmap into icon */ 53435c4bbdfSmrg hIcon = CreateIconIndirect(&ii); 53535c4bbdfSmrg 53635c4bbdfSmrg /* Release Win32 mask and bitmap */ 53735c4bbdfSmrg DeleteObject(ii.hbmMask); 53835c4bbdfSmrg DeleteObject(ii.hbmColor); 53935c4bbdfSmrg 54035c4bbdfSmrg /* Free X mask and bitmap */ 54135c4bbdfSmrg free(mask); 54235c4bbdfSmrg free(image); 54335c4bbdfSmrg free(imageMask); 54435c4bbdfSmrg 54535c4bbdfSmrg if (xImageMask) 54635c4bbdfSmrg XDestroyImage(xImageMask); 54735c4bbdfSmrg 54835c4bbdfSmrg XDestroyImage(xImageIcon); 54935c4bbdfSmrg } 55035c4bbdfSmrg } 55135c4bbdfSmrg XFree(hints); 55235c4bbdfSmrg } 55335c4bbdfSmrg } 55435c4bbdfSmrg return hIcon; 55535c4bbdfSmrg} 55605b261ecSmrg 55705b261ecSmrg/* 55835c4bbdfSmrg * Change the Windows window icon 55905b261ecSmrg */ 56005b261ecSmrg 56105b261ecSmrg#ifdef XWIN_MULTIWINDOW 56205b261ecSmrgvoid 56335c4bbdfSmrgwinUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew) 56405b261ecSmrg{ 56535c4bbdfSmrg HICON hIcon, hIconSmall = NULL, hIconOld; 56635c4bbdfSmrg 56735c4bbdfSmrg /* Start with the icon from preferences, if any */ 56835c4bbdfSmrg hIcon = hIconNew; 56935c4bbdfSmrg hIconSmall = hIconNew; 57035c4bbdfSmrg 57135c4bbdfSmrg /* If we still need an icon, try and get the icon from WM_HINTS */ 57235c4bbdfSmrg if (!hIcon) 57335c4bbdfSmrg hIcon = winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXICON)); 57435c4bbdfSmrg if (!hIconSmall) 57535c4bbdfSmrg hIconSmall = 57635c4bbdfSmrg winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXSMICON)); 57735c4bbdfSmrg 57835c4bbdfSmrg /* If we got the small, but not the large one swap them */ 57935c4bbdfSmrg if (!hIcon && hIconSmall) { 58035c4bbdfSmrg hIcon = hIconSmall; 58135c4bbdfSmrg hIconSmall = NULL; 58235c4bbdfSmrg } 5836747b715Smrg 58435c4bbdfSmrg /* Set the large icon */ 58535c4bbdfSmrg hIconOld = (HICON) SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon); 58635c4bbdfSmrg /* Delete the old icon if its not the default */ 58735c4bbdfSmrg winDestroyIcon(hIconOld); 5886747b715Smrg 58935c4bbdfSmrg /* Same for the small icon */ 59035c4bbdfSmrg hIconOld = 59135c4bbdfSmrg (HICON) SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall); 59235c4bbdfSmrg winDestroyIcon(hIconOld); 59305b261ecSmrg} 59405b261ecSmrg 59535c4bbdfSmrgvoid 59635c4bbdfSmrgwinInitGlobalIcons(void) 59705b261ecSmrg{ 59835c4bbdfSmrg int sm_cx = GetSystemMetrics(SM_CXICON); 59935c4bbdfSmrg int sm_cxsm = GetSystemMetrics(SM_CXSMICON); 60035c4bbdfSmrg 60135c4bbdfSmrg /* Load default X icon in case it's not ready yet */ 60235c4bbdfSmrg if (!g_hIconX) { 60335c4bbdfSmrg g_hIconX = winOverrideDefaultIcon(sm_cx); 60435c4bbdfSmrg g_hSmallIconX = winOverrideDefaultIcon(sm_cxsm); 60505b261ecSmrg } 60635c4bbdfSmrg 60735c4bbdfSmrg if (!g_hIconX) { 60835c4bbdfSmrg g_hIconX = (HICON) LoadImage(g_hInstance, 60935c4bbdfSmrg MAKEINTRESOURCE(IDI_XWIN), 61035c4bbdfSmrg IMAGE_ICON, 61135c4bbdfSmrg GetSystemMetrics(SM_CXICON), 61235c4bbdfSmrg GetSystemMetrics(SM_CYICON), 0); 61335c4bbdfSmrg g_hSmallIconX = (HICON) LoadImage(g_hInstance, 61435c4bbdfSmrg MAKEINTRESOURCE(IDI_XWIN), 61535c4bbdfSmrg IMAGE_ICON, 61635c4bbdfSmrg GetSystemMetrics(SM_CXSMICON), 61735c4bbdfSmrg GetSystemMetrics(SM_CYSMICON), 61835c4bbdfSmrg LR_DEFAULTSIZE); 61905b261ecSmrg } 62005b261ecSmrg} 62105b261ecSmrg 62235c4bbdfSmrgvoid 62335c4bbdfSmrgwinSelectIcons(HICON * pIcon, HICON * pSmallIcon) 62405b261ecSmrg{ 62535c4bbdfSmrg HICON hIcon, hSmallIcon; 62635c4bbdfSmrg 62735c4bbdfSmrg winInitGlobalIcons(); 62835c4bbdfSmrg 62935c4bbdfSmrg /* Use default X icon */ 63005b261ecSmrg hIcon = g_hIconX; 63105b261ecSmrg hSmallIcon = g_hSmallIconX; 63235c4bbdfSmrg 63335c4bbdfSmrg if (pIcon) 63435c4bbdfSmrg *pIcon = hIcon; 63535c4bbdfSmrg 63635c4bbdfSmrg if (pSmallIcon) 63735c4bbdfSmrg *pSmallIcon = hSmallIcon; 63805b261ecSmrg} 63905b261ecSmrg 64035c4bbdfSmrgvoid 64135c4bbdfSmrgwinDestroyIcon(HICON hIcon) 64205b261ecSmrg{ 64335c4bbdfSmrg /* Delete the icon if its not one of the application defaults or an override */ 64435c4bbdfSmrg if (hIcon && 64535c4bbdfSmrg hIcon != g_hIconX && 64635c4bbdfSmrg hIcon != g_hSmallIconX && !winIconIsOverride(hIcon)) 64735c4bbdfSmrg DestroyIcon(hIcon); 64805b261ecSmrg} 64905b261ecSmrg#endif 650