637 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			637 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 *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
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_XWIN_CONFIG_H
 | 
						|
#include <xwin-config.h>
 | 
						|
#endif
 | 
						|
#include "win.h"
 | 
						|
#include "dixevents.h"
 | 
						|
#include "winmultiwindowclass.h"
 | 
						|
#include "winprefs.h"
 | 
						|
 | 
						|
#include "propertyst.h"
 | 
						|
#include "windowstr.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * 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;
 | 
						|
    char *iconData = 0;
 | 
						|
    int stride, xStride;
 | 
						|
    float factX, factY;
 | 
						|
    int posX, posY;
 | 
						|
    unsigned char *ptr;
 | 
						|
    unsigned int zero;
 | 
						|
    unsigned int color;
 | 
						|
 | 
						|
    effXBPP = BitsPerPixel(pixmap->drawable.depth);
 | 
						|
    effXDepth = pixmap->drawable.depth;
 | 
						|
 | 
						|
    if (pixmap->drawable.bitsPerPixel == 15)
 | 
						|
        effXBPP = 16;
 | 
						|
 | 
						|
    if (pixmap->drawable.depth == 15)
 | 
						|
        effXDepth = 16;
 | 
						|
 | 
						|
    /* Need 16-bit aligned rows for DDBitmaps */
 | 
						|
    stride = ((iconSize * effBPP + 15) & (~15)) / 8;
 | 
						|
    xStride = PixmapBytePad(pixmap->drawable.width, pixmap->drawable.depth);
 | 
						|
    if (stride == 0 || xStride == 0) {
 | 
						|
        ErrorF("winScaleXBitmapToWindows - stride or xStride is zero.  "
 | 
						|
               "Bailing.\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Allocate memory for icon data */
 | 
						|
    iconData = malloc(xStride * pixmap->drawable.height);
 | 
						|
    if (!iconData) {
 | 
						|
        ErrorF("winScaleXBitmapToWindows - malloc failed for iconData.  "
 | 
						|
               "Bailing.\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Get icon data */
 | 
						|
    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 = (unsigned char *) 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++) = (effXDepth == 32) ? *(ptr++) : 0x0;   /* alpha */
 | 
						|
                    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);
 | 
						|
}
 | 
						|
 | 
						|
static HICON
 | 
						|
NetWMToWinIconAlpha(uint32_t * icon)
 | 
						|
{
 | 
						|
    int width = icon[0];
 | 
						|
    int height = icon[1];
 | 
						|
    uint32_t *pixels = &icon[2];
 | 
						|
    HICON result;
 | 
						|
    HDC hdc = GetDC(NULL);
 | 
						|
    uint32_t *DIB_pixels;
 | 
						|
    ICONINFO ii = { TRUE };
 | 
						|
    BITMAPV4HEADER bmh = { sizeof(bmh) };
 | 
						|
 | 
						|
    /* Define an ARGB pixel format used for Color+Alpha icons */
 | 
						|
    bmh.bV4Width = width;
 | 
						|
    bmh.bV4Height = -height;    /* Invert the image */
 | 
						|
    bmh.bV4Planes = 1;
 | 
						|
    bmh.bV4BitCount = 32;
 | 
						|
    bmh.bV4V4Compression = BI_BITFIELDS;
 | 
						|
    bmh.bV4AlphaMask = 0xFF000000;
 | 
						|
    bmh.bV4RedMask = 0x00FF0000;
 | 
						|
    bmh.bV4GreenMask = 0x0000FF00;
 | 
						|
    bmh.bV4BlueMask = 0x000000FF;
 | 
						|
 | 
						|
    ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) & bmh,
 | 
						|
                                   DIB_RGB_COLORS, (void **) &DIB_pixels, NULL,
 | 
						|
                                   0);
 | 
						|
    ReleaseDC(NULL, hdc);
 | 
						|
    ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL);
 | 
						|
    memcpy(DIB_pixels, pixels, height * width * 4);
 | 
						|
 | 
						|
    /* CreateIconIndirect() traditionally required DDBitmaps */
 | 
						|
    /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */
 | 
						|
    /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */
 | 
						|
    result = CreateIconIndirect(&ii);
 | 
						|
 | 
						|
    DeleteObject(ii.hbmColor);
 | 
						|
    DeleteObject(ii.hbmMask);
 | 
						|
 | 
						|
    winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
static HICON
 | 
						|
NetWMToWinIconThreshold(uint32_t * icon)
 | 
						|
{
 | 
						|
    int width = icon[0];
 | 
						|
    int height = icon[1];
 | 
						|
    uint32_t *pixels = &icon[2];
 | 
						|
    int row, col;
 | 
						|
    HICON result;
 | 
						|
    ICONINFO ii = { TRUE };
 | 
						|
 | 
						|
    HDC hdc = GetDC(NULL);
 | 
						|
    HDC xorDC = CreateCompatibleDC(hdc);
 | 
						|
    HDC andDC = CreateCompatibleDC(hdc);
 | 
						|
 | 
						|
    ii.hbmColor = CreateCompatibleBitmap(hdc, width, height);
 | 
						|
    ii.hbmMask = CreateCompatibleBitmap(hdc, width, height);
 | 
						|
    ReleaseDC(NULL, hdc);
 | 
						|
    SelectObject(xorDC, ii.hbmColor);
 | 
						|
    SelectObject(andDC, ii.hbmMask);
 | 
						|
 | 
						|
    for (row = 0; row < height; row++) {
 | 
						|
        for (col = 0; col < width; col++) {
 | 
						|
            if ((*pixels & 0xFF000000) > 31 << 24) {    /* 31 alpha threshold, i.e. opaque above, transparent below */
 | 
						|
                SetPixelV(xorDC, col, row,
 | 
						|
                          RGB(((char *) pixels)[2], ((char *) pixels)[1],
 | 
						|
                              ((char *) pixels)[0]));
 | 
						|
                SetPixelV(andDC, col, row, RGB(0, 0, 0));       /* black mask */
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                SetPixelV(xorDC, col, row, RGB(0, 0, 0));
 | 
						|
                SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */
 | 
						|
            }
 | 
						|
            pixels++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    DeleteDC(xorDC);
 | 
						|
    DeleteDC(andDC);
 | 
						|
 | 
						|
    result = CreateIconIndirect(&ii);
 | 
						|
 | 
						|
    DeleteObject(ii.hbmColor);
 | 
						|
    DeleteObject(ii.hbmMask);
 | 
						|
 | 
						|
    winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1],
 | 
						|
             result);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
static HICON
 | 
						|
NetWMToWinIcon(int bpp, uint32_t * icon)
 | 
						|
{
 | 
						|
    static Bool hasIconAlphaChannel = FALSE;
 | 
						|
    static BOOL versionChecked = FALSE;
 | 
						|
 | 
						|
    if (!versionChecked) {
 | 
						|
        OSVERSIONINFOEX osvi = { 0 };
 | 
						|
        ULONGLONG dwlConditionMask = 0;
 | 
						|
 | 
						|
        osvi.dwOSVersionInfoSize = sizeof(osvi);
 | 
						|
        osvi.dwMajorVersion = 5;
 | 
						|
        osvi.dwMinorVersion = 1;
 | 
						|
 | 
						|
        /* Windows versions later than XP have icon alpha channel suport, 2000 does not */
 | 
						|
        VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION,
 | 
						|
                          VER_GREATER_EQUAL);
 | 
						|
        VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION,
 | 
						|
                          VER_GREATER_EQUAL);
 | 
						|
        hasIconAlphaChannel =
 | 
						|
            VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
 | 
						|
                              dwlConditionMask);
 | 
						|
        versionChecked = TRUE;
 | 
						|
 | 
						|
        ErrorF("OS has icon alpha channel support: %s\n",
 | 
						|
               hasIconAlphaChannel ? "yes" : "no");
 | 
						|
    }
 | 
						|
 | 
						|
    if (hasIconAlphaChannel && (bpp == 32))
 | 
						|
        return NetWMToWinIconAlpha(icon);
 | 
						|
    else
 | 
						|
        return NetWMToWinIconThreshold(icon);
 | 
						|
}
 | 
						|
 | 
						|
static pointer
 | 
						|
GetWindowProp(WindowPtr pWin, Atom name, long int *size_return)
 | 
						|
{
 | 
						|
    struct _Window *pwin;
 | 
						|
    struct _Property *prop;
 | 
						|
 | 
						|
    if (!pWin || !name) {
 | 
						|
        ErrorF("GetWindowProp - pWin or name was NULL\n");
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
    pwin = (struct _Window *) pWin;
 | 
						|
    if (!pwin->optional)
 | 
						|
        return NULL;
 | 
						|
    for (prop = (struct _Property *) pwin->optional->userProps;
 | 
						|
         prop; prop = prop->next) {
 | 
						|
        if (prop->propertyName == name) {
 | 
						|
            *size_return = prop->size;
 | 
						|
            return prop->data;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Attempt to create a custom icon from the WM_HINTS bitmaps
 | 
						|
 */
 | 
						|
 | 
						|
HICON
 | 
						|
winXIconToHICON(WindowPtr pWin, int iconSize)
 | 
						|
{
 | 
						|
    unsigned char *mask, *image, *imageMask;
 | 
						|
    unsigned char *dst, *src;
 | 
						|
    PixmapPtr iconPtr;
 | 
						|
    PixmapPtr maskPtr;
 | 
						|
    int planes, bpp, effBPP, stride, maskStride, i;
 | 
						|
    int biggest_size = 0;
 | 
						|
    HDC hDC;
 | 
						|
    ICONINFO ii;
 | 
						|
    WinXWMHints hints;
 | 
						|
    HICON hIcon = NULL;
 | 
						|
    uint32_t *biggest_icon = NULL;
 | 
						|
 | 
						|
    /* Try to get _NET_WM_ICON icons first */
 | 
						|
    static Atom _XA_NET_WM_ICON;
 | 
						|
    static int generation;
 | 
						|
    uint32_t *icon, *icon_data = NULL;
 | 
						|
    long int size = 0;
 | 
						|
 | 
						|
    hDC = GetDC(GetDesktopWindow());
 | 
						|
    planes = GetDeviceCaps(hDC, PLANES);
 | 
						|
    bpp = GetDeviceCaps(hDC, BITSPIXEL);
 | 
						|
    ReleaseDC(GetDesktopWindow(), hDC);
 | 
						|
 | 
						|
    if (generation != serverGeneration) {
 | 
						|
        generation = serverGeneration;
 | 
						|
        _XA_NET_WM_ICON = MakeAtom("_NET_WM_ICON", 12, TRUE);
 | 
						|
    }
 | 
						|
 | 
						|
    if (_XA_NET_WM_ICON)
 | 
						|
        icon_data = GetWindowProp(pWin, _XA_NET_WM_ICON, &size);
 | 
						|
    if (icon_data) {
 | 
						|
        for (icon = icon_data;
 | 
						|
             icon < &icon_data[size] && *icon;
 | 
						|
             icon = &icon[icon[0] * icon[1] + 2]) {
 | 
						|
            if (icon[0] == iconSize && icon[1] == iconSize)
 | 
						|
                return NetWMToWinIcon(bpp, icon);
 | 
						|
            /* Find the biggest icon and let Windows scale the size */
 | 
						|
            else if (biggest_size < icon[0]) {
 | 
						|
                biggest_icon = icon;
 | 
						|
                biggest_size = icon[0];
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (biggest_icon)
 | 
						|
            return NetWMToWinIcon(bpp, biggest_icon);
 | 
						|
    }
 | 
						|
    winDebug("winXIconToHICON - pWin %x: no suitable NetIcon\n", (int) pWin,
 | 
						|
             iconSize);
 | 
						|
 | 
						|
    winMultiWindowGetWMHints(pWin, &hints);
 | 
						|
    if (!hints.icon_pixmap)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    dixLookupResourceByType((pointer) &iconPtr, hints.icon_pixmap, RT_PIXMAP,
 | 
						|
                            NullClient, DixUnknownAccess);
 | 
						|
 | 
						|
    if (!iconPtr)
 | 
						|
        return NULL;
 | 
						|
 | 
						|
    /* 15 BPP is really 16BPP as far as we care */
 | 
						|
    if (bpp == 15)
 | 
						|
        effBPP = 16;
 | 
						|
    else
 | 
						|
        effBPP = bpp;
 | 
						|
 | 
						|
    /* Need 16-bit aligned rows for DDBitmaps */
 | 
						|
    stride = ((iconSize * effBPP + 15) & (~15)) / 8;
 | 
						|
 | 
						|
    /* Mask is 1-bit deep */
 | 
						|
    maskStride = ((iconSize * 1 + 15) & (~15)) / 8;
 | 
						|
 | 
						|
    image = malloc(stride * iconSize);
 | 
						|
    imageMask = malloc(stride * iconSize);
 | 
						|
    /* Default to a completely black mask */
 | 
						|
    mask = calloc(maskStride, iconSize);
 | 
						|
 | 
						|
    winScaleXBitmapToWindows(iconSize, effBPP, iconPtr, image);
 | 
						|
    dixLookupResourceByType((pointer) &maskPtr, hints.icon_mask, RT_PIXMAP,
 | 
						|
                            NullClient, DixUnknownAccess);
 | 
						|
 | 
						|
    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 
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef XWIN_MULTIWINDOW
 | 
						|
void
 | 
						|
winUpdateIcon(Window id)
 | 
						|
{
 | 
						|
    WindowPtr pWin;
 | 
						|
    HICON hIcon, hIconSmall = NULL, hIconOld;
 | 
						|
 | 
						|
    dixLookupResourceByType((pointer) &pWin, id, RT_WINDOW, NullClient,
 | 
						|
                            DixUnknownAccess);
 | 
						|
    if (pWin) {
 | 
						|
        winWindowPriv(pWin);
 | 
						|
        if (pWinPriv->hWnd) {
 | 
						|
            hIcon = winOverrideIcon((unsigned long) pWin);
 | 
						|
            if (!hIcon) {
 | 
						|
                hIcon = winXIconToHICON(pWin, GetSystemMetrics(SM_CXICON));
 | 
						|
                if (!hIcon) {
 | 
						|
                    hIcon = g_hIconX;
 | 
						|
                    hIconSmall = g_hSmallIconX;
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    /* Leave undefined if not found */
 | 
						|
                    hIconSmall =
 | 
						|
                        winXIconToHICON(pWin, GetSystemMetrics(SM_CXSMICON));
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            /* Set the large icon */
 | 
						|
            hIconOld = (HICON) SendMessage(pWinPriv->hWnd,
 | 
						|
                                           WM_SETICON, ICON_BIG,
 | 
						|
                                           (LPARAM) hIcon);
 | 
						|
 | 
						|
            /* Delete the icon if its not the default */
 | 
						|
            winDestroyIcon(hIconOld);
 | 
						|
 | 
						|
            /* Same for the small icon */
 | 
						|
            hIconOld = (HICON) SendMessage(pWinPriv->hWnd,
 | 
						|
                                           WM_SETICON, ICON_SMALL,
 | 
						|
                                           (LPARAM) hIconSmall);
 | 
						|
            winDestroyIcon(hIconOld);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
winInitGlobalIcons(void)
 | 
						|
{
 | 
						|
    int sm_cx = GetSystemMetrics(SM_CXICON);
 | 
						|
    int sm_cxsm = GetSystemMetrics(SM_CXSMICON);
 | 
						|
 | 
						|
    /* Load default X icon in case it's not ready yet */
 | 
						|
    if (!g_hIconX) {
 | 
						|
        g_hIconX = winOverrideDefaultIcon(sm_cx);
 | 
						|
        g_hSmallIconX = winOverrideDefaultIcon(sm_cxsm);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!g_hIconX) {
 | 
						|
        g_hIconX = (HICON) LoadImage(g_hInstance,
 | 
						|
                                     MAKEINTRESOURCE(IDI_XWIN),
 | 
						|
                                     IMAGE_ICON,
 | 
						|
                                     GetSystemMetrics(SM_CXICON),
 | 
						|
                                     GetSystemMetrics(SM_CYICON), 0);
 | 
						|
        g_hSmallIconX = (HICON) LoadImage(g_hInstance,
 | 
						|
                                          MAKEINTRESOURCE(IDI_XWIN),
 | 
						|
                                          IMAGE_ICON,
 | 
						|
                                          GetSystemMetrics(SM_CXSMICON),
 | 
						|
                                          GetSystemMetrics(SM_CYSMICON),
 | 
						|
                                          LR_DEFAULTSIZE);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
winSelectIcons(WindowPtr pWin, HICON * pIcon, HICON * pSmallIcon)
 | 
						|
{
 | 
						|
    HICON hIcon, hSmallIcon;
 | 
						|
 | 
						|
    winInitGlobalIcons();
 | 
						|
 | 
						|
    /* Try and get the icon from WM_HINTS */
 | 
						|
    hIcon = winXIconToHICON(pWin, GetSystemMetrics(SM_CXICON));
 | 
						|
    hSmallIcon = winXIconToHICON(pWin, GetSystemMetrics(SM_CXSMICON));
 | 
						|
 | 
						|
    /* If we got the small, but not the large one swap them */
 | 
						|
    if (!hIcon && hSmallIcon) {
 | 
						|
        hIcon = hSmallIcon;
 | 
						|
        hSmallIcon = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Use default X icon if no icon loaded from WM_HINTS */
 | 
						|
    if (!hIcon) {
 | 
						|
        hIcon = g_hIconX;
 | 
						|
        hSmallIcon = g_hSmallIconX;
 | 
						|
    }
 | 
						|
 | 
						|
    if (pIcon)
 | 
						|
        *pIcon = hIcon;
 | 
						|
    else
 | 
						|
        winDestroyIcon(hIcon);
 | 
						|
 | 
						|
    if (pSmallIcon)
 | 
						|
        *pSmallIcon = hSmallIcon;
 | 
						|
    else
 | 
						|
        winDestroyIcon(hSmallIcon);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
winDestroyIcon(HICON hIcon)
 | 
						|
{
 | 
						|
    /* Delete the icon if its not one of the application defaults or an override */
 | 
						|
    if (hIcon &&
 | 
						|
        hIcon != g_hIconX &&
 | 
						|
        hIcon != g_hSmallIconX && !winIconIsOverride((unsigned long) hIcon))
 | 
						|
        DestroyIcon(hIcon);
 | 
						|
}
 | 
						|
#endif
 |