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
35 #ifndef WINVER
36 #define WINVER 0x0500
37 #endif
38
39 #include <limits.h>
40 #include <stdbool.h>
41
42 #include <X11/Xwindows.h>
43 #include <X11/Xlib.h>
44 #include <xcb/xcb.h>
45 #include <xcb/xcb_icccm.h>
46 #include <xcb/xcb_image.h>
47
48 #include "winresource.h"
49 #include "winprefs.h"
50 #include "winmsg.h"
51 #include "winmultiwindowicons.h"
52 #include "winglobals.h"
53
54 /*
55 * global variables
56 */
57 extern HINSTANCE g_hInstance;
58
59 /*
60 * Scale an X icon ZPixmap into a Windoze icon bitmap
61 */
62
63 static void
winScaleXImageToWindowsIcon(int iconSize,int effBPP,int stride,xcb_image_t * pixmap,unsigned char * image)64 winScaleXImageToWindowsIcon(int iconSize,
65 int effBPP,
66 int stride, xcb_image_t* pixmap, unsigned char *image)
67 {
68 int row, column, effXBPP, effXDepth;
69 unsigned char *outPtr;
70 unsigned char *iconData = 0;
71 int xStride;
72 float factX, factY;
73 int posX, posY;
74 unsigned char *ptr;
75 unsigned int zero;
76 unsigned int color;
77
78 effXBPP = pixmap->bpp;
79 if (pixmap->bpp == 15)
80 effXBPP = 16;
81
82 effXDepth = pixmap->depth;
83 if (pixmap->depth == 15)
84 effXDepth = 16;
85
86 xStride = pixmap->stride;
87 if (stride == 0 || xStride == 0) {
88 ErrorF("winScaleXBitmapToWindows - stride or xStride is zero. "
89 "Bailing.\n");
90 return;
91 }
92
93 /* Get icon data */
94 iconData = (unsigned char *) pixmap->data;
95
96 /* Keep aspect ratio */
97 factX = ((float) pixmap->width) / ((float) iconSize);
98 factY = ((float) pixmap->height) / ((float) iconSize);
99 if (factX > factY)
100 factY = factX;
101 else
102 factX = factY;
103
104 /* Out-of-bounds, fill icon with zero */
105 zero = 0;
106
107 for (row = 0; row < iconSize; row++) {
108 outPtr = image + stride * row;
109 for (column = 0; column < iconSize; column++) {
110 posX = factX * column;
111 posY = factY * row;
112
113 ptr = (unsigned char *) iconData + posY * xStride;
114 if (effXBPP == 1) {
115 ptr += posX / 8;
116
117 /* Out of X icon bounds, leave space blank */
118 if (posX >= pixmap->width || posY >= pixmap->height)
119 ptr = (unsigned char *) &zero;
120
121 if ((*ptr) & (1 << (posX & 7)))
122 switch (effBPP) {
123 case 32:
124 *(outPtr++) = 0;
125 case 24:
126 *(outPtr++) = 0;
127 case 16:
128 *(outPtr++) = 0;
129 case 8:
130 *(outPtr++) = 0;
131 break;
132 case 1:
133 outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
134 break;
135 }
136 else
137 switch (effBPP) {
138 case 32:
139 *(outPtr++) = 255;
140 *(outPtr++) = 255;
141 *(outPtr++) = 255;
142 *(outPtr++) = 0;
143 break;
144 case 24:
145 *(outPtr++) = 255;
146 case 16:
147 *(outPtr++) = 255;
148 case 8:
149 *(outPtr++) = 255;
150 break;
151 case 1:
152 outPtr[column / 8] |= (1 << (7 - (column & 7)));
153 break;
154 }
155 }
156 else if (effXDepth == 24 || effXDepth == 32) {
157 ptr += posX * (effXBPP / 8);
158
159 /* Out of X icon bounds, leave space blank */
160 if (posX >= pixmap->width || posY >= pixmap->height)
161 ptr = (unsigned char *) &zero;
162 color = (((*ptr) << 16)
163 + ((*(ptr + 1)) << 8)
164 + ((*(ptr + 2)) << 0));
165 switch (effBPP) {
166 case 32:
167 *(outPtr++) = *(ptr++); /* b */
168 *(outPtr++) = *(ptr++); /* g */
169 *(outPtr++) = *(ptr++); /* r */
170 *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */
171 break;
172 case 24:
173 *(outPtr++) = *(ptr++);
174 *(outPtr++) = *(ptr++);
175 *(outPtr++) = *(ptr++);
176 break;
177 case 16:
178 color = ((((*ptr) >> 2) << 10)
179 + (((*(ptr + 1)) >> 2) << 5)
180 + (((*(ptr + 2)) >> 2)));
181 *(outPtr++) = (color >> 8);
182 *(outPtr++) = (color & 255);
183 break;
184 case 8:
185 color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2))));
186 color /= 3;
187 *(outPtr++) = color;
188 break;
189 case 1:
190 if (color)
191 outPtr[column / 8] |= (1 << (7 - (column & 7)));
192 else
193 outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
194 }
195 }
196 else if (effXDepth == 16) {
197 ptr += posX * (effXBPP / 8);
198
199 /* Out of X icon bounds, leave space blank */
200 if (posX >= pixmap->width || posY >= pixmap->height)
201 ptr = (unsigned char *) &zero;
202 color = ((*ptr) << 8) + (*(ptr + 1));
203 switch (effBPP) {
204 case 32:
205 *(outPtr++) = (color & 31) << 2;
206 *(outPtr++) = ((color >> 5) & 31) << 2;
207 *(outPtr++) = ((color >> 10) & 31) << 2;
208 *(outPtr++) = 0; /* resvd */
209 break;
210 case 24:
211 *(outPtr++) = (color & 31) << 2;
212 *(outPtr++) = ((color >> 5) & 31) << 2;
213 *(outPtr++) = ((color >> 10) & 31) << 2;
214 break;
215 case 16:
216 *(outPtr++) = *(ptr++);
217 *(outPtr++) = *(ptr++);
218 break;
219 case 8:
220 *(outPtr++) = (((color & 31)
221 + ((color >> 5) & 31)
222 + ((color >> 10) & 31)) / 3) << 2;
223 break;
224 case 1:
225 if (color)
226 outPtr[column / 8] |= (1 << (7 - (column & 7)));
227 else
228 outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
229 break;
230 } /* end switch(effbpp) */
231 } /* end if effxbpp==16) */
232 } /* end for column */
233 } /* end for row */
234 }
235
236 static HICON
NetWMToWinIconAlpha(uint32_t * icon)237 NetWMToWinIconAlpha(uint32_t * icon)
238 {
239 int width = icon[0];
240 int height = icon[1];
241 uint32_t *pixels = &icon[2];
242 HICON result;
243 HDC hdc = GetDC(NULL);
244 uint32_t *DIB_pixels;
245 ICONINFO ii;
246 BITMAPV4HEADER bmh = { sizeof(bmh) };
247
248 /* Define an ARGB pixel format used for Color+Alpha icons */
249 bmh.bV4Width = width;
250 bmh.bV4Height = -height; /* Invert the image */
251 bmh.bV4Planes = 1;
252 bmh.bV4BitCount = 32;
253 bmh.bV4V4Compression = BI_BITFIELDS;
254 bmh.bV4AlphaMask = 0xFF000000;
255 bmh.bV4RedMask = 0x00FF0000;
256 bmh.bV4GreenMask = 0x0000FF00;
257 bmh.bV4BlueMask = 0x000000FF;
258
259 ii.fIcon = TRUE;
260 ii.xHotspot = 0; /* ignored */
261 ii.yHotspot = 0; /* ignored */
262 ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) &bmh,
263 DIB_RGB_COLORS, (void **) &DIB_pixels, NULL,
264 0);
265 ReleaseDC(NULL, hdc);
266
267 if (!ii.hbmColor)
268 return NULL;
269
270 ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL);
271 memcpy(DIB_pixels, pixels, height * width * 4);
272
273 /* CreateIconIndirect() traditionally required DDBitmaps */
274 /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */
275 /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */
276 result = CreateIconIndirect(&ii);
277
278 DeleteObject(ii.hbmColor);
279 DeleteObject(ii.hbmMask);
280
281 winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result);
282 return result;
283 }
284
285 static HICON
NetWMToWinIconThreshold(uint32_t * icon)286 NetWMToWinIconThreshold(uint32_t * icon)
287 {
288 int width = icon[0];
289 int height = icon[1];
290 uint32_t *pixels = &icon[2];
291 int row, col;
292 HICON result;
293 ICONINFO ii;
294
295 HDC hdc = GetDC(NULL);
296 HDC xorDC = CreateCompatibleDC(hdc);
297 HDC andDC = CreateCompatibleDC(hdc);
298
299 ii.fIcon = TRUE;
300 ii.xHotspot = 0; /* ignored */
301 ii.yHotspot = 0; /* ignored */
302 ii.hbmColor = CreateCompatibleBitmap(hdc, width, height);
303 ii.hbmMask = CreateCompatibleBitmap(hdc, width, height);
304 ReleaseDC(NULL, hdc);
305 SelectObject(xorDC, ii.hbmColor);
306 SelectObject(andDC, ii.hbmMask);
307
308 for (row = 0; row < height; row++) {
309 for (col = 0; col < width; col++) {
310 if ((*pixels & 0xFF000000) > 31 << 24) { /* 31 alpha threshold, i.e. opaque above, transparent below */
311 SetPixelV(xorDC, col, row,
312 RGB(((char *) pixels)[2], ((char *) pixels)[1],
313 ((char *) pixels)[0]));
314 SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */
315 }
316 else {
317 SetPixelV(xorDC, col, row, RGB(0, 0, 0));
318 SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */
319 }
320 pixels++;
321 }
322 }
323 DeleteDC(xorDC);
324 DeleteDC(andDC);
325
326 result = CreateIconIndirect(&ii);
327
328 DeleteObject(ii.hbmColor);
329 DeleteObject(ii.hbmMask);
330
331 winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1],
332 result);
333 return result;
334 }
335
336 static HICON
NetWMToWinIcon(int bpp,uint32_t * icon)337 NetWMToWinIcon(int bpp, uint32_t * icon)
338 {
339 static bool hasIconAlphaChannel = FALSE;
340 static bool versionChecked = FALSE;
341
342 if (!versionChecked) {
343 OSVERSIONINFOEX osvi = { 0 };
344 ULONGLONG dwlConditionMask = 0;
345
346 osvi.dwOSVersionInfoSize = sizeof(osvi);
347 osvi.dwMajorVersion = 5;
348 osvi.dwMinorVersion = 1;
349
350 /* Windows versions later than XP have icon alpha channel suport, 2000 does not */
351 VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION,
352 VER_GREATER_EQUAL);
353 VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION,
354 VER_GREATER_EQUAL);
355 hasIconAlphaChannel =
356 VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
357 dwlConditionMask);
358 versionChecked = TRUE;
359
360 ErrorF("OS has icon alpha channel support: %s\n",
361 hasIconAlphaChannel ? "yes" : "no");
362 }
363
364 if (hasIconAlphaChannel && (bpp == 32))
365 return NetWMToWinIconAlpha(icon);
366 else
367 return NetWMToWinIconThreshold(icon);
368 }
369
370 /*
371 * Attempt to create a custom icon from the WM_HINTS bitmaps
372 */
373
374 static
375 HICON
winXIconToHICON(xcb_connection_t * conn,xcb_window_t id,int iconSize)376 winXIconToHICON(xcb_connection_t *conn, xcb_window_t id, int iconSize)
377 {
378 unsigned char *mask, *image = NULL, *imageMask;
379 unsigned char *dst, *src;
380 int planes, bpp, i;
381 unsigned int biggest_size = 0;
382 HDC hDC;
383 ICONINFO ii;
384 xcb_icccm_wm_hints_t hints;
385 HICON hIcon = NULL;
386 uint32_t *biggest_icon = NULL;
387 static xcb_atom_t _XA_NET_WM_ICON;
388 static int generation;
389 uint32_t *icon, *icon_data = NULL;
390 unsigned long int size;
391
392 hDC = GetDC(GetDesktopWindow());
393 planes = GetDeviceCaps(hDC, PLANES);
394 bpp = GetDeviceCaps(hDC, BITSPIXEL);
395 ReleaseDC(GetDesktopWindow(), hDC);
396
397 /* Always prefer _NET_WM_ICON icons */
398 if (generation != serverGeneration) {
399 xcb_intern_atom_reply_t *atom_reply;
400 xcb_intern_atom_cookie_t atom_cookie;
401 const char *atomName = "_NET_WM_ICON";
402
403 generation = serverGeneration;
404
405 _XA_NET_WM_ICON = XCB_NONE;
406
407 atom_cookie = xcb_intern_atom(conn, 0, strlen(atomName), atomName);
408 atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL);
409 if (atom_reply) {
410 _XA_NET_WM_ICON = atom_reply->atom;
411 free(atom_reply);
412 }
413 }
414
415 {
416 xcb_get_property_cookie_t cookie = xcb_get_property(conn, FALSE, id, _XA_NET_WM_ICON, XCB_ATOM_CARDINAL, 0L, INT_MAX);
417 xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, NULL);
418
419 if (reply &&
420 ((icon_data = xcb_get_property_value(reply)) != NULL)) {
421 size = xcb_get_property_value_length(reply)/sizeof(uint32_t);
422 for (icon = icon_data; icon < &icon_data[size] && *icon;
423 icon = &icon[icon[0] * icon[1] + 2]) {
424 winDebug("winXIconToHICON: %u x %u NetIcon\n", icon[0], icon[1]);
425
426 /* Icon data size will overflow an int and thus is bigger than the
427 property can possibly be */
428 if ((INT_MAX/icon[0]) < icon[1]) {
429 winDebug("winXIconToHICON: _NET_WM_ICON icon data size overflow\n");
430 break;
431 }
432
433 /* Icon data size is bigger than amount of data remaining */
434 if (&icon[icon[0] * icon[1] + 2] > &icon_data[size]) {
435 winDebug("winXIconToHICON: _NET_WM_ICON data is malformed\n");
436 break;
437 }
438
439 /* Found an exact match to the size we require... */
440 if (icon[0] == iconSize && icon[1] == iconSize) {
441 winDebug("winXIconToHICON: selected %d x %d NetIcon\n",
442 iconSize, iconSize);
443 hIcon = NetWMToWinIcon(bpp, icon);
444 break;
445 }
446 /* Otherwise, find the biggest icon and let Windows scale the size */
447 else if (biggest_size < icon[0]) {
448 biggest_icon = icon;
449 biggest_size = icon[0];
450 }
451 }
452
453 if (!hIcon && biggest_icon) {
454 winDebug
455 ("winXIconToHICON: selected %u x %u NetIcon for scaling to %d x %d\n",
456 biggest_icon[0], biggest_icon[1], iconSize, iconSize);
457
458 hIcon = NetWMToWinIcon(bpp, biggest_icon);
459 }
460
461 free(reply);
462 }
463 }
464
465 if (!hIcon) {
466 xcb_get_property_cookie_t wm_hints_cookie;
467
468 winDebug("winXIconToHICON: no suitable NetIcon\n");
469
470 wm_hints_cookie = xcb_icccm_get_wm_hints(conn, id);
471 if (xcb_icccm_get_wm_hints_reply(conn, wm_hints_cookie, &hints, NULL)) {
472 winDebug("winXIconToHICON: id 0x%x icon_pixmap hint 0x%x\n",
473 (unsigned int)id,
474 (unsigned int)hints.icon_pixmap);
475
476 if (hints.icon_pixmap) {
477 unsigned int width, height;
478 xcb_image_t *xImageIcon;
479 xcb_image_t *xImageMask = NULL;
480
481 xcb_get_geometry_cookie_t geom_cookie = xcb_get_geometry(conn, hints.icon_pixmap);
482 xcb_get_geometry_reply_t *geom_reply = xcb_get_geometry_reply(conn, geom_cookie, NULL);
483
484 if (geom_reply) {
485 width = geom_reply->width;
486 height = geom_reply->height;
487
488 xImageIcon = xcb_image_get(conn, hints.icon_pixmap,
489 0, 0, width, height,
490 0xFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP);
491
492 winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%p\n",
493 (unsigned int)id, xImageIcon);
494
495 if (hints.icon_mask)
496 xImageMask = xcb_image_get(conn, hints.icon_mask,
497 0, 0, width, height,
498 0xFFFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP);
499
500 if (xImageIcon) {
501 int effBPP, stride, maskStride;
502
503 /* 15 BPP is really 16BPP as far as we care */
504 if (bpp == 15)
505 effBPP = 16;
506 else
507 effBPP = bpp;
508
509 /* Need 16-bit aligned rows for DDBitmaps */
510 stride = ((iconSize * effBPP + 15) & (~15)) / 8;
511
512 /* Mask is 1-bit deep */
513 maskStride = ((iconSize * 1 + 15) & (~15)) / 8;
514
515 image = malloc(stride * iconSize);
516 imageMask = malloc(stride * iconSize);
517 mask = malloc(maskStride * iconSize);
518
519 /* Default to a completely black mask */
520 memset(imageMask, 0, stride * iconSize);
521 memset(mask, 0, maskStride * iconSize);
522
523 winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
524 xImageIcon, image);
525
526 if (xImageMask) {
527 winScaleXImageToWindowsIcon(iconSize, 1, maskStride,
528 xImageMask, mask);
529 winScaleXImageToWindowsIcon(iconSize, effBPP, stride,
530 xImageMask, imageMask);
531 }
532
533 /* Now we need to set all bits of the icon which are not masked */
534 /* on to 0 because Color is really an XOR, not an OR function */
535 dst = image;
536 src = imageMask;
537
538 for (i = 0; i < (stride * iconSize); i++)
539 if ((*(src++)))
540 *(dst++) = 0;
541 else
542 dst++;
543
544 ii.fIcon = TRUE;
545 ii.xHotspot = 0; /* ignored */
546 ii.yHotspot = 0; /* ignored */
547
548 /* Create Win32 mask from pixmap shape */
549 ii.hbmMask =
550 CreateBitmap(iconSize, iconSize, planes, 1, mask);
551
552 /* Create Win32 bitmap from pixmap */
553 ii.hbmColor =
554 CreateBitmap(iconSize, iconSize, planes, bpp, image);
555
556 /* Merge Win32 mask and bitmap into icon */
557 hIcon = CreateIconIndirect(&ii);
558
559 /* Release Win32 mask and bitmap */
560 DeleteObject(ii.hbmMask);
561 DeleteObject(ii.hbmColor);
562
563 /* Free X mask and bitmap */
564 free(mask);
565 free(image);
566 free(imageMask);
567
568 if (xImageMask)
569 xcb_image_destroy(xImageMask);
570
571 xcb_image_destroy(xImageIcon);
572 }
573 }
574 }
575 }
576 }
577 return hIcon;
578 }
579
580 /*
581 * Change the Windows window icon
582 */
583
584 void
winUpdateIcon(HWND hWnd,xcb_connection_t * conn,Window id,HICON hIconNew)585 winUpdateIcon(HWND hWnd, xcb_connection_t *conn, Window id, HICON hIconNew)
586 {
587 HICON hIcon, hIconSmall = NULL, hIconOld;
588
589 if (hIconNew)
590 {
591 /* Start with the icon from preferences, if any */
592 hIcon = hIconNew;
593 hIconSmall = hIconNew;
594 }
595 else
596 {
597 /* If we still need an icon, try and get the icon from WM_HINTS */
598 hIcon = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXICON));
599 hIconSmall = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXSMICON));
600 }
601
602 /* If we got the small, but not the large one swap them */
603 if (!hIcon && hIconSmall) {
604 hIcon = hIconSmall;
605 hIconSmall = NULL;
606 }
607
608 /* Set the large icon */
609 hIconOld = (HICON) SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
610 /* Delete the old icon if its not the default */
611 winDestroyIcon(hIconOld);
612
613 /* Same for the small icon */
614 hIconOld =
615 (HICON) SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
616 winDestroyIcon(hIconOld);
617 }
618
619 void
winInitGlobalIcons(void)620 winInitGlobalIcons(void)
621 {
622 int sm_cx = GetSystemMetrics(SM_CXICON);
623 int sm_cxsm = GetSystemMetrics(SM_CXSMICON);
624
625 /* Load default X icon in case it's not ready yet */
626 if (!g_hIconX) {
627 g_hIconX = winOverrideDefaultIcon(sm_cx);
628 g_hSmallIconX = winOverrideDefaultIcon(sm_cxsm);
629 }
630
631 if (!g_hIconX) {
632 g_hIconX = (HICON) LoadImage(g_hInstance,
633 MAKEINTRESOURCE(IDI_XWIN),
634 IMAGE_ICON,
635 GetSystemMetrics(SM_CXICON),
636 GetSystemMetrics(SM_CYICON), 0);
637 g_hSmallIconX = (HICON) LoadImage(g_hInstance,
638 MAKEINTRESOURCE(IDI_XWIN),
639 IMAGE_ICON,
640 GetSystemMetrics(SM_CXSMICON),
641 GetSystemMetrics(SM_CYSMICON),
642 LR_DEFAULTSIZE);
643 }
644 }
645
646 void
winSelectIcons(HICON * pIcon,HICON * pSmallIcon)647 winSelectIcons(HICON * pIcon, HICON * pSmallIcon)
648 {
649 HICON hIcon, hSmallIcon;
650
651 winInitGlobalIcons();
652
653 /* Use default X icon */
654 hIcon = g_hIconX;
655 hSmallIcon = g_hSmallIconX;
656
657 if (pIcon)
658 *pIcon = hIcon;
659
660 if (pSmallIcon)
661 *pSmallIcon = hSmallIcon;
662 }
663
664 void
winDestroyIcon(HICON hIcon)665 winDestroyIcon(HICON hIcon)
666 {
667 /* Delete the icon if its not one of the application defaults or an override */
668 if (hIcon &&
669 hIcon != g_hIconX &&
670 hIcon != g_hSmallIconX && !winIconIsOverride(hIcon))
671 DestroyIcon(hIcon);
672 }
673