From 0f834b91a4768673833ab4917e87d86c237bb1a6 Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 23 Mar 2012 10:05:55 +0100 Subject: libX11 xserver fontconfig mesa pixman xkbcomp xkeyboard-config git update 23 Mar 2012 --- xorg-server/hw/xwin/wincursor.c | 1240 +++++++++++++++++++-------------------- 1 file changed, 613 insertions(+), 627 deletions(-) (limited to 'xorg-server/hw/xwin/wincursor.c') diff --git a/xorg-server/hw/xwin/wincursor.c b/xorg-server/hw/xwin/wincursor.c index 9f669bcf8..b56104fde 100644 --- a/xorg-server/hw/xwin/wincursor.c +++ b/xorg-server/hw/xwin/wincursor.c @@ -1,627 +1,613 @@ -/* - *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: Dakshinamurthy Karra - * Suhaib M Siddiqi - * Peter Busch - * Harold L Hunt II - */ - -#ifdef HAVE_XWIN_CONFIG_H -#include -#endif -#include "win.h" -#include "winmsg.h" -#include -#include -#include -#include "misc.h" - -#define BRIGHTNESS(x) (x##Red * 0.299 + x##Green * 0.587 + x##Blue * 0.114) - -#if 0 -# define WIN_DEBUG_MSG winDebug -#else -# define WIN_DEBUG_MSG(...) -#endif - -/* - * Local function prototypes - */ - -static void -winPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); - -static Bool -winCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y); - -static void -winCrossScreen (ScreenPtr pScreen, Bool fEntering); - -miPointerScreenFuncRec g_winPointerCursorFuncs = -{ - winCursorOffScreen, - winCrossScreen, - winPointerWarpCursor -}; - - -static void -winPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - winScreenPriv(pScreen); - RECT rcClient; - static Bool s_fInitialWarp = TRUE; - - /* Discard first warp call */ - if (s_fInitialWarp) - { - /* First warp moves mouse to center of window, just ignore it */ - - /* Don't ignore subsequent warps */ - s_fInitialWarp = FALSE; - - winErrorFVerb (2, "winPointerWarpCursor - Discarding first warp: %d %d\n", - x, y); - - return; - } - - /* - Only update the Windows cursor position if root window is active, - or we are in a rootless mode - */ - if ((pScreenPriv->hwndScreen == GetForegroundWindow ()) - || pScreenPriv->pScreenInfo->fRootless -#ifdef XWIN_MULTIWINDOW - || pScreenPriv->pScreenInfo->fMultiWindow -#endif - ) - { - /* Get the client area coordinates */ - GetClientRect (pScreenPriv->hwndScreen, &rcClient); - - /* Translate the client area coords to screen coords */ - MapWindowPoints (pScreenPriv->hwndScreen, - HWND_DESKTOP, - (LPPOINT)&rcClient, - 2); - - /* - * Update the Windows cursor position so that we don't - * immediately warp back to the current position. - */ - SetCursorPos (rcClient.left + x, rcClient.top + y); - } - - /* Call the mi warp procedure to do the actual warping in X. */ - miPointerWarpCursor (pDev, pScreen, x, y); -} - -static Bool -winCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y) -{ - return FALSE; -} - -static void -winCrossScreen (ScreenPtr pScreen, Bool fEntering) -{ -} - -static unsigned char -reverse(unsigned char c) -{ - int i; - unsigned char ret = 0; - for (i = 0; i < 8; ++i) - { - ret |= ((c >> i)&1) << (7 - i); - } - return ret; -} - -/* - * Convert X cursor to Windows cursor - * FIXME: Perhaps there are more smart code - */ -static HCURSOR -winLoadCursor (ScreenPtr pScreen, CursorPtr pCursor, int screen) -{ - winScreenPriv(pScreen); - HCURSOR hCursor = NULL; - unsigned char *pAnd; - unsigned char *pXor; - int nCX, nCY; - int nBytes; - double dForeY, dBackY; - BOOL fReverse; - HBITMAP hAnd, hXor; - ICONINFO ii; - unsigned char *pCur; - int x, y; - unsigned char bit; - HDC hDC; - BITMAPV4HEADER bi; - BITMAPINFO *pbmi; - unsigned long *lpBits; - - WIN_DEBUG_MSG("winLoadCursor: Win32: %dx%d X11: %dx%d hotspot: %d,%d\n", - pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, - pCursor->bits->width, pCursor->bits->height, - pCursor->bits->xhot, pCursor->bits->yhot - ); - - /* We can use only White and Black, so calc brightness of color - * Also check if the cursor is inverted */ - dForeY = BRIGHTNESS(pCursor->fore); - dBackY = BRIGHTNESS(pCursor->back); - fReverse = dForeY < dBackY; - - /* Check wether the X11 cursor is bigger than the win32 cursor */ - if (pScreenPriv->cursor.sm_cx < pCursor->bits->width || - pScreenPriv->cursor.sm_cy < pCursor->bits->height) - { - winErrorFVerb (3, "winLoadCursor - Windows requires %dx%d cursor but X requires %dx%d\n", - pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, - pCursor->bits->width, pCursor->bits->height); - } - - /* Get the number of bytes required to store the whole cursor image - * This is roughly (sm_cx * sm_cy) / 8 - * round up to 8 pixel boundary so we can convert whole bytes */ - nBytes = bits_to_bytes(pScreenPriv->cursor.sm_cx) * pScreenPriv->cursor.sm_cy; - - /* Get the effective width and height */ - nCX = min(pScreenPriv->cursor.sm_cx, pCursor->bits->width); - nCY = min(pScreenPriv->cursor.sm_cy, pCursor->bits->height); - - /* Allocate memory for the bitmaps */ - pAnd = malloc (nBytes); - memset (pAnd, 0xFF, nBytes); - pXor = calloc (1, nBytes); - - /* Convert the X11 bitmap to a win32 bitmap - * The first is for an empty mask */ - if (pCursor->bits->emptyMask) - { - int x, y, xmax = bits_to_bytes(nCX); - for (y = 0; y < nCY; ++y) - for (x = 0; x < xmax; ++x) - { - int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x; - int nXPix = BitmapBytePad(pCursor->bits->width) * y + x; - - pAnd[nWinPix] = 0; - if (fReverse) - pXor[nWinPix] = reverse (~pCursor->bits->source[nXPix]); - else - pXor[nWinPix] = reverse (pCursor->bits->source[nXPix]); - } - } - else - { - int x, y, xmax = bits_to_bytes(nCX); - for (y = 0; y < nCY; ++y) - for (x = 0; x < xmax; ++x) - { - int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x; - int nXPix = BitmapBytePad(pCursor->bits->width) * y + x; - - unsigned char mask = pCursor->bits->mask[nXPix]; - pAnd[nWinPix] = reverse (~mask); - if (fReverse) - pXor[nWinPix] = reverse (~pCursor->bits->source[nXPix] & mask); - else - pXor[nWinPix] = reverse (pCursor->bits->source[nXPix] & mask); - } - } - - /* prepare the pointers */ - hCursor = NULL; - lpBits = NULL; - - /* We have a truecolor alpha-blended cursor and can use it! */ - if (pCursor->bits->argb) - { - WIN_DEBUG_MSG("winLoadCursor: Trying truecolor alphablended cursor\n"); - memset (&bi, 0, sizeof (BITMAPV4HEADER)); - bi.bV4Size = sizeof(BITMAPV4HEADER); - bi.bV4Width = pScreenPriv->cursor.sm_cx; - bi.bV4Height = -(pScreenPriv->cursor.sm_cy); /* right-side up */ - bi.bV4Planes = 1; - bi.bV4BitCount = 32; - bi.bV4V4Compression = BI_BITFIELDS; - bi.bV4RedMask = 0x00FF0000; - bi.bV4GreenMask = 0x0000FF00; - bi.bV4BlueMask = 0x000000FF; - bi.bV4AlphaMask = 0xFF000000; - - lpBits = (unsigned long *) calloc (pScreenPriv->cursor.sm_cx*pScreenPriv->cursor.sm_cy, - sizeof (unsigned long)); - - if (lpBits) - { - for (y=0; ybits->argb[y * pCursor->bits->width]); - dst = &(lpBits[y * pScreenPriv->cursor.sm_cx]); - memcpy (dst, src, 4*nCX); - } - } - } /* End if-truecolor-icon */ - - if (!lpBits) - { - /* Bicolor, use a palettized DIB */ - WIN_DEBUG_MSG("winLoadCursor: Trying two color cursor\n"); - pbmi = (BITMAPINFO*)&bi; - memset (pbmi, 0, sizeof (BITMAPINFOHEADER)); - pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - pbmi->bmiHeader.biWidth = pScreenPriv->cursor.sm_cx; - pbmi->bmiHeader.biHeight = -abs(pScreenPriv->cursor.sm_cy); /* right-side up */ - pbmi->bmiHeader.biPlanes = 1; - pbmi->bmiHeader.biBitCount = 8; - pbmi->bmiHeader.biCompression = BI_RGB; - pbmi->bmiHeader.biSizeImage = 0; - pbmi->bmiHeader.biClrUsed = 3; - pbmi->bmiHeader.biClrImportant = 3; - pbmi->bmiColors[0].rgbRed = 0; /* Empty */ - pbmi->bmiColors[0].rgbGreen = 0; - pbmi->bmiColors[0].rgbBlue = 0; - pbmi->bmiColors[0].rgbReserved = 0; - pbmi->bmiColors[1].rgbRed = pCursor->backRed>>8; /* Background */ - pbmi->bmiColors[1].rgbGreen = pCursor->backGreen>>8; - pbmi->bmiColors[1].rgbBlue = pCursor->backBlue>>8; - pbmi->bmiColors[1].rgbReserved = 0; - pbmi->bmiColors[2].rgbRed = pCursor->foreRed>>8; /* Foreground */ - pbmi->bmiColors[2].rgbGreen = pCursor->foreGreen>>8; - pbmi->bmiColors[2].rgbBlue = pCursor->foreBlue>>8; - pbmi->bmiColors[2].rgbReserved = 0; - - lpBits = (unsigned long *) calloc (pScreenPriv->cursor.sm_cx*pScreenPriv->cursor.sm_cy, - sizeof (char)); - - pCur = (unsigned char *)lpBits; - if (lpBits) - { - for (y=0; ycursor.sm_cy; y++) - { - for (x=0; xcursor.sm_cx; x++) - { - if (x>=nCX || y>=nCY) /* Outside of X11 icon bounds */ - (*pCur++) = 0; - else /* Within X11 icon bounds */ - { - int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + (x/8); - - bit = pAnd[nWinPix]; - bit = bit & (1<<(7-(x&7))); - if (!bit) /* Within the cursor mask? */ - { - int nXPix = BitmapBytePad(pCursor->bits->width) * y + (x/8); - bit = ~reverse(~pCursor->bits->source[nXPix] & pCursor->bits->mask[nXPix]); - bit = bit & (1<<(7-(x&7))); - if (bit) /* Draw foreground */ - (*pCur++) = 2; - else /* Draw background */ - (*pCur++) = 1; - } - else /* Outside the cursor mask */ - (*pCur++) = 0; - } - } /* end for (x) */ - } /* end for (y) */ - } /* end if (lpbits) */ - } - - /* If one of the previous two methods gave us the bitmap we need, make a cursor */ - if (lpBits) - { - WIN_DEBUG_MSG("winLoadCursor: Creating bitmap cursor: hotspot %d,%d\n", - pCursor->bits->xhot, pCursor->bits->yhot); - - hAnd = NULL; - hXor = NULL; - - hAnd = CreateBitmap (pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, 1, 1, pAnd); - - hDC = GetDC (NULL); - if (hDC) - { - hXor = CreateCompatibleBitmap (hDC, pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy); - SetDIBits (hDC, hXor, 0, pScreenPriv->cursor.sm_cy, lpBits, (BITMAPINFO*)&bi, DIB_RGB_COLORS); - ReleaseDC (NULL, hDC); - } - free (lpBits); - - - if (hAnd && hXor) - { - ii.fIcon = FALSE; - ii.xHotspot = pCursor->bits->xhot; - ii.yHotspot = pCursor->bits->yhot; - ii.hbmMask = hAnd; - ii.hbmColor = hXor; - hCursor = (HCURSOR) CreateIconIndirect( &ii ); - - if (hCursor == NULL) - winW32Error(2, "winLoadCursor - CreateIconIndirect failed:"); - else - { - if (GetIconInfo(hCursor, &ii)) - { - if (ii.fIcon) - { - WIN_DEBUG_MSG("winLoadCursor: CreateIconIndirect returned no cursor. Trying again.\n"); - - DestroyCursor(hCursor); - - ii.fIcon = FALSE; - ii.xHotspot = pCursor->bits->xhot; - ii.yHotspot = pCursor->bits->yhot; - hCursor = (HCURSOR) CreateIconIndirect( &ii ); - - if (hCursor == NULL) - winW32Error(2, "winLoadCursor - CreateIconIndirect failed:"); - } - /* GetIconInfo creates new bitmaps. Destroy them again */ - if (ii.hbmMask) - DeleteObject(ii.hbmMask); - if (ii.hbmColor) - DeleteObject(ii.hbmColor); - } - } - } - - if (hAnd) - DeleteObject (hAnd); - if (hXor) - DeleteObject (hXor); - } - - if (!hCursor) - { - /* We couldn't make a color cursor for this screen, use - black and white instead */ - hCursor = CreateCursor (g_hInstance, - pCursor->bits->xhot, pCursor->bits->yhot, - pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, - pAnd, pXor); - if (hCursor == NULL) - winW32Error(2, "winLoadCursor - CreateCursor failed:"); - } - free (pAnd); - free (pXor); - - return hCursor; -} - -/* -=========================================================================== - - Pointer sprite functions - -=========================================================================== -*/ - -/* - * winRealizeCursor - * Convert the X cursor representation to native format if possible. - */ -static Bool -winRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - if(pCursor == NULL || pCursor->bits == NULL) - return FALSE; - - /* FIXME: cache ARGB8888 representation? */ - - return TRUE; -} - - -/* - * winUnrealizeCursor - * Free the storage space associated with a realized cursor. - */ -static Bool -winUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - return TRUE; -} - - -/* - * winSetCursor - * Set the cursor sprite and position. - */ -static void -winSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) -{ - POINT ptCurPos, ptTemp; - HWND hwnd; - RECT rcClient; - BOOL bInhibit; - winScreenPriv(pScreen); - WIN_DEBUG_MSG("winSetCursor: cursor=%p\n", pCursor); - - /* Inhibit changing the cursor if the mouse is not in a client area */ - bInhibit = FALSE; - if (GetCursorPos (&ptCurPos)) - { - hwnd = WindowFromPoint (ptCurPos); - if (hwnd) - { - if (GetClientRect (hwnd, &rcClient)) - { - ptTemp.x = rcClient.left; - ptTemp.y = rcClient.top; - if (ClientToScreen (hwnd, &ptTemp)) - { - rcClient.left = ptTemp.x; - rcClient.top = ptTemp.y; - ptTemp.x = rcClient.right; - ptTemp.y = rcClient.bottom; - if (ClientToScreen (hwnd, &ptTemp)) - { - rcClient.right = ptTemp.x; - rcClient.bottom = ptTemp.y; - if (!PtInRect (&rcClient, ptCurPos)) - bInhibit = TRUE; - } - } - } - } - } - - if (pCursor == NULL) - { - if (pScreenPriv->cursor.visible) - { - if (!bInhibit && g_fSoftwareCursor) - ShowCursor (FALSE); - pScreenPriv->cursor.visible = FALSE; - } - } - else - { - if (pScreenPriv->cursor.handle) - { - if (!bInhibit) - SetCursor (NULL); - DestroyCursor (pScreenPriv->cursor.handle); - pScreenPriv->cursor.handle = NULL; - } - pScreenPriv->cursor.handle = - winLoadCursor (pScreen, pCursor, pScreen->myNum); - WIN_DEBUG_MSG("winSetCursor: handle=%p\n", pScreenPriv->cursor.handle); - - if (!bInhibit) - SetCursor (pScreenPriv->cursor.handle); - - if (!pScreenPriv->cursor.visible) - { - if (!bInhibit && g_fSoftwareCursor) - ShowCursor (TRUE); - pScreenPriv->cursor.visible = TRUE; - } - } -} - - -/* - * winMoveCursor - * Move the cursor. This is a noop for us. - */ -static void -winMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ -} - -static Bool -winDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) -{ - winScreenPriv(pScr); - return pScreenPriv->cursor.spriteFuncs->DeviceCursorInitialize(pDev, pScr); -} - -static void -winDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr) -{ - winScreenPriv(pScr); - pScreenPriv->cursor.spriteFuncs->DeviceCursorCleanup(pDev, pScr); -} - -static miPointerSpriteFuncRec winSpriteFuncsRec = { - winRealizeCursor, - winUnrealizeCursor, - winSetCursor, - winMoveCursor, - winDeviceCursorInitialize, - winDeviceCursorCleanup -}; - - -/* -=========================================================================== - - Other screen functions - -=========================================================================== -*/ - -/* - * winCursorQueryBestSize - * Handle queries for best cursor size - */ -static void -winCursorQueryBestSize (int class, unsigned short *width, - unsigned short *height, ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - - if (class == CursorShape) - { - *width = pScreenPriv->cursor.sm_cx; - *height = pScreenPriv->cursor.sm_cy; - } - else - { - if (pScreenPriv->cursor.QueryBestSize) - (*pScreenPriv->cursor.QueryBestSize)(class, width, height, pScreen); - } -} - -/* - * winInitCursor - * Initialize cursor support - */ -Bool -winInitCursor (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - miPointerScreenPtr pPointPriv; - /* override some screen procedures */ - pScreenPriv->cursor.QueryBestSize = pScreen->QueryBestSize; - pScreen->QueryBestSize = winCursorQueryBestSize; - - pPointPriv = (miPointerScreenPtr) - dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); - - pScreenPriv->cursor.spriteFuncs = pPointPriv->spriteFuncs; - pPointPriv->spriteFuncs = &winSpriteFuncsRec; - - pScreenPriv->cursor.handle = NULL; - pScreenPriv->cursor.visible = FALSE; - - pScreenPriv->cursor.sm_cx = GetSystemMetrics (SM_CXCURSOR); - pScreenPriv->cursor.sm_cy = GetSystemMetrics (SM_CYCURSOR); - - return TRUE; -} +/* + *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: Dakshinamurthy Karra + * Suhaib M Siddiqi + * Peter Busch + * Harold L Hunt II + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include +#endif +#include "win.h" +#include "winmsg.h" +#include +#include +#include +#include "misc.h" + +#define BRIGHTNESS(x) (x##Red * 0.299 + x##Green * 0.587 + x##Blue * 0.114) + +#if 0 +#define WIN_DEBUG_MSG winDebug +#else +#define WIN_DEBUG_MSG(...) +#endif + +/* + * Local function prototypes + */ + +static void + winPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); + +static Bool + winCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y); + +static void + winCrossScreen(ScreenPtr pScreen, Bool fEntering); + +miPointerScreenFuncRec g_winPointerCursorFuncs = { + winCursorOffScreen, + winCrossScreen, + winPointerWarpCursor +}; + +static void +winPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + winScreenPriv(pScreen); + RECT rcClient; + static Bool s_fInitialWarp = TRUE; + + /* Discard first warp call */ + if (s_fInitialWarp) { + /* First warp moves mouse to center of window, just ignore it */ + + /* Don't ignore subsequent warps */ + s_fInitialWarp = FALSE; + + winErrorFVerb(2, + "winPointerWarpCursor - Discarding first warp: %d %d\n", + x, y); + + return; + } + + /* + Only update the Windows cursor position if root window is active, + or we are in a rootless mode + */ + if ((pScreenPriv->hwndScreen == GetForegroundWindow()) + || pScreenPriv->pScreenInfo->fRootless +#ifdef XWIN_MULTIWINDOW + || pScreenPriv->pScreenInfo->fMultiWindow +#endif + ) { + /* Get the client area coordinates */ + GetClientRect(pScreenPriv->hwndScreen, &rcClient); + + /* Translate the client area coords to screen coords */ + MapWindowPoints(pScreenPriv->hwndScreen, + HWND_DESKTOP, (LPPOINT) & rcClient, 2); + + /* + * Update the Windows cursor position so that we don't + * immediately warp back to the current position. + */ + SetCursorPos(rcClient.left + x, rcClient.top + y); + } + + /* Call the mi warp procedure to do the actual warping in X. */ + miPointerWarpCursor(pDev, pScreen, x, y); +} + +static Bool +winCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) +{ + return FALSE; +} + +static void +winCrossScreen(ScreenPtr pScreen, Bool fEntering) +{ +} + +static unsigned char +reverse(unsigned char c) +{ + int i; + unsigned char ret = 0; + + for (i = 0; i < 8; ++i) { + ret |= ((c >> i) & 1) << (7 - i); + } + return ret; +} + +/* + * Convert X cursor to Windows cursor + * FIXME: Perhaps there are more smart code + */ +static HCURSOR +winLoadCursor(ScreenPtr pScreen, CursorPtr pCursor, int screen) +{ + winScreenPriv(pScreen); + HCURSOR hCursor = NULL; + unsigned char *pAnd; + unsigned char *pXor; + int nCX, nCY; + int nBytes; + double dForeY, dBackY; + BOOL fReverse; + HBITMAP hAnd, hXor; + ICONINFO ii; + unsigned char *pCur; + int x, y; + unsigned char bit; + HDC hDC; + BITMAPV4HEADER bi; + BITMAPINFO *pbmi; + unsigned long *lpBits; + + WIN_DEBUG_MSG("winLoadCursor: Win32: %dx%d X11: %dx%d hotspot: %d,%d\n", + pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, + pCursor->bits->width, pCursor->bits->height, + pCursor->bits->xhot, pCursor->bits->yhot); + + /* We can use only White and Black, so calc brightness of color + * Also check if the cursor is inverted */ + dForeY = BRIGHTNESS(pCursor->fore); + dBackY = BRIGHTNESS(pCursor->back); + fReverse = dForeY < dBackY; + + /* Check wether the X11 cursor is bigger than the win32 cursor */ + if (pScreenPriv->cursor.sm_cx < pCursor->bits->width || + pScreenPriv->cursor.sm_cy < pCursor->bits->height) { + winErrorFVerb(3, + "winLoadCursor - Windows requires %dx%d cursor but X requires %dx%d\n", + pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, + pCursor->bits->width, pCursor->bits->height); + } + + /* Get the number of bytes required to store the whole cursor image + * This is roughly (sm_cx * sm_cy) / 8 + * round up to 8 pixel boundary so we can convert whole bytes */ + nBytes = + bits_to_bytes(pScreenPriv->cursor.sm_cx) * pScreenPriv->cursor.sm_cy; + + /* Get the effective width and height */ + nCX = min(pScreenPriv->cursor.sm_cx, pCursor->bits->width); + nCY = min(pScreenPriv->cursor.sm_cy, pCursor->bits->height); + + /* Allocate memory for the bitmaps */ + pAnd = malloc(nBytes); + memset(pAnd, 0xFF, nBytes); + pXor = calloc(1, nBytes); + + /* Convert the X11 bitmap to a win32 bitmap + * The first is for an empty mask */ + if (pCursor->bits->emptyMask) { + int x, y, xmax = bits_to_bytes(nCX); + + for (y = 0; y < nCY; ++y) + for (x = 0; x < xmax; ++x) { + int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x; + int nXPix = BitmapBytePad(pCursor->bits->width) * y + x; + + pAnd[nWinPix] = 0; + if (fReverse) + pXor[nWinPix] = reverse(~pCursor->bits->source[nXPix]); + else + pXor[nWinPix] = reverse(pCursor->bits->source[nXPix]); + } + } + else { + int x, y, xmax = bits_to_bytes(nCX); + + for (y = 0; y < nCY; ++y) + for (x = 0; x < xmax; ++x) { + int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x; + int nXPix = BitmapBytePad(pCursor->bits->width) * y + x; + + unsigned char mask = pCursor->bits->mask[nXPix]; + + pAnd[nWinPix] = reverse(~mask); + if (fReverse) + pXor[nWinPix] = + reverse(~pCursor->bits->source[nXPix] & mask); + else + pXor[nWinPix] = + reverse(pCursor->bits->source[nXPix] & mask); + } + } + + /* prepare the pointers */ + hCursor = NULL; + lpBits = NULL; + + /* We have a truecolor alpha-blended cursor and can use it! */ + if (pCursor->bits->argb) { + WIN_DEBUG_MSG("winLoadCursor: Trying truecolor alphablended cursor\n"); + memset(&bi, 0, sizeof(BITMAPV4HEADER)); + bi.bV4Size = sizeof(BITMAPV4HEADER); + bi.bV4Width = pScreenPriv->cursor.sm_cx; + bi.bV4Height = -(pScreenPriv->cursor.sm_cy); /* right-side up */ + bi.bV4Planes = 1; + bi.bV4BitCount = 32; + bi.bV4V4Compression = BI_BITFIELDS; + bi.bV4RedMask = 0x00FF0000; + bi.bV4GreenMask = 0x0000FF00; + bi.bV4BlueMask = 0x000000FF; + bi.bV4AlphaMask = 0xFF000000; + + lpBits = + (unsigned long *) calloc(pScreenPriv->cursor.sm_cx * + pScreenPriv->cursor.sm_cy, + sizeof(unsigned long)); + + if (lpBits) { + for (y = 0; y < nCY; y++) { + unsigned long *src, *dst; + + src = &(pCursor->bits->argb[y * pCursor->bits->width]); + dst = &(lpBits[y * pScreenPriv->cursor.sm_cx]); + memcpy(dst, src, 4 * nCX); + } + } + } /* End if-truecolor-icon */ + + if (!lpBits) { + /* Bicolor, use a palettized DIB */ + WIN_DEBUG_MSG("winLoadCursor: Trying two color cursor\n"); + pbmi = (BITMAPINFO *) & bi; + memset(pbmi, 0, sizeof(BITMAPINFOHEADER)); + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = pScreenPriv->cursor.sm_cx; + pbmi->bmiHeader.biHeight = -abs(pScreenPriv->cursor.sm_cy); /* right-side up */ + pbmi->bmiHeader.biPlanes = 1; + pbmi->bmiHeader.biBitCount = 8; + pbmi->bmiHeader.biCompression = BI_RGB; + pbmi->bmiHeader.biSizeImage = 0; + pbmi->bmiHeader.biClrUsed = 3; + pbmi->bmiHeader.biClrImportant = 3; + pbmi->bmiColors[0].rgbRed = 0; /* Empty */ + pbmi->bmiColors[0].rgbGreen = 0; + pbmi->bmiColors[0].rgbBlue = 0; + pbmi->bmiColors[0].rgbReserved = 0; + pbmi->bmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */ + pbmi->bmiColors[1].rgbGreen = pCursor->backGreen >> 8; + pbmi->bmiColors[1].rgbBlue = pCursor->backBlue >> 8; + pbmi->bmiColors[1].rgbReserved = 0; + pbmi->bmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */ + pbmi->bmiColors[2].rgbGreen = pCursor->foreGreen >> 8; + pbmi->bmiColors[2].rgbBlue = pCursor->foreBlue >> 8; + pbmi->bmiColors[2].rgbReserved = 0; + + lpBits = + (unsigned long *) calloc(pScreenPriv->cursor.sm_cx * + pScreenPriv->cursor.sm_cy, sizeof(char)); + + pCur = (unsigned char *) lpBits; + if (lpBits) { + for (y = 0; y < pScreenPriv->cursor.sm_cy; y++) { + for (x = 0; x < pScreenPriv->cursor.sm_cx; x++) { + if (x >= nCX || y >= nCY) /* Outside of X11 icon bounds */ + (*pCur++) = 0; + else { /* Within X11 icon bounds */ + + int nWinPix = + bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + + (x / 8); + + bit = pAnd[nWinPix]; + bit = bit & (1 << (7 - (x & 7))); + if (!bit) { /* Within the cursor mask? */ + int nXPix = + BitmapBytePad(pCursor->bits->width) * y + + (x / 8); + bit = + ~reverse(~pCursor->bits-> + source[nXPix] & pCursor->bits-> + mask[nXPix]); + bit = bit & (1 << (7 - (x & 7))); + if (bit) /* Draw foreground */ + (*pCur++) = 2; + else /* Draw background */ + (*pCur++) = 1; + } + else /* Outside the cursor mask */ + (*pCur++) = 0; + } + } /* end for (x) */ + } /* end for (y) */ + } /* end if (lpbits) */ + } + + /* If one of the previous two methods gave us the bitmap we need, make a cursor */ + if (lpBits) { + WIN_DEBUG_MSG("winLoadCursor: Creating bitmap cursor: hotspot %d,%d\n", + pCursor->bits->xhot, pCursor->bits->yhot); + + hAnd = NULL; + hXor = NULL; + + hAnd = + CreateBitmap(pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, + 1, 1, pAnd); + + hDC = GetDC(NULL); + if (hDC) { + hXor = + CreateCompatibleBitmap(hDC, pScreenPriv->cursor.sm_cx, + pScreenPriv->cursor.sm_cy); + SetDIBits(hDC, hXor, 0, pScreenPriv->cursor.sm_cy, lpBits, + (BITMAPINFO *) & bi, DIB_RGB_COLORS); + ReleaseDC(NULL, hDC); + } + free(lpBits); + + if (hAnd && hXor) { + ii.fIcon = FALSE; + ii.xHotspot = pCursor->bits->xhot; + ii.yHotspot = pCursor->bits->yhot; + ii.hbmMask = hAnd; + ii.hbmColor = hXor; + hCursor = (HCURSOR) CreateIconIndirect(&ii); + + if (hCursor == NULL) + winW32Error(2, "winLoadCursor - CreateIconIndirect failed:"); + else { + if (GetIconInfo(hCursor, &ii)) { + if (ii.fIcon) { + WIN_DEBUG_MSG + ("winLoadCursor: CreateIconIndirect returned no cursor. Trying again.\n"); + + DestroyCursor(hCursor); + + ii.fIcon = FALSE; + ii.xHotspot = pCursor->bits->xhot; + ii.yHotspot = pCursor->bits->yhot; + hCursor = (HCURSOR) CreateIconIndirect(&ii); + + if (hCursor == NULL) + winW32Error(2, + "winLoadCursor - CreateIconIndirect failed:"); + } + /* GetIconInfo creates new bitmaps. Destroy them again */ + if (ii.hbmMask) + DeleteObject(ii.hbmMask); + if (ii.hbmColor) + DeleteObject(ii.hbmColor); + } + } + } + + if (hAnd) + DeleteObject(hAnd); + if (hXor) + DeleteObject(hXor); + } + + if (!hCursor) { + /* We couldn't make a color cursor for this screen, use + black and white instead */ + hCursor = CreateCursor(g_hInstance, + pCursor->bits->xhot, pCursor->bits->yhot, + pScreenPriv->cursor.sm_cx, + pScreenPriv->cursor.sm_cy, pAnd, pXor); + if (hCursor == NULL) + winW32Error(2, "winLoadCursor - CreateCursor failed:"); + } + free(pAnd); + free(pXor); + + return hCursor; +} + +/* +=========================================================================== + + Pointer sprite functions + +=========================================================================== +*/ + +/* + * winRealizeCursor + * Convert the X cursor representation to native format if possible. + */ +static Bool +winRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + if (pCursor == NULL || pCursor->bits == NULL) + return FALSE; + + /* FIXME: cache ARGB8888 representation? */ + + return TRUE; +} + +/* + * winUnrealizeCursor + * Free the storage space associated with a realized cursor. + */ +static Bool +winUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + return TRUE; +} + +/* + * winSetCursor + * Set the cursor sprite and position. + */ +static void +winSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, + int y) +{ + POINT ptCurPos, ptTemp; + HWND hwnd; + RECT rcClient; + BOOL bInhibit; + + winScreenPriv(pScreen); + WIN_DEBUG_MSG("winSetCursor: cursor=%p\n", pCursor); + + /* Inhibit changing the cursor if the mouse is not in a client area */ + bInhibit = FALSE; + if (GetCursorPos(&ptCurPos)) { + hwnd = WindowFromPoint(ptCurPos); + if (hwnd) { + if (GetClientRect(hwnd, &rcClient)) { + ptTemp.x = rcClient.left; + ptTemp.y = rcClient.top; + if (ClientToScreen(hwnd, &ptTemp)) { + rcClient.left = ptTemp.x; + rcClient.top = ptTemp.y; + ptTemp.x = rcClient.right; + ptTemp.y = rcClient.bottom; + if (ClientToScreen(hwnd, &ptTemp)) { + rcClient.right = ptTemp.x; + rcClient.bottom = ptTemp.y; + if (!PtInRect(&rcClient, ptCurPos)) + bInhibit = TRUE; + } + } + } + } + } + + if (pCursor == NULL) { + if (pScreenPriv->cursor.visible) { + if (!bInhibit && g_fSoftwareCursor) + ShowCursor(FALSE); + pScreenPriv->cursor.visible = FALSE; + } + } + else { + if (pScreenPriv->cursor.handle) { + if (!bInhibit) + SetCursor(NULL); + DestroyCursor(pScreenPriv->cursor.handle); + pScreenPriv->cursor.handle = NULL; + } + pScreenPriv->cursor.handle = + winLoadCursor(pScreen, pCursor, pScreen->myNum); + WIN_DEBUG_MSG("winSetCursor: handle=%p\n", pScreenPriv->cursor.handle); + + if (!bInhibit) + SetCursor(pScreenPriv->cursor.handle); + + if (!pScreenPriv->cursor.visible) { + if (!bInhibit && g_fSoftwareCursor) + ShowCursor(TRUE); + pScreenPriv->cursor.visible = TRUE; + } + } +} + +/* + * winMoveCursor + * Move the cursor. This is a noop for us. + */ +static void +winMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ +} + +static Bool +winDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) +{ + winScreenPriv(pScr); + return pScreenPriv->cursor.spriteFuncs->DeviceCursorInitialize(pDev, pScr); +} + +static void +winDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr) +{ + winScreenPriv(pScr); + pScreenPriv->cursor.spriteFuncs->DeviceCursorCleanup(pDev, pScr); +} + +static miPointerSpriteFuncRec winSpriteFuncsRec = { + winRealizeCursor, + winUnrealizeCursor, + winSetCursor, + winMoveCursor, + winDeviceCursorInitialize, + winDeviceCursorCleanup +}; + +/* +=========================================================================== + + Other screen functions + +=========================================================================== +*/ + +/* + * winCursorQueryBestSize + * Handle queries for best cursor size + */ +static void +winCursorQueryBestSize(int class, unsigned short *width, + unsigned short *height, ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + + if (class == CursorShape) { + *width = pScreenPriv->cursor.sm_cx; + *height = pScreenPriv->cursor.sm_cy; + } + else { + if (pScreenPriv->cursor.QueryBestSize) + (*pScreenPriv->cursor.QueryBestSize) (class, width, height, + pScreen); + } +} + +/* + * winInitCursor + * Initialize cursor support + */ +Bool +winInitCursor(ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + miPointerScreenPtr pPointPriv; + + /* override some screen procedures */ + pScreenPriv->cursor.QueryBestSize = pScreen->QueryBestSize; + pScreen->QueryBestSize = winCursorQueryBestSize; + + pPointPriv = (miPointerScreenPtr) + dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); + + pScreenPriv->cursor.spriteFuncs = pPointPriv->spriteFuncs; + pPointPriv->spriteFuncs = &winSpriteFuncsRec; + + pScreenPriv->cursor.handle = NULL; + pScreenPriv->cursor.visible = FALSE; + + pScreenPriv->cursor.sm_cx = GetSystemMetrics(SM_CXCURSOR); + pScreenPriv->cursor.sm_cy = GetSystemMetrics(SM_CYCURSOR); + + return TRUE; +} -- cgit v1.2.3