2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
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:
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
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.
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.
28 * Authors: Earle F. Philhower, III
31 #ifdef HAVE_XWIN_CONFIG_H
32 #include <xwin-config.h>
35 #include "dixevents.h"
36 #include "winmultiwindowclass.h"
41 * External global variables
44 extern HICON g_hIconX
;
45 extern HICON g_hSmallIconX
;
49 * Prototypes for local functions
53 winScaleXBitmapToWindows (int iconSize
, int effBPP
,
54 PixmapPtr pixmap
, unsigned char *image
);
58 * Scale an X icon bitmap into a Windoze icon bitmap
62 winScaleXBitmapToWindows (int iconSize
,
67 int row
, column
, effXBPP
, effXDepth
;
68 unsigned char *outPtr
;
69 unsigned char *iconData
= 0;
77 effXBPP
= BitsPerPixel(pixmap
->drawable
.depth
);
78 effXDepth
= pixmap
->drawable
.depth
;
80 if (pixmap
->drawable
.bitsPerPixel
== 15)
83 if (pixmap
->drawable
.depth
== 15)
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)
91 ErrorF ("winScaleXBitmapToWindows - stride or xStride is zero. "
96 /* Allocate memory for icon data */
97 iconData
= malloc (xStride
* pixmap
->drawable
.height
);
100 ErrorF ("winScaleXBitmapToWindows - malloc failed for iconData. "
106 miGetImage ((DrawablePtr
) &(pixmap
->drawable
), 0, 0,
107 pixmap
->drawable
.width
, pixmap
->drawable
.height
,
108 ZPixmap
, 0xffffffff, iconData
);
110 /* Keep aspect ratio */
111 factX
= ((float)pixmap
->drawable
.width
) / ((float)iconSize
);
112 factY
= ((float)pixmap
->drawable
.height
) / ((float)iconSize
);
118 /* Out-of-bounds, fill icon with zero */
121 for (row
= 0; row
< iconSize
; row
++)
123 outPtr
= image
+ stride
* row
;
124 for (column
= 0; column
< iconSize
; column
++)
126 posX
= factX
* column
;
129 ptr
= iconData
+ posY
*xStride
;
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
;
139 if ((*ptr
) & (1 << (posX
& 7)))
152 outPtr
[column
/ 8] &= ~(1 << (7 - (column
& 7)));
172 outPtr
[column
/ 8] |= (1 << (7 - (column
& 7)));
176 else if (effXDepth
== 24 || effXDepth
== 32)
178 ptr
+= posX
* (effXBPP
/ 8);
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));
190 *(outPtr
++) = *(ptr
++); // b
191 *(outPtr
++) = *(ptr
++); // g
192 *(outPtr
++) = *(ptr
++); // r
193 *(outPtr
++) = 0; // resvd
196 *(outPtr
++) = *(ptr
++);
197 *(outPtr
++) = *(ptr
++);
198 *(outPtr
++) = *(ptr
++);
201 color
= ((((*ptr
) >> 2) << 10)
202 + (((*(ptr
+ 1)) >> 2) << 5)
203 + (((*(ptr
+ 2)) >> 2)));
204 *(outPtr
++) = (color
>> 8);
205 *(outPtr
++) = (color
& 255);
208 color
= (((*ptr
))) + (((*(ptr
+ 1)))) + (((*(ptr
+ 2))));
214 outPtr
[column
/ 8] |= (1 << (7 - (column
& 7)));
216 outPtr
[column
/ 8] &= ~(1 << (7 - (column
& 7)));
219 else if (effXDepth
== 16)
221 ptr
+= posX
* (effXBPP
/ 8);
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));
231 *(outPtr
++) = (color
& 31) << 2;
232 *(outPtr
++) = ((color
>> 5) & 31) << 2;
233 *(outPtr
++) = ((color
>> 10) & 31) << 2;
234 *(outPtr
++) = 0; // resvd
237 *(outPtr
++) = (color
& 31) << 2;
238 *(outPtr
++) = ((color
>> 5) & 31) << 2;
239 *(outPtr
++) = ((color
>> 10) & 31) << 2;
242 *(outPtr
++) = *(ptr
++);
243 *(outPtr
++) = *(ptr
++);
246 *(outPtr
++) = (((color
& 31)
247 + ((color
>> 5) & 31)
248 + ((color
>> 10) & 31)) / 3) << 2;
252 outPtr
[column
/ 8] |= (1 << (7 - (column
& 7)));
254 outPtr
[column
/ 8] &= ~(1 << (7 - (column
& 7)));
256 } /* end switch(effbpp) */
257 } /* end if effxbpp==16) */
258 } /* end for column */
265 * Attempt to create a custom icon from the WM_HINTS bitmaps
269 winXIconToHICON (WindowPtr pWin
, int iconSize
)
271 unsigned char *mask
, *image
, *imageMask
;
272 unsigned char *dst
, *src
;
275 int planes
, bpp
, effBPP
, stride
, maskStride
, i
;
281 winMultiWindowGetWMHints (pWin
, &hints
);
282 if (!hints
.icon_pixmap
) return NULL
;
284 iconPtr
= (PixmapPtr
) LookupIDByType (hints
.icon_pixmap
, RT_PIXMAP
);
286 if (!iconPtr
) return NULL
;
288 hDC
= GetDC (GetDesktopWindow ());
289 planes
= GetDeviceCaps (hDC
, PLANES
);
290 bpp
= GetDeviceCaps (hDC
, BITSPIXEL
);
291 ReleaseDC (GetDesktopWindow (), hDC
);
293 /* 15 BPP is really 16BPP as far as we care */
299 /* Need 32-bit aligned rows */
300 stride
= ((iconSize
* effBPP
+ 31) & (~31)) / 8;
302 /* Mask is 1-bit deep */
303 maskStride
= ((iconSize
* 1 + 31) & (~31)) / 8;
305 image
= (unsigned char * ) malloc (stride
* iconSize
);
306 imageMask
= (unsigned char *) malloc (stride
* iconSize
);
307 mask
= (unsigned char *) malloc (maskStride
* iconSize
);
309 /* Default to a completely black mask */
310 memset (mask
, 0, maskStride
* iconSize
);
312 winScaleXBitmapToWindows (iconSize
, effBPP
, iconPtr
, image
);
313 maskPtr
= (PixmapPtr
) LookupIDByType (hints
.icon_mask
, RT_PIXMAP
);
317 winScaleXBitmapToWindows (iconSize
, 1, maskPtr
, mask
);
319 winScaleXBitmapToWindows (iconSize
, effBPP
, maskPtr
, imageMask
);
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 */
326 for (i
= 0; i
< (stride
* iconSize
); i
++)
334 ii
.xHotspot
= 0; /* ignored */
335 ii
.yHotspot
= 0; /* ignored */
337 /* Create Win32 mask from pixmap shape */
338 ii
.hbmMask
= CreateBitmap (iconSize
, iconSize
, planes
, 1, mask
);
340 /* Create Win32 bitmap from pixmap */
341 ii
.hbmColor
= CreateBitmap (iconSize
, iconSize
, planes
, bpp
, image
);
343 /* Merge Win32 mask and bitmap into icon */
344 hIcon
= CreateIconIndirect (&ii
);
346 /* Release Win32 mask and bitmap */
347 DeleteObject (ii
.hbmMask
);
348 DeleteObject (ii
.hbmColor
);
350 /* Free X mask and bitmap */
361 * Change the Windows window icon
364 #ifdef XWIN_MULTIWINDOW
366 winUpdateIcon (Window id
)
369 HICON hIcon
, hiconOld
;
371 pWin
= (WindowPtr
) LookupIDByType (id
, RT_WINDOW
);
373 hIcon
= (HICON
)winOverrideIcon ((unsigned long)pWin
);
376 hIcon
= winXIconToHICON (pWin
, GetSystemMetrics(SM_CXICON
));
384 hiconOld
= (HICON
) SetClassLong (pWinPriv
->hWnd
,
388 /* Delete the icon if its not the default */
389 winDestroyIcon(hiconOld
);
393 hIcon
= winXIconToHICON (pWin
, GetSystemMetrics(SM_CXSMICON
));
400 hiconOld
= (HICON
) SetClassLong (pWinPriv
->hWnd
,
403 winDestroyIcon (hiconOld
);
408 void winInitGlobalIcons (void)
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 */
415 g_hIconX
= (HICON
)winOverrideDefaultIcon(sm_cx
);
416 g_hSmallIconX
= (HICON
)winOverrideDefaultIcon(sm_cxsm
);
421 g_hIconX
= (HICON
)LoadImage (g_hInstance
,
422 MAKEINTRESOURCE(IDI_XWIN
),
424 GetSystemMetrics(SM_CXICON
),
425 GetSystemMetrics(SM_CYICON
),
427 g_hSmallIconX
= (HICON
)LoadImage (g_hInstance
,
428 MAKEINTRESOURCE(IDI_XWIN
),
430 GetSystemMetrics(SM_CXSMICON
),
431 GetSystemMetrics(SM_CYSMICON
),
436 void winSelectIcons(WindowPtr pWin
, HICON
*pIcon
, HICON
*pSmallIcon
)
438 HICON hIcon
, hSmallIcon
;
440 winInitGlobalIcons();
442 /* Try and get the icon from WM_HINTS */
443 hIcon
= winXIconToHICON (pWin
, GetSystemMetrics(SM_CXICON
));
444 hSmallIcon
= winXIconToHICON (pWin
, GetSystemMetrics(SM_CXSMICON
));
446 /* If we got the small, but not the large one swap them */
447 if (!hIcon
&& hSmallIcon
)
453 /* Use default X icon if no icon loaded from WM_HINTS */
456 hSmallIcon
= g_hSmallIconX
;
462 winDestroyIcon(hIcon
);
464 *pSmallIcon
= hSmallIcon
;
466 winDestroyIcon(hSmallIcon
);
469 void winDestroyIcon(HICON hIcon
)
471 /* Delete the icon if its not the default */
474 hIcon
!= g_hSmallIconX
&&
475 !winIconIsOverride((unsigned long)hIcon
))