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