merge latest (4.3.99.16) from XFree86 (vendor) branch
This commit is contained in:
378
hw/xwin/winmultiwindowicons.c
Executable file
378
hw/xwin/winmultiwindowicons.c
Executable file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
*Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
|
||||
*
|
||||
*Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
*"Software"), to deal in the Software without restriction, including
|
||||
*without limitation the rights to use, copy, modify, merge, publish,
|
||||
*distribute, sublicense, and/or sell copies of the Software, and to
|
||||
*permit persons to whom the Software is furnished to do so, subject to
|
||||
*the following conditions:
|
||||
*
|
||||
*The above copyright notice and this permission notice shall be
|
||||
*included in all copies or substantial portions of the Software.
|
||||
*
|
||||
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
*NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
|
||||
*ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
*CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
*WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*Except as contained in this notice, the name of the XFree86 Project
|
||||
*shall not be used in advertising or otherwise to promote the sale, use
|
||||
*or other dealings in this Software without prior written authorization
|
||||
*from the XFree86 Project.
|
||||
*
|
||||
* Authors: Earle F. Philhower, III
|
||||
*/
|
||||
/* $XFree86: xc/programs/Xserver/hw/xwin/winmultiwindowicons.c,v 1.2 2003/10/02 13:30:10 eich Exp $ */
|
||||
|
||||
#include "win.h"
|
||||
#include "dixevents.h"
|
||||
#include "winmultiwindowclass.h"
|
||||
#include "winprefs.h"
|
||||
|
||||
|
||||
/*
|
||||
* External global variables
|
||||
*/
|
||||
|
||||
extern HICON g_hiconX;
|
||||
|
||||
|
||||
/*
|
||||
* Prototypes for local functions
|
||||
*/
|
||||
|
||||
static void
|
||||
winScaleXBitmapToWindows (int iconSize, int effBPP,
|
||||
PixmapPtr pixmap, unsigned char *image);
|
||||
|
||||
|
||||
/*
|
||||
* Scale an X icon bitmap into a Windoze icon bitmap
|
||||
*/
|
||||
|
||||
static void
|
||||
winScaleXBitmapToWindows (int iconSize,
|
||||
int effBPP,
|
||||
PixmapPtr pixmap,
|
||||
unsigned char *image)
|
||||
{
|
||||
int row, column, effXBPP, effXDepth;
|
||||
unsigned char *outPtr;
|
||||
unsigned char *iconData = 0;
|
||||
int stride, xStride;
|
||||
float factX, factY;
|
||||
int posX, posY;
|
||||
unsigned char *ptr;
|
||||
unsigned int zero;
|
||||
unsigned int color;
|
||||
|
||||
|
||||
if (pixmap->drawable.bitsPerPixel == 15)
|
||||
effXBPP = 16;
|
||||
else
|
||||
effXBPP = pixmap->drawable.bitsPerPixel;
|
||||
|
||||
if (pixmap->drawable.depth == 15)
|
||||
effXDepth = 16;
|
||||
else
|
||||
effXDepth = pixmap->drawable.depth;
|
||||
|
||||
/* Need 32-bit aligned rows */
|
||||
stride = ((iconSize * effBPP + 31) & (~31)) / 8;
|
||||
xStride = ((pixmap->drawable.width * effXBPP + 31) & (~31)) / 8;
|
||||
|
||||
iconData = malloc (xStride * pixmap->drawable.height);
|
||||
miGetImage ((DrawablePtr) &(pixmap->drawable), 0, 0,
|
||||
pixmap->drawable.width, pixmap->drawable.height,
|
||||
ZPixmap, 0xffffffff, iconData);
|
||||
|
||||
/* Keep aspect ratio */
|
||||
factX = ((float)pixmap->drawable.width) / ((float)iconSize);
|
||||
factY = ((float)pixmap->drawable.height) / ((float)iconSize);
|
||||
if (factX > factY)
|
||||
factY = factX;
|
||||
else
|
||||
factX = factY;
|
||||
|
||||
/* Out-of-bounds, fill icon with zero */
|
||||
zero = 0;
|
||||
|
||||
for (row = 0; row < iconSize; row++)
|
||||
{
|
||||
outPtr = image + stride * row;
|
||||
for (column = 0; column < iconSize; column++)
|
||||
{
|
||||
posX = factX * column;
|
||||
posY = factY * row;
|
||||
|
||||
ptr = iconData + posY*xStride;
|
||||
if (effXBPP == 1)
|
||||
{
|
||||
ptr += posX / 8;
|
||||
|
||||
/* Out of X icon bounds, leave space blank */
|
||||
if (posX >= pixmap->drawable.width
|
||||
|| posY >= pixmap->drawable.height)
|
||||
ptr = (unsigned char *) &zero;
|
||||
|
||||
if ((*ptr) & (1 << (posX & 7)))
|
||||
switch (effBPP)
|
||||
{
|
||||
case 32:
|
||||
*(outPtr++) = 0;
|
||||
case 24:
|
||||
*(outPtr++) = 0;
|
||||
case 16:
|
||||
*(outPtr++) = 0;
|
||||
case 8:
|
||||
*(outPtr++) = 0;
|
||||
break;
|
||||
case 1:
|
||||
outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
|
||||
break;
|
||||
}
|
||||
else
|
||||
switch (effBPP)
|
||||
{
|
||||
case 32:
|
||||
*(outPtr++) = 255;
|
||||
*(outPtr++) = 255;
|
||||
*(outPtr++) = 255;
|
||||
*(outPtr++) = 0;
|
||||
break;
|
||||
case 24:
|
||||
*(outPtr++) = 255;
|
||||
case 16:
|
||||
*(outPtr++) = 255;
|
||||
case 8:
|
||||
*(outPtr++) = 255;
|
||||
break;
|
||||
case 1:
|
||||
outPtr[column / 8] |= (1 << (7 - (column & 7)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (effXDepth == 24 || effXDepth == 32)
|
||||
{
|
||||
ptr += posX * (effXBPP / 8);
|
||||
|
||||
/* Out of X icon bounds, leave space blank */
|
||||
if (posX >= pixmap->drawable.width
|
||||
|| posY >= pixmap->drawable.height)
|
||||
ptr = (unsigned char *) &zero;
|
||||
color = (((*ptr) << 16)
|
||||
+ ((*(ptr + 1)) << 8)
|
||||
+ ((*(ptr + 2)) << 0));
|
||||
switch (effBPP)
|
||||
{
|
||||
case 32:
|
||||
*(outPtr++) = *(ptr++); // b
|
||||
*(outPtr++) = *(ptr++); // g
|
||||
*(outPtr++) = *(ptr++); // r
|
||||
*(outPtr++) = 0; // resvd
|
||||
break;
|
||||
case 24:
|
||||
*(outPtr++) = *(ptr++);
|
||||
*(outPtr++) = *(ptr++);
|
||||
*(outPtr++) = *(ptr++);
|
||||
break;
|
||||
case 16:
|
||||
color = ((((*ptr) >> 2) << 10)
|
||||
+ (((*(ptr + 1)) >> 2) << 5)
|
||||
+ (((*(ptr + 2)) >> 2)));
|
||||
*(outPtr++) = (color >> 8);
|
||||
*(outPtr++) = (color & 255);
|
||||
break;
|
||||
case 8:
|
||||
color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2))));
|
||||
color /= 3;
|
||||
*(outPtr++) = color;
|
||||
break;
|
||||
case 1:
|
||||
if (color)
|
||||
outPtr[column / 8] |= (1 << (7 - (column & 7)));
|
||||
else
|
||||
outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
|
||||
}
|
||||
}
|
||||
else if (effXDepth == 16)
|
||||
{
|
||||
ptr += posX * (effXBPP / 8);
|
||||
|
||||
/* Out of X icon bounds, leave space blank */
|
||||
if (posX >= pixmap->drawable.width
|
||||
|| posY >= pixmap->drawable.height)
|
||||
ptr = (unsigned char *) &zero;
|
||||
color = ((*ptr) << 8) + (*(ptr + 1));
|
||||
switch (effBPP)
|
||||
{
|
||||
case 32:
|
||||
*(outPtr++) = (color & 31) << 2;
|
||||
*(outPtr++) = ((color >> 5) & 31) << 2;
|
||||
*(outPtr++) = ((color >> 10) & 31) << 2;
|
||||
*(outPtr++) = 0; // resvd
|
||||
break;
|
||||
case 24:
|
||||
*(outPtr++) = (color & 31) << 2;
|
||||
*(outPtr++) = ((color >> 5) & 31) << 2;
|
||||
*(outPtr++) = ((color >> 10) & 31) << 2;
|
||||
break;
|
||||
case 16:
|
||||
*(outPtr++) = *(ptr++);
|
||||
*(outPtr++) = *(ptr++);
|
||||
break;
|
||||
case 8:
|
||||
*(outPtr++) = (((color & 31)
|
||||
+ ((color >> 5) & 31)
|
||||
+ ((color >> 10) & 31)) / 3) << 2;
|
||||
break;
|
||||
case 1:
|
||||
if (color)
|
||||
outPtr[column / 8] |= (1 << (7 - (column & 7)));
|
||||
else
|
||||
outPtr[column / 8] &= ~(1 << (7 - (column & 7)));
|
||||
break;
|
||||
} /* end switch(effbpp) */
|
||||
} /* end if effxbpp==16) */
|
||||
} /* end for column */
|
||||
} /* end for row */
|
||||
free (iconData);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Attempt to create a custom icon from the WM_HINTS bitmaps
|
||||
*/
|
||||
|
||||
HICON
|
||||
winXIconToHICON (WindowPtr pWin)
|
||||
{
|
||||
unsigned char *mask, *image, *imageMask;
|
||||
unsigned char *dst, *src;
|
||||
PixmapPtr iconPtr;
|
||||
PixmapPtr maskPtr;
|
||||
int iconSize, planes, bpp, effBPP, stride, maskStride, i;
|
||||
HDC hDC;
|
||||
ICONINFO ii;
|
||||
WinXWMHints hints;
|
||||
HICON hIcon;
|
||||
|
||||
winMultiWindowGetWMHints (pWin, &hints);
|
||||
if (!hints.icon_pixmap) return NULL;
|
||||
|
||||
iconPtr = LookupIDByType (hints.icon_pixmap, RT_PIXMAP);
|
||||
|
||||
if (!iconPtr) return NULL;
|
||||
|
||||
iconSize = 32;
|
||||
|
||||
hDC = GetDC (GetDesktopWindow ());
|
||||
planes = GetDeviceCaps (hDC, PLANES);
|
||||
bpp = GetDeviceCaps (hDC, BITSPIXEL);
|
||||
ReleaseDC (GetDesktopWindow (), hDC);
|
||||
|
||||
/* 15 BPP is really 16BPP as far as we care */
|
||||
if (bpp == 15)
|
||||
effBPP = 16;
|
||||
else
|
||||
effBPP = bpp;
|
||||
|
||||
/* Need 32-bit aligned rows */
|
||||
stride = ((iconSize * effBPP + 31) & (~31)) / 8;
|
||||
|
||||
/* Mask is 1-bit deep */
|
||||
maskStride = ((iconSize * 1 + 31) & (~31)) / 8;
|
||||
|
||||
image = (unsigned char * ) malloc (stride * iconSize);
|
||||
imageMask = (unsigned char *) malloc (stride * iconSize);
|
||||
mask = (unsigned char *) malloc (maskStride * iconSize);
|
||||
|
||||
/* Default to a completely black mask */
|
||||
memset (mask, 0, maskStride * iconSize);
|
||||
|
||||
winScaleXBitmapToWindows (iconSize, effBPP, iconPtr, image);
|
||||
maskPtr = LookupIDByType (hints.icon_mask, RT_PIXMAP);
|
||||
|
||||
if (maskPtr)
|
||||
{
|
||||
winScaleXBitmapToWindows (iconSize, 1, maskPtr, mask);
|
||||
|
||||
winScaleXBitmapToWindows (iconSize, effBPP, maskPtr, imageMask);
|
||||
|
||||
/* Now we need to set all bits of the icon which are not masked */
|
||||
/* on to 0 because Color is really an XOR, not an OR function */
|
||||
dst = image;
|
||||
src = imageMask;
|
||||
|
||||
for (i = 0; i < (stride * iconSize); i++)
|
||||
if ((*(src++)))
|
||||
*(dst++) = 0;
|
||||
else
|
||||
dst++;
|
||||
}
|
||||
|
||||
ii.fIcon = TRUE;
|
||||
ii.xHotspot = 0; /* ignored */
|
||||
ii.yHotspot = 0; /* ignored */
|
||||
|
||||
/* Create Win32 mask from pixmap shape */
|
||||
ii.hbmMask = CreateBitmap (iconSize, iconSize, planes, 1, mask);
|
||||
|
||||
/* Create Win32 bitmap from pixmap */
|
||||
ii.hbmColor = CreateBitmap (iconSize, iconSize, planes, bpp, image);
|
||||
|
||||
/* Merge Win32 mask and bitmap into icon */
|
||||
hIcon = CreateIconIndirect (&ii);
|
||||
|
||||
/* Release Win32 mask and bitmap */
|
||||
DeleteObject (ii.hbmMask);
|
||||
DeleteObject (ii.hbmColor);
|
||||
|
||||
/* Free X mask and bitmap */
|
||||
free (mask);
|
||||
free (image);
|
||||
free (imageMask);
|
||||
|
||||
return hIcon;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Change the Windows window icon
|
||||
*/
|
||||
|
||||
void
|
||||
winUpdateIcon (Window id)
|
||||
{
|
||||
WindowPtr pWin;
|
||||
HICON hIcon, hiconOld;
|
||||
|
||||
pWin = LookupIDByType (id, RT_WINDOW);
|
||||
hIcon = (HICON)winOverrideIcon ((unsigned long)pWin);
|
||||
|
||||
if (!hIcon)
|
||||
hIcon = winXIconToHICON (pWin);
|
||||
|
||||
if (hIcon)
|
||||
{
|
||||
winWindowPriv(pWin);
|
||||
|
||||
if (pWinPriv->hWnd)
|
||||
{
|
||||
hiconOld = (HICON) SetClassLong (pWinPriv->hWnd,
|
||||
GCL_HICON,
|
||||
(int) hIcon);
|
||||
|
||||
/* Delete the icon if its not the default */
|
||||
if (hiconOld != g_hiconX &&
|
||||
!winIconIsOverride((unsigned long)hiconOld))
|
||||
DeleteObject (hiconOld);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user