Initial commit
[xorg_rtime.git] / xorg-server-1.4 / hw / xwin / winmultiwindowicons.c
blob45ed093ece275b6ab3c4e14cf8f7d76e67a25090
1 /*
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>
33 #endif
34 #include "win.h"
35 #include "dixevents.h"
36 #include "winmultiwindowclass.h"
37 #include "winprefs.h"
41 * External global variables
44 extern HICON g_hIconX;
45 extern HICON g_hSmallIconX;
49 * Prototypes for local functions
52 static void
53 winScaleXBitmapToWindows (int iconSize, int effBPP,
54 PixmapPtr pixmap, unsigned char *image);
58 * Scale an X icon bitmap into a Windoze icon bitmap
61 static void
62 winScaleXBitmapToWindows (int iconSize,
63 int effBPP,
64 PixmapPtr pixmap,
65 unsigned char *image)
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;
77 effXBPP = BitsPerPixel(pixmap->drawable.depth);
78 effXDepth = pixmap->drawable.depth;
80 if (pixmap->drawable.bitsPerPixel == 15)
81 effXBPP = 16;
83 if (pixmap->drawable.depth == 15)
84 effXDepth = 16;
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. "
92 "Bailing.\n");
93 return;
96 /* Allocate memory for icon data */
97 iconData = malloc (xStride * pixmap->drawable.height);
98 if (!iconData)
100 ErrorF ("winScaleXBitmapToWindows - malloc failed for iconData. "
101 "Bailing.\n");
102 return;
105 /* Get icon data */
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);
113 if (factX > factY)
114 factY = factX;
115 else
116 factX = factY;
118 /* Out-of-bounds, fill icon with zero */
119 zero = 0;
121 for (row = 0; row < iconSize; row++)
123 outPtr = image + stride * row;
124 for (column = 0; column < iconSize; column++)
126 posX = factX * column;
127 posY = factY * row;
129 ptr = iconData + posY*xStride;
130 if (effXBPP == 1)
132 ptr += posX / 8;
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)))
140 switch (effBPP)
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;
155 else
156 switch (effBPP)
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;
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));
187 switch (effBPP)
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)));
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));
228 switch (effBPP)
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);
265 * Attempt to create a custom icon from the WM_HINTS bitmaps
268 HICON
269 winXIconToHICON (WindowPtr pWin, int iconSize)
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;
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 */
294 if (bpp == 15)
295 effBPP = 16;
296 else
297 effBPP = bpp;
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);
315 if (maskPtr)
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 */
323 dst = image;
324 src = imageMask;
326 for (i = 0; i < (stride * iconSize); i++)
327 if ((*(src++)))
328 *(dst++) = 0;
329 else
330 dst++;
333 ii.fIcon = TRUE;
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 */
351 free (mask);
352 free (image);
353 free (imageMask);
355 return hIcon;
361 * Change the Windows window icon
364 #ifdef XWIN_MULTIWINDOW
365 void
366 winUpdateIcon (Window id)
368 WindowPtr pWin;
369 HICON hIcon, hiconOld;
371 pWin = (WindowPtr) LookupIDByType (id, RT_WINDOW);
372 if (!pWin) return;
373 hIcon = (HICON)winOverrideIcon ((unsigned long)pWin);
375 if (!hIcon)
376 hIcon = winXIconToHICON (pWin, GetSystemMetrics(SM_CXICON));
378 if (hIcon)
380 winWindowPriv(pWin);
382 if (pWinPriv->hWnd)
384 hiconOld = (HICON) SetClassLong (pWinPriv->hWnd,
385 GCL_HICON,
386 (int) hIcon);
388 /* Delete the icon if its not the default */
389 winDestroyIcon(hiconOld);
393 hIcon = winXIconToHICON (pWin, GetSystemMetrics(SM_CXSMICON));
394 if (hIcon)
396 winWindowPriv(pWin);
398 if (pWinPriv->hWnd)
400 hiconOld = (HICON) SetClassLong (pWinPriv->hWnd,
401 GCL_HICONSM,
402 (int) hIcon);
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 */
413 if (!g_hIconX)
415 g_hIconX = (HICON)winOverrideDefaultIcon(sm_cx);
416 g_hSmallIconX = (HICON)winOverrideDefaultIcon(sm_cxsm);
419 if (!g_hIconX)
421 g_hIconX = (HICON)LoadImage (g_hInstance,
422 MAKEINTRESOURCE(IDI_XWIN),
423 IMAGE_ICON,
424 GetSystemMetrics(SM_CXICON),
425 GetSystemMetrics(SM_CYICON),
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);
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)
449 hIcon = hSmallIcon;
450 hSmallIcon = NULL;
453 /* Use default X icon if no icon loaded from WM_HINTS */
454 if (!hIcon) {
455 hIcon = g_hIconX;
456 hSmallIcon = g_hSmallIconX;
459 if (pIcon)
460 *pIcon = hIcon;
461 else
462 winDestroyIcon(hIcon);
463 if (pSmallIcon)
464 *pSmallIcon = hSmallIcon;
465 else
466 winDestroyIcon(hSmallIcon);
469 void winDestroyIcon(HICON hIcon)
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);
478 #endif