winmultiwindowicons.c revision 05b261ec
1/* 2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 *"Software"), to deal in the Software without restriction, including 7 *without limitation the rights to use, copy, modify, merge, publish, 8 *distribute, sublicense, and/or sell copies of the Software, and to 9 *permit persons to whom the Software is furnished to do so, subject to 10 *the following conditions: 11 * 12 *The above copyright notice and this permission notice shall be 13 *included in all copies or substantial portions of the Software. 14 * 15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 * 23 *Except as contained in this notice, the name of the XFree86 Project 24 *shall not be used in advertising or otherwise to promote the sale, use 25 *or other dealings in this Software without prior written authorization 26 *from the XFree86 Project. 27 * 28 * Authors: Earle F. Philhower, III 29 */ 30 31#ifdef HAVE_XWIN_CONFIG_H 32#include <xwin-config.h> 33#endif 34#include "win.h" 35#include "dixevents.h" 36#include "winmultiwindowclass.h" 37#include "winprefs.h" 38 39 40/* 41 * External global variables 42 */ 43 44extern HICON g_hIconX; 45extern HICON g_hSmallIconX; 46 47 48/* 49 * Prototypes for local functions 50 */ 51 52static void 53winScaleXBitmapToWindows (int iconSize, int effBPP, 54 PixmapPtr pixmap, unsigned char *image); 55 56 57/* 58 * Scale an X icon bitmap into a Windoze icon bitmap 59 */ 60 61static void 62winScaleXBitmapToWindows (int iconSize, 63 int effBPP, 64 PixmapPtr pixmap, 65 unsigned char *image) 66{ 67 int row, column, effXBPP, effXDepth; 68 unsigned char *outPtr; 69 unsigned char *iconData = 0; 70 int stride, xStride; 71 float factX, factY; 72 int posX, posY; 73 unsigned char *ptr; 74 unsigned int zero; 75 unsigned int color; 76 77 effXBPP = BitsPerPixel(pixmap->drawable.depth); 78 effXDepth = pixmap->drawable.depth; 79 80 if (pixmap->drawable.bitsPerPixel == 15) 81 effXBPP = 16; 82 83 if (pixmap->drawable.depth == 15) 84 effXDepth = 16; 85 86 /* Need 32-bit aligned rows */ 87 stride = ((iconSize * effBPP + 31) & (~31)) / 8; 88 xStride = PixmapBytePad (pixmap->drawable.width, pixmap->drawable.depth); 89 if (stride == 0 || xStride == 0) 90 { 91 ErrorF ("winScaleXBitmapToWindows - stride or xStride is zero. " 92 "Bailing.\n"); 93 return; 94 } 95 96 /* Allocate memory for icon data */ 97 iconData = malloc (xStride * pixmap->drawable.height); 98 if (!iconData) 99 { 100 ErrorF ("winScaleXBitmapToWindows - malloc failed for iconData. " 101 "Bailing.\n"); 102 return; 103 } 104 105 /* Get icon data */ 106 miGetImage ((DrawablePtr) &(pixmap->drawable), 0, 0, 107 pixmap->drawable.width, pixmap->drawable.height, 108 ZPixmap, 0xffffffff, iconData); 109 110 /* Keep aspect ratio */ 111 factX = ((float)pixmap->drawable.width) / ((float)iconSize); 112 factY = ((float)pixmap->drawable.height) / ((float)iconSize); 113 if (factX > factY) 114 factY = factX; 115 else 116 factX = factY; 117 118 /* Out-of-bounds, fill icon with zero */ 119 zero = 0; 120 121 for (row = 0; row < iconSize; row++) 122 { 123 outPtr = image + stride * row; 124 for (column = 0; column < iconSize; column++) 125 { 126 posX = factX * column; 127 posY = factY * row; 128 129 ptr = iconData + posY*xStride; 130 if (effXBPP == 1) 131 { 132 ptr += posX / 8; 133 134 /* Out of X icon bounds, leave space blank */ 135 if (posX >= pixmap->drawable.width 136 || posY >= pixmap->drawable.height) 137 ptr = (unsigned char *) &zero; 138 139 if ((*ptr) & (1 << (posX & 7))) 140 switch (effBPP) 141 { 142 case 32: 143 *(outPtr++) = 0; 144 case 24: 145 *(outPtr++) = 0; 146 case 16: 147 *(outPtr++) = 0; 148 case 8: 149 *(outPtr++) = 0; 150 break; 151 case 1: 152 outPtr[column / 8] &= ~(1 << (7 - (column & 7))); 153 break; 154 } 155 else 156 switch (effBPP) 157 { 158 case 32: 159 *(outPtr++) = 255; 160 *(outPtr++) = 255; 161 *(outPtr++) = 255; 162 *(outPtr++) = 0; 163 break; 164 case 24: 165 *(outPtr++) = 255; 166 case 16: 167 *(outPtr++) = 255; 168 case 8: 169 *(outPtr++) = 255; 170 break; 171 case 1: 172 outPtr[column / 8] |= (1 << (7 - (column & 7))); 173 break; 174 } 175 } 176 else if (effXDepth == 24 || effXDepth == 32) 177 { 178 ptr += posX * (effXBPP / 8); 179 180 /* Out of X icon bounds, leave space blank */ 181 if (posX >= pixmap->drawable.width 182 || posY >= pixmap->drawable.height) 183 ptr = (unsigned char *) &zero; 184 color = (((*ptr) << 16) 185 + ((*(ptr + 1)) << 8) 186 + ((*(ptr + 2)) << 0)); 187 switch (effBPP) 188 { 189 case 32: 190 *(outPtr++) = *(ptr++); // b 191 *(outPtr++) = *(ptr++); // g 192 *(outPtr++) = *(ptr++); // r 193 *(outPtr++) = 0; // resvd 194 break; 195 case 24: 196 *(outPtr++) = *(ptr++); 197 *(outPtr++) = *(ptr++); 198 *(outPtr++) = *(ptr++); 199 break; 200 case 16: 201 color = ((((*ptr) >> 2) << 10) 202 + (((*(ptr + 1)) >> 2) << 5) 203 + (((*(ptr + 2)) >> 2))); 204 *(outPtr++) = (color >> 8); 205 *(outPtr++) = (color & 255); 206 break; 207 case 8: 208 color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2)))); 209 color /= 3; 210 *(outPtr++) = color; 211 break; 212 case 1: 213 if (color) 214 outPtr[column / 8] |= (1 << (7 - (column & 7))); 215 else 216 outPtr[column / 8] &= ~(1 << (7 - (column & 7))); 217 } 218 } 219 else if (effXDepth == 16) 220 { 221 ptr += posX * (effXBPP / 8); 222 223 /* Out of X icon bounds, leave space blank */ 224 if (posX >= pixmap->drawable.width 225 || posY >= pixmap->drawable.height) 226 ptr = (unsigned char *) &zero; 227 color = ((*ptr) << 8) + (*(ptr + 1)); 228 switch (effBPP) 229 { 230 case 32: 231 *(outPtr++) = (color & 31) << 2; 232 *(outPtr++) = ((color >> 5) & 31) << 2; 233 *(outPtr++) = ((color >> 10) & 31) << 2; 234 *(outPtr++) = 0; // resvd 235 break; 236 case 24: 237 *(outPtr++) = (color & 31) << 2; 238 *(outPtr++) = ((color >> 5) & 31) << 2; 239 *(outPtr++) = ((color >> 10) & 31) << 2; 240 break; 241 case 16: 242 *(outPtr++) = *(ptr++); 243 *(outPtr++) = *(ptr++); 244 break; 245 case 8: 246 *(outPtr++) = (((color & 31) 247 + ((color >> 5) & 31) 248 + ((color >> 10) & 31)) / 3) << 2; 249 break; 250 case 1: 251 if (color) 252 outPtr[column / 8] |= (1 << (7 - (column & 7))); 253 else 254 outPtr[column / 8] &= ~(1 << (7 - (column & 7))); 255 break; 256 } /* end switch(effbpp) */ 257 } /* end if effxbpp==16) */ 258 } /* end for column */ 259 } /* end for row */ 260 free (iconData); 261} 262 263 264/* 265 * Attempt to create a custom icon from the WM_HINTS bitmaps 266 */ 267 268HICON 269winXIconToHICON (WindowPtr pWin, int iconSize) 270{ 271 unsigned char *mask, *image, *imageMask; 272 unsigned char *dst, *src; 273 PixmapPtr iconPtr; 274 PixmapPtr maskPtr; 275 int planes, bpp, effBPP, stride, maskStride, i; 276 HDC hDC; 277 ICONINFO ii; 278 WinXWMHints hints; 279 HICON hIcon; 280 281 winMultiWindowGetWMHints (pWin, &hints); 282 if (!hints.icon_pixmap) return NULL; 283 284 iconPtr = (PixmapPtr) LookupIDByType (hints.icon_pixmap, RT_PIXMAP); 285 286 if (!iconPtr) return NULL; 287 288 hDC = GetDC (GetDesktopWindow ()); 289 planes = GetDeviceCaps (hDC, PLANES); 290 bpp = GetDeviceCaps (hDC, BITSPIXEL); 291 ReleaseDC (GetDesktopWindow (), hDC); 292 293 /* 15 BPP is really 16BPP as far as we care */ 294 if (bpp == 15) 295 effBPP = 16; 296 else 297 effBPP = bpp; 298 299 /* Need 32-bit aligned rows */ 300 stride = ((iconSize * effBPP + 31) & (~31)) / 8; 301 302 /* Mask is 1-bit deep */ 303 maskStride = ((iconSize * 1 + 31) & (~31)) / 8; 304 305 image = (unsigned char * ) malloc (stride * iconSize); 306 imageMask = (unsigned char *) malloc (stride * iconSize); 307 mask = (unsigned char *) malloc (maskStride * iconSize); 308 309 /* Default to a completely black mask */ 310 memset (mask, 0, maskStride * iconSize); 311 312 winScaleXBitmapToWindows (iconSize, effBPP, iconPtr, image); 313 maskPtr = (PixmapPtr) LookupIDByType (hints.icon_mask, RT_PIXMAP); 314 315 if (maskPtr) 316 { 317 winScaleXBitmapToWindows (iconSize, 1, maskPtr, mask); 318 319 winScaleXBitmapToWindows (iconSize, effBPP, maskPtr, imageMask); 320 321 /* Now we need to set all bits of the icon which are not masked */ 322 /* on to 0 because Color is really an XOR, not an OR function */ 323 dst = image; 324 src = imageMask; 325 326 for (i = 0; i < (stride * iconSize); i++) 327 if ((*(src++))) 328 *(dst++) = 0; 329 else 330 dst++; 331 } 332 333 ii.fIcon = TRUE; 334 ii.xHotspot = 0; /* ignored */ 335 ii.yHotspot = 0; /* ignored */ 336 337 /* Create Win32 mask from pixmap shape */ 338 ii.hbmMask = CreateBitmap (iconSize, iconSize, planes, 1, mask); 339 340 /* Create Win32 bitmap from pixmap */ 341 ii.hbmColor = CreateBitmap (iconSize, iconSize, planes, bpp, image); 342 343 /* Merge Win32 mask and bitmap into icon */ 344 hIcon = CreateIconIndirect (&ii); 345 346 /* Release Win32 mask and bitmap */ 347 DeleteObject (ii.hbmMask); 348 DeleteObject (ii.hbmColor); 349 350 /* Free X mask and bitmap */ 351 free (mask); 352 free (image); 353 free (imageMask); 354 355 return hIcon; 356} 357 358 359 360/* 361 * Change the Windows window icon 362 */ 363 364#ifdef XWIN_MULTIWINDOW 365void 366winUpdateIcon (Window id) 367{ 368 WindowPtr pWin; 369 HICON hIcon, hiconOld; 370 371 pWin = (WindowPtr) LookupIDByType (id, RT_WINDOW); 372 if (!pWin) return; 373 hIcon = (HICON)winOverrideIcon ((unsigned long)pWin); 374 375 if (!hIcon) 376 hIcon = winXIconToHICON (pWin, GetSystemMetrics(SM_CXICON)); 377 378 if (hIcon) 379 { 380 winWindowPriv(pWin); 381 382 if (pWinPriv->hWnd) 383 { 384 hiconOld = (HICON) SetClassLong (pWinPriv->hWnd, 385 GCL_HICON, 386 (int) hIcon); 387 388 /* Delete the icon if its not the default */ 389 winDestroyIcon(hiconOld); 390 } 391 } 392 393 hIcon = winXIconToHICON (pWin, GetSystemMetrics(SM_CXSMICON)); 394 if (hIcon) 395 { 396 winWindowPriv(pWin); 397 398 if (pWinPriv->hWnd) 399 { 400 hiconOld = (HICON) SetClassLong (pWinPriv->hWnd, 401 GCL_HICONSM, 402 (int) hIcon); 403 winDestroyIcon (hiconOld); 404 } 405 } 406} 407 408void winInitGlobalIcons (void) 409{ 410 int sm_cx = GetSystemMetrics(SM_CXICON); 411 int sm_cxsm = GetSystemMetrics(SM_CXSMICON); 412 /* Load default X icon in case it's not ready yet */ 413 if (!g_hIconX) 414 { 415 g_hIconX = (HICON)winOverrideDefaultIcon(sm_cx); 416 g_hSmallIconX = (HICON)winOverrideDefaultIcon(sm_cxsm); 417 } 418 419 if (!g_hIconX) 420 { 421 g_hIconX = (HICON)LoadImage (g_hInstance, 422 MAKEINTRESOURCE(IDI_XWIN), 423 IMAGE_ICON, 424 GetSystemMetrics(SM_CXICON), 425 GetSystemMetrics(SM_CYICON), 426 0); 427 g_hSmallIconX = (HICON)LoadImage (g_hInstance, 428 MAKEINTRESOURCE(IDI_XWIN), 429 IMAGE_ICON, 430 GetSystemMetrics(SM_CXSMICON), 431 GetSystemMetrics(SM_CYSMICON), 432 LR_DEFAULTSIZE); 433 } 434} 435 436void winSelectIcons(WindowPtr pWin, HICON *pIcon, HICON *pSmallIcon) 437{ 438 HICON hIcon, hSmallIcon; 439 440 winInitGlobalIcons(); 441 442 /* Try and get the icon from WM_HINTS */ 443 hIcon = winXIconToHICON (pWin, GetSystemMetrics(SM_CXICON)); 444 hSmallIcon = winXIconToHICON (pWin, GetSystemMetrics(SM_CXSMICON)); 445 446 /* If we got the small, but not the large one swap them */ 447 if (!hIcon && hSmallIcon) 448 { 449 hIcon = hSmallIcon; 450 hSmallIcon = NULL; 451 } 452 453 /* Use default X icon if no icon loaded from WM_HINTS */ 454 if (!hIcon) { 455 hIcon = g_hIconX; 456 hSmallIcon = g_hSmallIconX; 457 } 458 459 if (pIcon) 460 *pIcon = hIcon; 461 else 462 winDestroyIcon(hIcon); 463 if (pSmallIcon) 464 *pSmallIcon = hSmallIcon; 465 else 466 winDestroyIcon(hSmallIcon); 467} 468 469void winDestroyIcon(HICON hIcon) 470{ 471 /* Delete the icon if its not the default */ 472 if (hIcon && 473 hIcon != g_hIconX && 474 hIcon != g_hSmallIconX && 475 !winIconIsOverride((unsigned long)hIcon)) 476 DestroyIcon (hIcon); 477} 478#endif 479