1706f2543Smrg/* 2706f2543Smrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 3706f2543Smrg * 4706f2543Smrg *Permission is hereby granted, free of charge, to any person obtaining 5706f2543Smrg * a copy of this software and associated documentation files (the 6706f2543Smrg *"Software"), to deal in the Software without restriction, including 7706f2543Smrg *without limitation the rights to use, copy, modify, merge, publish, 8706f2543Smrg *distribute, sublicense, and/or sell copies of the Software, and to 9706f2543Smrg *permit persons to whom the Software is furnished to do so, subject to 10706f2543Smrg *the following conditions: 11706f2543Smrg * 12706f2543Smrg *The above copyright notice and this permission notice shall be 13706f2543Smrg *included in all copies or substantial portions of the Software. 14706f2543Smrg * 15706f2543Smrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16706f2543Smrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17706f2543Smrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18706f2543Smrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 19706f2543Smrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 20706f2543Smrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21706f2543Smrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22706f2543Smrg * 23706f2543Smrg *Except as contained in this notice, the name of the XFree86 Project 24706f2543Smrg *shall not be used in advertising or otherwise to promote the sale, use 25706f2543Smrg *or other dealings in this Software without prior written authorization 26706f2543Smrg *from the XFree86 Project. 27706f2543Smrg * 28706f2543Smrg * Authors: Earle F. Philhower, III 29706f2543Smrg */ 30706f2543Smrg 31706f2543Smrg#ifdef HAVE_XWIN_CONFIG_H 32706f2543Smrg#include <xwin-config.h> 33706f2543Smrg#endif 34706f2543Smrg#include "win.h" 35706f2543Smrg#include "dixevents.h" 36706f2543Smrg#include "winmultiwindowclass.h" 37706f2543Smrg#include "winprefs.h" 38706f2543Smrg 39706f2543Smrg#include "propertyst.h" 40706f2543Smrg 41706f2543Smrg#include "propertyst.h" 42706f2543Smrg#include "windowstr.h" 43706f2543Smrg 44706f2543Smrg 45706f2543Smrg/* 46706f2543Smrg * Prototypes for local functions 47706f2543Smrg */ 48706f2543Smrg 49706f2543Smrgstatic void 50706f2543SmrgwinScaleXBitmapToWindows (int iconSize, int effBPP, 51706f2543Smrg PixmapPtr pixmap, unsigned char *image); 52706f2543Smrg 53706f2543Smrg 54706f2543Smrg/* 55706f2543Smrg * Scale an X icon bitmap into a Windoze icon bitmap 56706f2543Smrg */ 57706f2543Smrg 58706f2543Smrgstatic void 59706f2543SmrgwinScaleXBitmapToWindows (int iconSize, 60706f2543Smrg int effBPP, 61706f2543Smrg PixmapPtr pixmap, 62706f2543Smrg unsigned char *image) 63706f2543Smrg{ 64706f2543Smrg int row, column, effXBPP, effXDepth; 65706f2543Smrg unsigned char *outPtr; 66706f2543Smrg char *iconData = 0; 67706f2543Smrg int stride, xStride; 68706f2543Smrg float factX, factY; 69706f2543Smrg int posX, posY; 70706f2543Smrg unsigned char *ptr; 71706f2543Smrg unsigned int zero; 72706f2543Smrg unsigned int color; 73706f2543Smrg 74706f2543Smrg effXBPP = BitsPerPixel(pixmap->drawable.depth); 75706f2543Smrg effXDepth = pixmap->drawable.depth; 76706f2543Smrg 77706f2543Smrg if (pixmap->drawable.bitsPerPixel == 15) 78706f2543Smrg effXBPP = 16; 79706f2543Smrg 80706f2543Smrg if (pixmap->drawable.depth == 15) 81706f2543Smrg effXDepth = 16; 82706f2543Smrg 83706f2543Smrg /* Need 16-bit aligned rows for DDBitmaps */ 84706f2543Smrg stride = ((iconSize * effBPP + 15) & (~15)) / 8; 85706f2543Smrg xStride = PixmapBytePad (pixmap->drawable.width, pixmap->drawable.depth); 86706f2543Smrg if (stride == 0 || xStride == 0) 87706f2543Smrg { 88706f2543Smrg ErrorF ("winScaleXBitmapToWindows - stride or xStride is zero. " 89706f2543Smrg "Bailing.\n"); 90706f2543Smrg return; 91706f2543Smrg } 92706f2543Smrg 93706f2543Smrg /* Allocate memory for icon data */ 94706f2543Smrg iconData = malloc (xStride * pixmap->drawable.height); 95706f2543Smrg if (!iconData) 96706f2543Smrg { 97706f2543Smrg ErrorF ("winScaleXBitmapToWindows - malloc failed for iconData. " 98706f2543Smrg "Bailing.\n"); 99706f2543Smrg return; 100706f2543Smrg } 101706f2543Smrg 102706f2543Smrg /* Get icon data */ 103706f2543Smrg miGetImage ((DrawablePtr) &(pixmap->drawable), 0, 0, 104706f2543Smrg pixmap->drawable.width, pixmap->drawable.height, 105706f2543Smrg ZPixmap, 0xffffffff, iconData); 106706f2543Smrg 107706f2543Smrg /* Keep aspect ratio */ 108706f2543Smrg factX = ((float)pixmap->drawable.width) / ((float)iconSize); 109706f2543Smrg factY = ((float)pixmap->drawable.height) / ((float)iconSize); 110706f2543Smrg if (factX > factY) 111706f2543Smrg factY = factX; 112706f2543Smrg else 113706f2543Smrg factX = factY; 114706f2543Smrg 115706f2543Smrg /* Out-of-bounds, fill icon with zero */ 116706f2543Smrg zero = 0; 117706f2543Smrg 118706f2543Smrg for (row = 0; row < iconSize; row++) 119706f2543Smrg { 120706f2543Smrg outPtr = image + stride * row; 121706f2543Smrg for (column = 0; column < iconSize; column++) 122706f2543Smrg { 123706f2543Smrg posX = factX * column; 124706f2543Smrg posY = factY * row; 125706f2543Smrg 126706f2543Smrg ptr = (unsigned char*) iconData + posY*xStride; 127706f2543Smrg if (effXBPP == 1) 128706f2543Smrg { 129706f2543Smrg ptr += posX / 8; 130706f2543Smrg 131706f2543Smrg /* Out of X icon bounds, leave space blank */ 132706f2543Smrg if (posX >= pixmap->drawable.width 133706f2543Smrg || posY >= pixmap->drawable.height) 134706f2543Smrg ptr = (unsigned char *) &zero; 135706f2543Smrg 136706f2543Smrg if ((*ptr) & (1 << (posX & 7))) 137706f2543Smrg switch (effBPP) 138706f2543Smrg { 139706f2543Smrg case 32: 140706f2543Smrg *(outPtr++) = 0; 141706f2543Smrg case 24: 142706f2543Smrg *(outPtr++) = 0; 143706f2543Smrg case 16: 144706f2543Smrg *(outPtr++) = 0; 145706f2543Smrg case 8: 146706f2543Smrg *(outPtr++) = 0; 147706f2543Smrg break; 148706f2543Smrg case 1: 149706f2543Smrg outPtr[column / 8] &= ~(1 << (7 - (column & 7))); 150706f2543Smrg break; 151706f2543Smrg } 152706f2543Smrg else 153706f2543Smrg switch (effBPP) 154706f2543Smrg { 155706f2543Smrg case 32: 156706f2543Smrg *(outPtr++) = 255; 157706f2543Smrg *(outPtr++) = 255; 158706f2543Smrg *(outPtr++) = 255; 159706f2543Smrg *(outPtr++) = 0; 160706f2543Smrg break; 161706f2543Smrg case 24: 162706f2543Smrg *(outPtr++) = 255; 163706f2543Smrg case 16: 164706f2543Smrg *(outPtr++) = 255; 165706f2543Smrg case 8: 166706f2543Smrg *(outPtr++) = 255; 167706f2543Smrg break; 168706f2543Smrg case 1: 169706f2543Smrg outPtr[column / 8] |= (1 << (7 - (column & 7))); 170706f2543Smrg break; 171706f2543Smrg } 172706f2543Smrg } 173706f2543Smrg else if (effXDepth == 24 || effXDepth == 32) 174706f2543Smrg { 175706f2543Smrg ptr += posX * (effXBPP / 8); 176706f2543Smrg 177706f2543Smrg /* Out of X icon bounds, leave space blank */ 178706f2543Smrg if (posX >= pixmap->drawable.width 179706f2543Smrg || posY >= pixmap->drawable.height) 180706f2543Smrg ptr = (unsigned char *) &zero; 181706f2543Smrg color = (((*ptr) << 16) 182706f2543Smrg + ((*(ptr + 1)) << 8) 183706f2543Smrg + ((*(ptr + 2)) << 0)); 184706f2543Smrg switch (effBPP) 185706f2543Smrg { 186706f2543Smrg case 32: 187706f2543Smrg *(outPtr++) = *(ptr++); /* b */ 188706f2543Smrg *(outPtr++) = *(ptr++); /* g */ 189706f2543Smrg *(outPtr++) = *(ptr++); /* r */ 190706f2543Smrg *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */ 191706f2543Smrg break; 192706f2543Smrg case 24: 193706f2543Smrg *(outPtr++) = *(ptr++); 194706f2543Smrg *(outPtr++) = *(ptr++); 195706f2543Smrg *(outPtr++) = *(ptr++); 196706f2543Smrg break; 197706f2543Smrg case 16: 198706f2543Smrg color = ((((*ptr) >> 2) << 10) 199706f2543Smrg + (((*(ptr + 1)) >> 2) << 5) 200706f2543Smrg + (((*(ptr + 2)) >> 2))); 201706f2543Smrg *(outPtr++) = (color >> 8); 202706f2543Smrg *(outPtr++) = (color & 255); 203706f2543Smrg break; 204706f2543Smrg case 8: 205706f2543Smrg color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2)))); 206706f2543Smrg color /= 3; 207706f2543Smrg *(outPtr++) = color; 208706f2543Smrg break; 209706f2543Smrg case 1: 210706f2543Smrg if (color) 211706f2543Smrg outPtr[column / 8] |= (1 << (7 - (column & 7))); 212706f2543Smrg else 213706f2543Smrg outPtr[column / 8] &= ~(1 << (7 - (column & 7))); 214706f2543Smrg } 215706f2543Smrg } 216706f2543Smrg else if (effXDepth == 16) 217706f2543Smrg { 218706f2543Smrg ptr += posX * (effXBPP / 8); 219706f2543Smrg 220706f2543Smrg /* Out of X icon bounds, leave space blank */ 221706f2543Smrg if (posX >= pixmap->drawable.width 222706f2543Smrg || posY >= pixmap->drawable.height) 223706f2543Smrg ptr = (unsigned char *) &zero; 224706f2543Smrg color = ((*ptr) << 8) + (*(ptr + 1)); 225706f2543Smrg switch (effBPP) 226706f2543Smrg { 227706f2543Smrg case 32: 228706f2543Smrg *(outPtr++) = (color & 31) << 2; 229706f2543Smrg *(outPtr++) = ((color >> 5) & 31) << 2; 230706f2543Smrg *(outPtr++) = ((color >> 10) & 31) << 2; 231706f2543Smrg *(outPtr++) = 0; /* resvd */ 232706f2543Smrg break; 233706f2543Smrg case 24: 234706f2543Smrg *(outPtr++) = (color & 31) << 2; 235706f2543Smrg *(outPtr++) = ((color >> 5) & 31) << 2; 236706f2543Smrg *(outPtr++) = ((color >> 10) & 31) << 2; 237706f2543Smrg break; 238706f2543Smrg case 16: 239706f2543Smrg *(outPtr++) = *(ptr++); 240706f2543Smrg *(outPtr++) = *(ptr++); 241706f2543Smrg break; 242706f2543Smrg case 8: 243706f2543Smrg *(outPtr++) = (((color & 31) 244706f2543Smrg + ((color >> 5) & 31) 245706f2543Smrg + ((color >> 10) & 31)) / 3) << 2; 246706f2543Smrg break; 247706f2543Smrg case 1: 248706f2543Smrg if (color) 249706f2543Smrg outPtr[column / 8] |= (1 << (7 - (column & 7))); 250706f2543Smrg else 251706f2543Smrg outPtr[column / 8] &= ~(1 << (7 - (column & 7))); 252706f2543Smrg break; 253706f2543Smrg } /* end switch(effbpp) */ 254706f2543Smrg } /* end if effxbpp==16) */ 255706f2543Smrg } /* end for column */ 256706f2543Smrg } /* end for row */ 257706f2543Smrg free (iconData); 258706f2543Smrg} 259706f2543Smrg 260706f2543Smrgstatic HICON 261706f2543SmrgNetWMToWinIconAlpha(uint32_t *icon) 262706f2543Smrg{ 263706f2543Smrg int width = icon[0]; 264706f2543Smrg int height = icon[1]; 265706f2543Smrg uint32_t *pixels = &icon[2]; 266706f2543Smrg HICON result; 267706f2543Smrg HDC hdc = GetDC(NULL); 268706f2543Smrg uint32_t *DIB_pixels; 269706f2543Smrg ICONINFO ii = {TRUE}; 270706f2543Smrg BITMAPV4HEADER bmh = {sizeof(bmh)}; 271706f2543Smrg 272706f2543Smrg /* Define an ARGB pixel format used for Color+Alpha icons */ 273706f2543Smrg bmh.bV4Width = width; 274706f2543Smrg bmh.bV4Height = -height; /* Invert the image */ 275706f2543Smrg bmh.bV4Planes = 1; 276706f2543Smrg bmh.bV4BitCount = 32; 277706f2543Smrg bmh.bV4V4Compression = BI_BITFIELDS; 278706f2543Smrg bmh.bV4AlphaMask = 0xFF000000; 279706f2543Smrg bmh.bV4RedMask = 0x00FF0000; 280706f2543Smrg bmh.bV4GreenMask = 0x0000FF00; 281706f2543Smrg bmh.bV4BlueMask = 0x000000FF; 282706f2543Smrg 283706f2543Smrg ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO*)&bmh, 284706f2543Smrg DIB_RGB_COLORS, (void**)&DIB_pixels, NULL, 0); 285706f2543Smrg ReleaseDC(NULL, hdc); 286706f2543Smrg ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL); 287706f2543Smrg memcpy(DIB_pixels, pixels, height*width*4); 288706f2543Smrg 289706f2543Smrg /* CreateIconIndirect() traditionally required DDBitmaps */ 290706f2543Smrg /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */ 291706f2543Smrg /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */ 292706f2543Smrg result = CreateIconIndirect(&ii); 293706f2543Smrg 294706f2543Smrg DeleteObject(ii.hbmColor); 295706f2543Smrg DeleteObject(ii.hbmMask); 296706f2543Smrg 297706f2543Smrg winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result); 298706f2543Smrg return result; 299706f2543Smrg} 300706f2543Smrg 301706f2543Smrgstatic HICON 302706f2543SmrgNetWMToWinIconThreshold(uint32_t *icon) 303706f2543Smrg{ 304706f2543Smrg int width = icon[0]; 305706f2543Smrg int height = icon[1]; 306706f2543Smrg uint32_t *pixels = &icon[2]; 307706f2543Smrg int row, col; 308706f2543Smrg HICON result; 309706f2543Smrg ICONINFO ii = {TRUE}; 310706f2543Smrg 311706f2543Smrg HDC hdc = GetDC(NULL); 312706f2543Smrg HDC xorDC = CreateCompatibleDC(hdc); 313706f2543Smrg HDC andDC = CreateCompatibleDC(hdc); 314706f2543Smrg ii.hbmColor = CreateCompatibleBitmap(hdc, width, height); 315706f2543Smrg ii.hbmMask = CreateCompatibleBitmap(hdc, width, height); 316706f2543Smrg ReleaseDC(NULL, hdc); 317706f2543Smrg SelectObject(xorDC, ii.hbmColor); 318706f2543Smrg SelectObject(andDC, ii.hbmMask); 319706f2543Smrg 320706f2543Smrg for (row = 0; row < height; row++) { 321706f2543Smrg for (col = 0; col < width; col++) { 322706f2543Smrg if ((*pixels & 0xFF000000) > 31<<24) { /* 31 alpha threshold, i.e. opaque above, transparent below */ 323706f2543Smrg SetPixelV(xorDC, col, row, RGB(((char*)pixels)[2], ((char*)pixels)[1], 324706f2543Smrg ((char*)pixels)[0])); 325706f2543Smrg SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */ 326706f2543Smrg } 327706f2543Smrg else { 328706f2543Smrg SetPixelV(xorDC, col, row, RGB(0, 0, 0)); 329706f2543Smrg SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */ 330706f2543Smrg } 331706f2543Smrg pixels++; 332706f2543Smrg } 333706f2543Smrg } 334706f2543Smrg DeleteDC(xorDC); 335706f2543Smrg DeleteDC(andDC); 336706f2543Smrg 337706f2543Smrg result = CreateIconIndirect(&ii); 338706f2543Smrg 339706f2543Smrg DeleteObject(ii.hbmColor); 340706f2543Smrg DeleteObject(ii.hbmMask ); 341706f2543Smrg 342706f2543Smrg winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1], result); 343706f2543Smrg return result; 344706f2543Smrg} 345706f2543Smrg 346706f2543Smrgstatic HICON 347706f2543SmrgNetWMToWinIcon(int bpp, uint32_t *icon) 348706f2543Smrg{ 349706f2543Smrg static Bool hasIconAlphaChannel = FALSE; 350706f2543Smrg static BOOL versionChecked = FALSE; 351706f2543Smrg 352706f2543Smrg if (!versionChecked) 353706f2543Smrg { 354706f2543Smrg OSVERSIONINFOEX osvi = {0}; 355706f2543Smrg ULONGLONG dwlConditionMask = 0; 356706f2543Smrg 357706f2543Smrg osvi.dwOSVersionInfoSize = sizeof (osvi); 358706f2543Smrg osvi.dwMajorVersion = 5; 359706f2543Smrg osvi.dwMinorVersion = 1; 360706f2543Smrg 361706f2543Smrg /* Windows versions later than XP have icon alpha channel suport, 2000 does not */ 362706f2543Smrg VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); 363706f2543Smrg VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); 364706f2543Smrg hasIconAlphaChannel = VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask); 365706f2543Smrg versionChecked = TRUE; 366706f2543Smrg 367706f2543Smrg ErrorF("OS has icon alpha channel support: %s\n", hasIconAlphaChannel ? "yes" : "no"); 368706f2543Smrg } 369706f2543Smrg 370706f2543Smrg if (hasIconAlphaChannel && (bpp==32)) 371706f2543Smrg return NetWMToWinIconAlpha(icon); 372706f2543Smrg else 373706f2543Smrg return NetWMToWinIconThreshold(icon); 374706f2543Smrg} 375706f2543Smrg 376706f2543Smrgstatic pointer 377706f2543SmrgGetWindowProp(WindowPtr pWin, Atom name, long int *size_return) 378706f2543Smrg{ 379706f2543Smrg struct _Window *pwin; 380706f2543Smrg struct _Property *prop; 381706f2543Smrg 382706f2543Smrg if (!pWin || !name) { 383706f2543Smrg ErrorF ("GetWindowProp - pWin or name was NULL\n"); 384706f2543Smrg return 0; 385706f2543Smrg } 386706f2543Smrg pwin = (struct _Window*) pWin; 387706f2543Smrg if (!pwin->optional) return NULL; 388706f2543Smrg for (prop = (struct _Property *) pwin->optional->userProps; 389706f2543Smrg prop; 390706f2543Smrg prop=prop->next){ 391706f2543Smrg if (prop->propertyName == name) { 392706f2543Smrg *size_return=prop->size; 393706f2543Smrg return prop->data; 394706f2543Smrg } 395706f2543Smrg } 396706f2543Smrg return NULL; 397706f2543Smrg} 398706f2543Smrg 399706f2543Smrg/* 400706f2543Smrg * Attempt to create a custom icon from the WM_HINTS bitmaps 401706f2543Smrg */ 402706f2543Smrg 403706f2543SmrgHICON 404706f2543SmrgwinXIconToHICON (WindowPtr pWin, int iconSize) 405706f2543Smrg{ 406706f2543Smrg unsigned char *mask, *image, *imageMask; 407706f2543Smrg unsigned char *dst, *src; 408706f2543Smrg PixmapPtr iconPtr; 409706f2543Smrg PixmapPtr maskPtr; 410706f2543Smrg int planes, bpp, effBPP, stride, maskStride, i; 411706f2543Smrg int biggest_size = 0; 412706f2543Smrg HDC hDC; 413706f2543Smrg ICONINFO ii; 414706f2543Smrg WinXWMHints hints; 415706f2543Smrg HICON hIcon = NULL; 416706f2543Smrg uint32_t *biggest_icon = NULL; 417706f2543Smrg 418706f2543Smrg /* Try to get _NET_WM_ICON icons first */ 419706f2543Smrg static Atom _XA_NET_WM_ICON; 420706f2543Smrg static int generation; 421706f2543Smrg uint32_t *icon, *icon_data = NULL; 422706f2543Smrg long int size=0; 423706f2543Smrg 424706f2543Smrg hDC = GetDC (GetDesktopWindow ()); 425706f2543Smrg planes = GetDeviceCaps (hDC, PLANES); 426706f2543Smrg bpp = GetDeviceCaps (hDC, BITSPIXEL); 427706f2543Smrg ReleaseDC (GetDesktopWindow (), hDC); 428706f2543Smrg 429706f2543Smrg if (generation != serverGeneration) { 430706f2543Smrg generation = serverGeneration; 431706f2543Smrg _XA_NET_WM_ICON = MakeAtom("_NET_WM_ICON", 12, TRUE); 432706f2543Smrg } 433706f2543Smrg 434706f2543Smrg if (_XA_NET_WM_ICON) icon_data = GetWindowProp(pWin, _XA_NET_WM_ICON, &size); 435706f2543Smrg if (icon_data) 436706f2543Smrg { 437706f2543Smrg for(icon = icon_data; 438706f2543Smrg icon < &icon_data[size] && *icon; 439706f2543Smrg icon = &icon[icon[0]*icon[1]+2]) 440706f2543Smrg { 441706f2543Smrg if (icon[0]==iconSize && icon[1]==iconSize) 442706f2543Smrg return NetWMToWinIcon(bpp, icon); 443706f2543Smrg /* Find the biggest icon and let Windows scale the size */ 444706f2543Smrg else if (biggest_size < icon[0]) 445706f2543Smrg { 446706f2543Smrg biggest_icon = icon; 447706f2543Smrg biggest_size = icon[0]; 448706f2543Smrg } 449706f2543Smrg } 450706f2543Smrg if (biggest_icon) 451706f2543Smrg return NetWMToWinIcon(bpp, biggest_icon); 452706f2543Smrg } 453706f2543Smrg winDebug("winXIconToHICON - pWin %x: no suitable NetIcon\n",(int)pWin, iconSize); 454706f2543Smrg 455706f2543Smrg winMultiWindowGetWMHints (pWin, &hints); 456706f2543Smrg if (!hints.icon_pixmap) return NULL; 457706f2543Smrg 458706f2543Smrg dixLookupResourceByType((pointer) &iconPtr, hints.icon_pixmap, RT_PIXMAP, 459706f2543Smrg NullClient, DixUnknownAccess); 460706f2543Smrg 461706f2543Smrg if (!iconPtr) return NULL; 462706f2543Smrg 463706f2543Smrg /* 15 BPP is really 16BPP as far as we care */ 464706f2543Smrg if (bpp == 15) 465706f2543Smrg effBPP = 16; 466706f2543Smrg else 467706f2543Smrg effBPP = bpp; 468706f2543Smrg 469706f2543Smrg /* Need 16-bit aligned rows for DDBitmaps */ 470706f2543Smrg stride = ((iconSize * effBPP + 15) & (~15)) / 8; 471706f2543Smrg 472706f2543Smrg /* Mask is 1-bit deep */ 473706f2543Smrg maskStride = ((iconSize * 1 + 15) & (~15)) / 8; 474706f2543Smrg 475706f2543Smrg image = malloc (stride * iconSize); 476706f2543Smrg imageMask = malloc (stride * iconSize); 477706f2543Smrg /* Default to a completely black mask */ 478706f2543Smrg mask = calloc (maskStride, iconSize); 479706f2543Smrg 480706f2543Smrg winScaleXBitmapToWindows (iconSize, effBPP, iconPtr, image); 481706f2543Smrg dixLookupResourceByType((pointer) &maskPtr, hints.icon_mask, RT_PIXMAP, 482706f2543Smrg NullClient, DixUnknownAccess); 483706f2543Smrg 484706f2543Smrg if (maskPtr) 485706f2543Smrg { 486706f2543Smrg winScaleXBitmapToWindows (iconSize, 1, maskPtr, mask); 487706f2543Smrg 488706f2543Smrg winScaleXBitmapToWindows (iconSize, effBPP, maskPtr, imageMask); 489706f2543Smrg 490706f2543Smrg /* Now we need to set all bits of the icon which are not masked */ 491706f2543Smrg /* on to 0 because Color is really an XOR, not an OR function */ 492706f2543Smrg dst = image; 493706f2543Smrg src = imageMask; 494706f2543Smrg 495706f2543Smrg for (i = 0; i < (stride * iconSize); i++) 496706f2543Smrg if ((*(src++))) 497706f2543Smrg *(dst++) = 0; 498706f2543Smrg else 499706f2543Smrg dst++; 500706f2543Smrg } 501706f2543Smrg 502706f2543Smrg ii.fIcon = TRUE; 503706f2543Smrg ii.xHotspot = 0; /* ignored */ 504706f2543Smrg ii.yHotspot = 0; /* ignored */ 505706f2543Smrg 506706f2543Smrg /* Create Win32 mask from pixmap shape */ 507706f2543Smrg ii.hbmMask = CreateBitmap (iconSize, iconSize, planes, 1, mask); 508706f2543Smrg 509706f2543Smrg /* Create Win32 bitmap from pixmap */ 510706f2543Smrg ii.hbmColor = CreateBitmap (iconSize, iconSize, planes, bpp, image); 511706f2543Smrg 512706f2543Smrg /* Merge Win32 mask and bitmap into icon */ 513706f2543Smrg hIcon = CreateIconIndirect (&ii); 514706f2543Smrg 515706f2543Smrg /* Release Win32 mask and bitmap */ 516706f2543Smrg DeleteObject (ii.hbmMask); 517706f2543Smrg DeleteObject (ii.hbmColor); 518706f2543Smrg 519706f2543Smrg /* Free X mask and bitmap */ 520706f2543Smrg free (mask); 521706f2543Smrg free (image); 522706f2543Smrg free (imageMask); 523706f2543Smrg 524706f2543Smrg return hIcon; 525706f2543Smrg} 526706f2543Smrg 527706f2543Smrg 528706f2543Smrg 529706f2543Smrg/* 530706f2543Smrg * Change the Windows window icon 531706f2543Smrg */ 532706f2543Smrg 533706f2543Smrg#ifdef XWIN_MULTIWINDOW 534706f2543Smrgvoid 535706f2543SmrgwinUpdateIcon (Window id) 536706f2543Smrg{ 537706f2543Smrg WindowPtr pWin; 538706f2543Smrg HICON hIcon, hIconSmall=NULL, hIconOld; 539706f2543Smrg 540706f2543Smrg dixLookupResourceByType((pointer) &pWin, id, RT_WINDOW, NullClient, DixUnknownAccess); 541706f2543Smrg if (pWin) 542706f2543Smrg { 543706f2543Smrg winWindowPriv(pWin); 544706f2543Smrg if (pWinPriv->hWnd) { 545706f2543Smrg hIcon = winOverrideIcon ((unsigned long)pWin); 546706f2543Smrg if (!hIcon) { 547706f2543Smrg hIcon = winXIconToHICON (pWin, GetSystemMetrics(SM_CXICON)); 548706f2543Smrg if (!hIcon) { 549706f2543Smrg hIcon = g_hIconX; 550706f2543Smrg hIconSmall = g_hSmallIconX; 551706f2543Smrg } else { 552706f2543Smrg /* Leave undefined if not found */ 553706f2543Smrg hIconSmall = winXIconToHICON (pWin, GetSystemMetrics(SM_CXSMICON)); 554706f2543Smrg } 555706f2543Smrg } 556706f2543Smrg 557706f2543Smrg /* Set the large icon */ 558706f2543Smrg hIconOld = (HICON) SendMessage (pWinPriv->hWnd, 559706f2543Smrg WM_SETICON, ICON_BIG, (LPARAM) hIcon); 560706f2543Smrg 561706f2543Smrg /* Delete the icon if its not the default */ 562706f2543Smrg winDestroyIcon(hIconOld); 563706f2543Smrg 564706f2543Smrg /* Same for the small icon */ 565706f2543Smrg hIconOld = (HICON) SendMessage (pWinPriv->hWnd, 566706f2543Smrg WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall); 567706f2543Smrg winDestroyIcon(hIconOld); 568706f2543Smrg } 569706f2543Smrg } 570706f2543Smrg} 571706f2543Smrg 572706f2543Smrgvoid winInitGlobalIcons (void) 573706f2543Smrg{ 574706f2543Smrg int sm_cx = GetSystemMetrics(SM_CXICON); 575706f2543Smrg int sm_cxsm = GetSystemMetrics(SM_CXSMICON); 576706f2543Smrg /* Load default X icon in case it's not ready yet */ 577706f2543Smrg if (!g_hIconX) 578706f2543Smrg { 579706f2543Smrg g_hIconX = winOverrideDefaultIcon(sm_cx); 580706f2543Smrg g_hSmallIconX = winOverrideDefaultIcon(sm_cxsm); 581706f2543Smrg } 582706f2543Smrg 583706f2543Smrg if (!g_hIconX) 584706f2543Smrg { 585706f2543Smrg g_hIconX = (HICON)LoadImage (g_hInstance, 586706f2543Smrg MAKEINTRESOURCE(IDI_XWIN), 587706f2543Smrg IMAGE_ICON, 588706f2543Smrg GetSystemMetrics(SM_CXICON), 589706f2543Smrg GetSystemMetrics(SM_CYICON), 590706f2543Smrg 0); 591706f2543Smrg g_hSmallIconX = (HICON)LoadImage (g_hInstance, 592706f2543Smrg MAKEINTRESOURCE(IDI_XWIN), 593706f2543Smrg IMAGE_ICON, 594706f2543Smrg GetSystemMetrics(SM_CXSMICON), 595706f2543Smrg GetSystemMetrics(SM_CYSMICON), 596706f2543Smrg LR_DEFAULTSIZE); 597706f2543Smrg } 598706f2543Smrg} 599706f2543Smrg 600706f2543Smrgvoid winSelectIcons(WindowPtr pWin, HICON *pIcon, HICON *pSmallIcon) 601706f2543Smrg{ 602706f2543Smrg HICON hIcon, hSmallIcon; 603706f2543Smrg 604706f2543Smrg winInitGlobalIcons(); 605706f2543Smrg 606706f2543Smrg /* Try and get the icon from WM_HINTS */ 607706f2543Smrg hIcon = winXIconToHICON (pWin, GetSystemMetrics(SM_CXICON)); 608706f2543Smrg hSmallIcon = winXIconToHICON (pWin, GetSystemMetrics(SM_CXSMICON)); 609706f2543Smrg 610706f2543Smrg /* If we got the small, but not the large one swap them */ 611706f2543Smrg if (!hIcon && hSmallIcon) 612706f2543Smrg { 613706f2543Smrg hIcon = hSmallIcon; 614706f2543Smrg hSmallIcon = NULL; 615706f2543Smrg } 616706f2543Smrg 617706f2543Smrg /* Use default X icon if no icon loaded from WM_HINTS */ 618706f2543Smrg if (!hIcon) { 619706f2543Smrg hIcon = g_hIconX; 620706f2543Smrg hSmallIcon = g_hSmallIconX; 621706f2543Smrg } 622706f2543Smrg 623706f2543Smrg if (pIcon) 624706f2543Smrg *pIcon = hIcon; 625706f2543Smrg else 626706f2543Smrg winDestroyIcon(hIcon); 627706f2543Smrg if (pSmallIcon) 628706f2543Smrg *pSmallIcon = hSmallIcon; 629706f2543Smrg else 630706f2543Smrg winDestroyIcon(hSmallIcon); 631706f2543Smrg} 632706f2543Smrg 633706f2543Smrgvoid winDestroyIcon(HICON hIcon) 634706f2543Smrg{ 635706f2543Smrg /* Delete the icon if its not the default */ 636706f2543Smrg if (hIcon && 637706f2543Smrg hIcon != g_hIconX && 638706f2543Smrg hIcon != g_hSmallIconX && 639706f2543Smrg !winIconIsOverride((unsigned long)hIcon)) 640706f2543Smrg DestroyIcon (hIcon); 641706f2543Smrg} 642706f2543Smrg#endif 643