105b261ecSmrg/* 205b261ecSmrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 305b261ecSmrg * 405b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining 505b261ecSmrg * a copy of this software and associated documentation files (the 605b261ecSmrg *"Software"), to deal in the Software without restriction, including 705b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish, 805b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to 905b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to 1005b261ecSmrg *the following conditions: 1105b261ecSmrg * 1205b261ecSmrg *The above copyright notice and this permission notice shall be 1305b261ecSmrg *included in all copies or substantial portions of the Software. 1405b261ecSmrg * 1505b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1605b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1705b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1805b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 1905b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 2005b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2105b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2205b261ecSmrg * 2305b261ecSmrg *Except as contained in this notice, the name of the XFree86 Project 2405b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use 2505b261ecSmrg *or other dealings in this Software without prior written authorization 2605b261ecSmrg *from the XFree86 Project. 2705b261ecSmrg * 2805b261ecSmrg * Authors: Dakshinamurthy Karra 2905b261ecSmrg * Suhaib M Siddiqi 3005b261ecSmrg * Peter Busch 3105b261ecSmrg * Harold L Hunt II 3205b261ecSmrg */ 3305b261ecSmrg 3405b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H 3505b261ecSmrg#include <xwin-config.h> 3605b261ecSmrg#endif 3705b261ecSmrg#include "win.h" 3805b261ecSmrg#include "winmsg.h" 3905b261ecSmrg#include <cursorstr.h> 4005b261ecSmrg#include <mipointrst.h> 4105b261ecSmrg#include <servermd.h> 426747b715Smrg#include "misc.h" 4305b261ecSmrg 4405b261ecSmrg#define BRIGHTNESS(x) (x##Red * 0.299 + x##Green * 0.587 + x##Blue * 0.114) 4505b261ecSmrg 4605b261ecSmrg#if 0 4735c4bbdfSmrg#define WIN_DEBUG_MSG winDebug 4805b261ecSmrg#else 4935c4bbdfSmrg#define WIN_DEBUG_MSG(...) 5005b261ecSmrg#endif 5105b261ecSmrg 5205b261ecSmrg/* 5305b261ecSmrg * Local function prototypes 5405b261ecSmrg */ 5505b261ecSmrg 5605b261ecSmrgstatic void 5735c4bbdfSmrg winPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); 5805b261ecSmrg 5905b261ecSmrgstatic Bool 6035c4bbdfSmrg winCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y); 6105b261ecSmrg 6205b261ecSmrgstatic void 6335c4bbdfSmrg winCrossScreen(ScreenPtr pScreen, Bool fEntering); 6405b261ecSmrg 6535c4bbdfSmrgmiPointerScreenFuncRec g_winPointerCursorFuncs = { 6635c4bbdfSmrg winCursorOffScreen, 6735c4bbdfSmrg winCrossScreen, 6835c4bbdfSmrg winPointerWarpCursor 6905b261ecSmrg}; 7005b261ecSmrg 7105b261ecSmrgstatic void 7235c4bbdfSmrgwinPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 7305b261ecSmrg{ 7435c4bbdfSmrg winScreenPriv(pScreen); 7535c4bbdfSmrg RECT rcClient; 7635c4bbdfSmrg static Bool s_fInitialWarp = TRUE; 7735c4bbdfSmrg 7835c4bbdfSmrg /* Discard first warp call */ 7935c4bbdfSmrg if (s_fInitialWarp) { 8035c4bbdfSmrg /* First warp moves mouse to center of window, just ignore it */ 8135c4bbdfSmrg 8235c4bbdfSmrg /* Don't ignore subsequent warps */ 8335c4bbdfSmrg s_fInitialWarp = FALSE; 8435c4bbdfSmrg 8535c4bbdfSmrg winErrorFVerb(2, 8635c4bbdfSmrg "winPointerWarpCursor - Discarding first warp: %d %d\n", 8735c4bbdfSmrg x, y); 8835c4bbdfSmrg 8935c4bbdfSmrg return; 9005b261ecSmrg } 9105b261ecSmrg 9235c4bbdfSmrg /* 9335c4bbdfSmrg Only update the Windows cursor position if root window is active, 9435c4bbdfSmrg or we are in a rootless mode 9535c4bbdfSmrg */ 9635c4bbdfSmrg if ((pScreenPriv->hwndScreen == GetForegroundWindow()) 9735c4bbdfSmrg || pScreenPriv->pScreenInfo->fRootless 9835c4bbdfSmrg || pScreenPriv->pScreenInfo->fMultiWindow 9935c4bbdfSmrg ) { 10035c4bbdfSmrg /* Get the client area coordinates */ 10135c4bbdfSmrg GetClientRect(pScreenPriv->hwndScreen, &rcClient); 10235c4bbdfSmrg 10335c4bbdfSmrg /* Translate the client area coords to screen coords */ 10435c4bbdfSmrg MapWindowPoints(pScreenPriv->hwndScreen, 10535c4bbdfSmrg HWND_DESKTOP, (LPPOINT) &rcClient, 2); 10635c4bbdfSmrg 10735c4bbdfSmrg /* 10835c4bbdfSmrg * Update the Windows cursor position so that we don't 10935c4bbdfSmrg * immediately warp back to the current position. 11035c4bbdfSmrg */ 11135c4bbdfSmrg SetCursorPos(rcClient.left + x, rcClient.top + y); 11205b261ecSmrg } 11305b261ecSmrg 11435c4bbdfSmrg /* Call the mi warp procedure to do the actual warping in X. */ 11535c4bbdfSmrg miPointerWarpCursor(pDev, pScreen, x, y); 11605b261ecSmrg} 11705b261ecSmrg 11805b261ecSmrgstatic Bool 11935c4bbdfSmrgwinCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) 12005b261ecSmrg{ 12135c4bbdfSmrg return FALSE; 12205b261ecSmrg} 12305b261ecSmrg 12405b261ecSmrgstatic void 12535c4bbdfSmrgwinCrossScreen(ScreenPtr pScreen, Bool fEntering) 12605b261ecSmrg{ 12705b261ecSmrg} 12805b261ecSmrg 12905b261ecSmrgstatic unsigned char 13005b261ecSmrgreverse(unsigned char c) 13105b261ecSmrg{ 13235c4bbdfSmrg int i; 13335c4bbdfSmrg unsigned char ret = 0; 13435c4bbdfSmrg 13535c4bbdfSmrg for (i = 0; i < 8; ++i) { 13635c4bbdfSmrg ret |= ((c >> i) & 1) << (7 - i); 13705b261ecSmrg } 13835c4bbdfSmrg return ret; 13905b261ecSmrg} 14005b261ecSmrg 14105b261ecSmrg/* 14205b261ecSmrg * Convert X cursor to Windows cursor 14305b261ecSmrg * FIXME: Perhaps there are more smart code 14405b261ecSmrg */ 14505b261ecSmrgstatic HCURSOR 14635c4bbdfSmrgwinLoadCursor(ScreenPtr pScreen, CursorPtr pCursor, int screen) 14705b261ecSmrg{ 14835c4bbdfSmrg winScreenPriv(pScreen); 14935c4bbdfSmrg HCURSOR hCursor = NULL; 15035c4bbdfSmrg unsigned char *pAnd; 15135c4bbdfSmrg unsigned char *pXor; 15235c4bbdfSmrg int nCX, nCY; 15335c4bbdfSmrg int nBytes; 15435c4bbdfSmrg double dForeY, dBackY; 15535c4bbdfSmrg BOOL fReverse; 15635c4bbdfSmrg HBITMAP hAnd, hXor; 15735c4bbdfSmrg ICONINFO ii; 15835c4bbdfSmrg unsigned char *pCur; 15935c4bbdfSmrg unsigned char bit; 16035c4bbdfSmrg HDC hDC; 16135c4bbdfSmrg BITMAPV4HEADER bi; 16235c4bbdfSmrg BITMAPINFO *pbmi; 16335c4bbdfSmrg uint32_t *lpBits; 16435c4bbdfSmrg 16535c4bbdfSmrg WIN_DEBUG_MSG("winLoadCursor: Win32: %dx%d X11: %dx%d hotspot: %d,%d\n", 16635c4bbdfSmrg pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, 16735c4bbdfSmrg pCursor->bits->width, pCursor->bits->height, 16835c4bbdfSmrg pCursor->bits->xhot, pCursor->bits->yhot); 16935c4bbdfSmrg 17035c4bbdfSmrg /* We can use only White and Black, so calc brightness of color 17135c4bbdfSmrg * Also check if the cursor is inverted */ 17235c4bbdfSmrg dForeY = BRIGHTNESS(pCursor->fore); 17335c4bbdfSmrg dBackY = BRIGHTNESS(pCursor->back); 17435c4bbdfSmrg fReverse = dForeY < dBackY; 17535c4bbdfSmrg 176ed6184dfSmrg /* Check whether the X11 cursor is bigger than the win32 cursor */ 17735c4bbdfSmrg if (pScreenPriv->cursor.sm_cx < pCursor->bits->width || 17835c4bbdfSmrg pScreenPriv->cursor.sm_cy < pCursor->bits->height) { 17935c4bbdfSmrg winErrorFVerb(3, 18035c4bbdfSmrg "winLoadCursor - Windows requires %dx%d cursor but X requires %dx%d\n", 18135c4bbdfSmrg pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, 18235c4bbdfSmrg pCursor->bits->width, pCursor->bits->height); 18305b261ecSmrg } 18405b261ecSmrg 18535c4bbdfSmrg /* Get the number of bytes required to store the whole cursor image 18635c4bbdfSmrg * This is roughly (sm_cx * sm_cy) / 8 18735c4bbdfSmrg * round up to 8 pixel boundary so we can convert whole bytes */ 18835c4bbdfSmrg nBytes = 18935c4bbdfSmrg bits_to_bytes(pScreenPriv->cursor.sm_cx) * pScreenPriv->cursor.sm_cy; 19035c4bbdfSmrg 19135c4bbdfSmrg /* Get the effective width and height */ 19235c4bbdfSmrg nCX = min(pScreenPriv->cursor.sm_cx, pCursor->bits->width); 19335c4bbdfSmrg nCY = min(pScreenPriv->cursor.sm_cy, pCursor->bits->height); 19435c4bbdfSmrg 19535c4bbdfSmrg /* Allocate memory for the bitmaps */ 19635c4bbdfSmrg pAnd = malloc(nBytes); 19735c4bbdfSmrg memset(pAnd, 0xFF, nBytes); 19835c4bbdfSmrg pXor = calloc(1, nBytes); 19935c4bbdfSmrg 20035c4bbdfSmrg /* Convert the X11 bitmap to a win32 bitmap 20135c4bbdfSmrg * The first is for an empty mask */ 20235c4bbdfSmrg if (pCursor->bits->emptyMask) { 20335c4bbdfSmrg int x, y, xmax = bits_to_bytes(nCX); 20435c4bbdfSmrg 20535c4bbdfSmrg for (y = 0; y < nCY; ++y) 20635c4bbdfSmrg for (x = 0; x < xmax; ++x) { 20735c4bbdfSmrg int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x; 20835c4bbdfSmrg int nXPix = BitmapBytePad(pCursor->bits->width) * y + x; 20935c4bbdfSmrg 21035c4bbdfSmrg pAnd[nWinPix] = 0; 21135c4bbdfSmrg if (fReverse) 21235c4bbdfSmrg pXor[nWinPix] = reverse(~pCursor->bits->source[nXPix]); 21335c4bbdfSmrg else 21435c4bbdfSmrg pXor[nWinPix] = reverse(pCursor->bits->source[nXPix]); 21535c4bbdfSmrg } 21605b261ecSmrg } 21735c4bbdfSmrg else { 21835c4bbdfSmrg int x, y, xmax = bits_to_bytes(nCX); 21935c4bbdfSmrg 22035c4bbdfSmrg for (y = 0; y < nCY; ++y) 22135c4bbdfSmrg for (x = 0; x < xmax; ++x) { 22235c4bbdfSmrg int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x; 22335c4bbdfSmrg int nXPix = BitmapBytePad(pCursor->bits->width) * y + x; 22435c4bbdfSmrg 22535c4bbdfSmrg unsigned char mask = pCursor->bits->mask[nXPix]; 22635c4bbdfSmrg 22735c4bbdfSmrg pAnd[nWinPix] = reverse(~mask); 22835c4bbdfSmrg if (fReverse) 22935c4bbdfSmrg pXor[nWinPix] = 23035c4bbdfSmrg reverse(~pCursor->bits->source[nXPix] & mask); 23135c4bbdfSmrg else 23235c4bbdfSmrg pXor[nWinPix] = 23335c4bbdfSmrg reverse(pCursor->bits->source[nXPix] & mask); 23435c4bbdfSmrg } 23505b261ecSmrg } 23605b261ecSmrg 23735c4bbdfSmrg /* prepare the pointers */ 23835c4bbdfSmrg hCursor = NULL; 23935c4bbdfSmrg lpBits = NULL; 24035c4bbdfSmrg 24135c4bbdfSmrg /* We have a truecolor alpha-blended cursor and can use it! */ 24235c4bbdfSmrg if (pCursor->bits->argb) { 24335c4bbdfSmrg WIN_DEBUG_MSG("winLoadCursor: Trying truecolor alphablended cursor\n"); 24435c4bbdfSmrg memset(&bi, 0, sizeof(BITMAPV4HEADER)); 24535c4bbdfSmrg bi.bV4Size = sizeof(BITMAPV4HEADER); 24635c4bbdfSmrg bi.bV4Width = pScreenPriv->cursor.sm_cx; 24735c4bbdfSmrg bi.bV4Height = -(pScreenPriv->cursor.sm_cy); /* right-side up */ 24835c4bbdfSmrg bi.bV4Planes = 1; 24935c4bbdfSmrg bi.bV4BitCount = 32; 25035c4bbdfSmrg bi.bV4V4Compression = BI_BITFIELDS; 25135c4bbdfSmrg bi.bV4RedMask = 0x00FF0000; 25235c4bbdfSmrg bi.bV4GreenMask = 0x0000FF00; 25335c4bbdfSmrg bi.bV4BlueMask = 0x000000FF; 25435c4bbdfSmrg bi.bV4AlphaMask = 0xFF000000; 25535c4bbdfSmrg 25635c4bbdfSmrg lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy, 25735c4bbdfSmrg sizeof(uint32_t)); 25835c4bbdfSmrg 25935c4bbdfSmrg if (lpBits) { 26035c4bbdfSmrg int y; 26135c4bbdfSmrg for (y = 0; y < nCY; y++) { 26235c4bbdfSmrg void *src, *dst; 26335c4bbdfSmrg src = &(pCursor->bits->argb[y * pCursor->bits->width]); 26435c4bbdfSmrg dst = &(lpBits[y * pScreenPriv->cursor.sm_cx]); 26535c4bbdfSmrg memcpy(dst, src, 4 * nCX); 26635c4bbdfSmrg } 26735c4bbdfSmrg } 26835c4bbdfSmrg } /* End if-truecolor-icon */ 26935c4bbdfSmrg 27035c4bbdfSmrg if (!lpBits) { 27135c4bbdfSmrg RGBQUAD *pbmiColors; 27235c4bbdfSmrg /* Bicolor, use a palettized DIB */ 27335c4bbdfSmrg WIN_DEBUG_MSG("winLoadCursor: Trying two color cursor\n"); 27435c4bbdfSmrg pbmi = (BITMAPINFO *) &bi; 27535c4bbdfSmrg pbmiColors = &(pbmi->bmiColors[0]); 27635c4bbdfSmrg 27735c4bbdfSmrg memset(pbmi, 0, sizeof(BITMAPINFOHEADER)); 27835c4bbdfSmrg pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 27935c4bbdfSmrg pbmi->bmiHeader.biWidth = pScreenPriv->cursor.sm_cx; 28035c4bbdfSmrg pbmi->bmiHeader.biHeight = -abs(pScreenPriv->cursor.sm_cy); /* right-side up */ 28135c4bbdfSmrg pbmi->bmiHeader.biPlanes = 1; 28235c4bbdfSmrg pbmi->bmiHeader.biBitCount = 8; 28335c4bbdfSmrg pbmi->bmiHeader.biCompression = BI_RGB; 28435c4bbdfSmrg pbmi->bmiHeader.biSizeImage = 0; 28535c4bbdfSmrg pbmi->bmiHeader.biClrUsed = 3; 28635c4bbdfSmrg pbmi->bmiHeader.biClrImportant = 3; 28735c4bbdfSmrg 28835c4bbdfSmrg pbmiColors[0].rgbRed = 0; /* Empty */ 28935c4bbdfSmrg pbmiColors[0].rgbGreen = 0; 29035c4bbdfSmrg pbmiColors[0].rgbBlue = 0; 29135c4bbdfSmrg pbmiColors[0].rgbReserved = 0; 29235c4bbdfSmrg pbmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */ 29335c4bbdfSmrg pbmiColors[1].rgbGreen = pCursor->backGreen >> 8; 29435c4bbdfSmrg pbmiColors[1].rgbBlue = pCursor->backBlue >> 8; 29535c4bbdfSmrg pbmiColors[1].rgbReserved = 0; 29635c4bbdfSmrg pbmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */ 29735c4bbdfSmrg pbmiColors[2].rgbGreen = pCursor->foreGreen >> 8; 29835c4bbdfSmrg pbmiColors[2].rgbBlue = pCursor->foreBlue >> 8; 29935c4bbdfSmrg pbmiColors[2].rgbReserved = 0; 30035c4bbdfSmrg 30135c4bbdfSmrg lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy, 1); 30235c4bbdfSmrg 30335c4bbdfSmrg pCur = (unsigned char *) lpBits; 30435c4bbdfSmrg if (lpBits) { 30535c4bbdfSmrg int x, y; 30635c4bbdfSmrg for (y = 0; y < pScreenPriv->cursor.sm_cy; y++) { 30735c4bbdfSmrg for (x = 0; x < pScreenPriv->cursor.sm_cx; x++) { 30835c4bbdfSmrg if (x >= nCX || y >= nCY) /* Outside of X11 icon bounds */ 30935c4bbdfSmrg (*pCur++) = 0; 31035c4bbdfSmrg else { /* Within X11 icon bounds */ 31135c4bbdfSmrg 31235c4bbdfSmrg int nWinPix = 31335c4bbdfSmrg bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + 31435c4bbdfSmrg (x / 8); 31535c4bbdfSmrg 31635c4bbdfSmrg bit = pAnd[nWinPix]; 31735c4bbdfSmrg bit = bit & (1 << (7 - (x & 7))); 31835c4bbdfSmrg if (!bit) { /* Within the cursor mask? */ 31935c4bbdfSmrg int nXPix = 32035c4bbdfSmrg BitmapBytePad(pCursor->bits->width) * y + 32135c4bbdfSmrg (x / 8); 32235c4bbdfSmrg bit = 32335c4bbdfSmrg ~reverse(~pCursor->bits-> 32435c4bbdfSmrg source[nXPix] & pCursor->bits-> 32535c4bbdfSmrg mask[nXPix]); 32635c4bbdfSmrg bit = bit & (1 << (7 - (x & 7))); 32735c4bbdfSmrg if (bit) /* Draw foreground */ 32835c4bbdfSmrg (*pCur++) = 2; 32935c4bbdfSmrg else /* Draw background */ 33035c4bbdfSmrg (*pCur++) = 1; 33135c4bbdfSmrg } 33235c4bbdfSmrg else /* Outside the cursor mask */ 33335c4bbdfSmrg (*pCur++) = 0; 33435c4bbdfSmrg } 33535c4bbdfSmrg } /* end for (x) */ 33635c4bbdfSmrg } /* end for (y) */ 33735c4bbdfSmrg } /* end if (lpbits) */ 33805b261ecSmrg } 33905b261ecSmrg 34035c4bbdfSmrg /* If one of the previous two methods gave us the bitmap we need, make a cursor */ 34135c4bbdfSmrg if (lpBits) { 34235c4bbdfSmrg WIN_DEBUG_MSG("winLoadCursor: Creating bitmap cursor: hotspot %d,%d\n", 34335c4bbdfSmrg pCursor->bits->xhot, pCursor->bits->yhot); 34435c4bbdfSmrg 34535c4bbdfSmrg hAnd = NULL; 34635c4bbdfSmrg hXor = NULL; 34735c4bbdfSmrg 34835c4bbdfSmrg hAnd = 34935c4bbdfSmrg CreateBitmap(pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, 35035c4bbdfSmrg 1, 1, pAnd); 35135c4bbdfSmrg 35235c4bbdfSmrg hDC = GetDC(NULL); 35335c4bbdfSmrg if (hDC) { 35435c4bbdfSmrg hXor = 35535c4bbdfSmrg CreateCompatibleBitmap(hDC, pScreenPriv->cursor.sm_cx, 35635c4bbdfSmrg pScreenPriv->cursor.sm_cy); 35735c4bbdfSmrg SetDIBits(hDC, hXor, 0, pScreenPriv->cursor.sm_cy, lpBits, 35835c4bbdfSmrg (BITMAPINFO *) &bi, DIB_RGB_COLORS); 35935c4bbdfSmrg ReleaseDC(NULL, hDC); 36035c4bbdfSmrg } 36135c4bbdfSmrg free(lpBits); 36235c4bbdfSmrg 36335c4bbdfSmrg if (hAnd && hXor) { 36435c4bbdfSmrg ii.fIcon = FALSE; 36535c4bbdfSmrg ii.xHotspot = pCursor->bits->xhot; 36635c4bbdfSmrg ii.yHotspot = pCursor->bits->yhot; 36735c4bbdfSmrg ii.hbmMask = hAnd; 36835c4bbdfSmrg ii.hbmColor = hXor; 36935c4bbdfSmrg hCursor = (HCURSOR) CreateIconIndirect(&ii); 37035c4bbdfSmrg 37135c4bbdfSmrg if (hCursor == NULL) 37235c4bbdfSmrg winW32Error(2, "winLoadCursor - CreateIconIndirect failed:"); 37335c4bbdfSmrg else { 37435c4bbdfSmrg if (GetIconInfo(hCursor, &ii)) { 37535c4bbdfSmrg if (ii.fIcon) { 37635c4bbdfSmrg WIN_DEBUG_MSG 37735c4bbdfSmrg ("winLoadCursor: CreateIconIndirect returned no cursor. Trying again.\n"); 37835c4bbdfSmrg 37935c4bbdfSmrg DestroyCursor(hCursor); 38035c4bbdfSmrg 38135c4bbdfSmrg ii.fIcon = FALSE; 38235c4bbdfSmrg ii.xHotspot = pCursor->bits->xhot; 38335c4bbdfSmrg ii.yHotspot = pCursor->bits->yhot; 38435c4bbdfSmrg hCursor = (HCURSOR) CreateIconIndirect(&ii); 38535c4bbdfSmrg 38635c4bbdfSmrg if (hCursor == NULL) 38735c4bbdfSmrg winW32Error(2, 38835c4bbdfSmrg "winLoadCursor - CreateIconIndirect failed:"); 38935c4bbdfSmrg } 39035c4bbdfSmrg /* GetIconInfo creates new bitmaps. Destroy them again */ 39135c4bbdfSmrg if (ii.hbmMask) 39235c4bbdfSmrg DeleteObject(ii.hbmMask); 39335c4bbdfSmrg if (ii.hbmColor) 39435c4bbdfSmrg DeleteObject(ii.hbmColor); 39535c4bbdfSmrg } 39635c4bbdfSmrg } 39735c4bbdfSmrg } 39835c4bbdfSmrg 39935c4bbdfSmrg if (hAnd) 40035c4bbdfSmrg DeleteObject(hAnd); 40135c4bbdfSmrg if (hXor) 40235c4bbdfSmrg DeleteObject(hXor); 40305b261ecSmrg } 40405b261ecSmrg 40535c4bbdfSmrg if (!hCursor) { 40635c4bbdfSmrg /* We couldn't make a color cursor for this screen, use 40735c4bbdfSmrg black and white instead */ 40835c4bbdfSmrg hCursor = CreateCursor(g_hInstance, 40935c4bbdfSmrg pCursor->bits->xhot, pCursor->bits->yhot, 41035c4bbdfSmrg pScreenPriv->cursor.sm_cx, 41135c4bbdfSmrg pScreenPriv->cursor.sm_cy, pAnd, pXor); 41235c4bbdfSmrg if (hCursor == NULL) 41335c4bbdfSmrg winW32Error(2, "winLoadCursor - CreateCursor failed:"); 41405b261ecSmrg } 41535c4bbdfSmrg free(pAnd); 41635c4bbdfSmrg free(pXor); 41705b261ecSmrg 41835c4bbdfSmrg return hCursor; 41905b261ecSmrg} 42005b261ecSmrg 42105b261ecSmrg/* 42205b261ecSmrg=========================================================================== 42305b261ecSmrg 42405b261ecSmrg Pointer sprite functions 42505b261ecSmrg 42605b261ecSmrg=========================================================================== 42705b261ecSmrg*/ 42805b261ecSmrg 42905b261ecSmrg/* 43005b261ecSmrg * winRealizeCursor 43105b261ecSmrg * Convert the X cursor representation to native format if possible. 43205b261ecSmrg */ 43305b261ecSmrgstatic Bool 43435c4bbdfSmrgwinRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 43505b261ecSmrg{ 43635c4bbdfSmrg if (pCursor == NULL || pCursor->bits == NULL) 43735c4bbdfSmrg return FALSE; 43805b261ecSmrg 43935c4bbdfSmrg /* FIXME: cache ARGB8888 representation? */ 44005b261ecSmrg 44135c4bbdfSmrg return TRUE; 44235c4bbdfSmrg} 44305b261ecSmrg 44405b261ecSmrg/* 44505b261ecSmrg * winUnrealizeCursor 44605b261ecSmrg * Free the storage space associated with a realized cursor. 44705b261ecSmrg */ 44805b261ecSmrgstatic Bool 4496747b715SmrgwinUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 45005b261ecSmrg{ 45135c4bbdfSmrg return TRUE; 45205b261ecSmrg} 45305b261ecSmrg 45405b261ecSmrg/* 45505b261ecSmrg * winSetCursor 45605b261ecSmrg * Set the cursor sprite and position. 45705b261ecSmrg */ 45805b261ecSmrgstatic void 45935c4bbdfSmrgwinSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, 46035c4bbdfSmrg int y) 46105b261ecSmrg{ 46235c4bbdfSmrg POINT ptCurPos, ptTemp; 46335c4bbdfSmrg HWND hwnd; 46435c4bbdfSmrg RECT rcClient; 46535c4bbdfSmrg BOOL bInhibit; 46635c4bbdfSmrg 46735c4bbdfSmrg winScreenPriv(pScreen); 46835c4bbdfSmrg WIN_DEBUG_MSG("winSetCursor: cursor=%p\n", pCursor); 46935c4bbdfSmrg 47035c4bbdfSmrg /* Inhibit changing the cursor if the mouse is not in a client area */ 47135c4bbdfSmrg bInhibit = FALSE; 47235c4bbdfSmrg if (GetCursorPos(&ptCurPos)) { 47335c4bbdfSmrg hwnd = WindowFromPoint(ptCurPos); 47435c4bbdfSmrg if (hwnd) { 47535c4bbdfSmrg if (GetClientRect(hwnd, &rcClient)) { 47635c4bbdfSmrg ptTemp.x = rcClient.left; 47735c4bbdfSmrg ptTemp.y = rcClient.top; 47835c4bbdfSmrg if (ClientToScreen(hwnd, &ptTemp)) { 47935c4bbdfSmrg rcClient.left = ptTemp.x; 48035c4bbdfSmrg rcClient.top = ptTemp.y; 48135c4bbdfSmrg ptTemp.x = rcClient.right; 48235c4bbdfSmrg ptTemp.y = rcClient.bottom; 48335c4bbdfSmrg if (ClientToScreen(hwnd, &ptTemp)) { 48435c4bbdfSmrg rcClient.right = ptTemp.x; 48535c4bbdfSmrg rcClient.bottom = ptTemp.y; 48635c4bbdfSmrg if (!PtInRect(&rcClient, ptCurPos)) 48735c4bbdfSmrg bInhibit = TRUE; 48835c4bbdfSmrg } 48935c4bbdfSmrg } 49035c4bbdfSmrg } 49135c4bbdfSmrg } 49205b261ecSmrg } 49305b261ecSmrg 49435c4bbdfSmrg if (pCursor == NULL) { 49535c4bbdfSmrg if (pScreenPriv->cursor.visible) { 49635c4bbdfSmrg if (!bInhibit && g_fSoftwareCursor) 49735c4bbdfSmrg ShowCursor(FALSE); 49835c4bbdfSmrg pScreenPriv->cursor.visible = FALSE; 49935c4bbdfSmrg } 50005b261ecSmrg } 50135c4bbdfSmrg else { 50235c4bbdfSmrg if (pScreenPriv->cursor.handle) { 50335c4bbdfSmrg if (!bInhibit) 50435c4bbdfSmrg SetCursor(NULL); 50535c4bbdfSmrg DestroyCursor(pScreenPriv->cursor.handle); 50635c4bbdfSmrg pScreenPriv->cursor.handle = NULL; 50735c4bbdfSmrg } 50835c4bbdfSmrg pScreenPriv->cursor.handle = 50935c4bbdfSmrg winLoadCursor(pScreen, pCursor, pScreen->myNum); 51035c4bbdfSmrg WIN_DEBUG_MSG("winSetCursor: handle=%p\n", pScreenPriv->cursor.handle); 51135c4bbdfSmrg 51235c4bbdfSmrg if (!bInhibit) 51335c4bbdfSmrg SetCursor(pScreenPriv->cursor.handle); 51435c4bbdfSmrg 51535c4bbdfSmrg if (!pScreenPriv->cursor.visible) { 51635c4bbdfSmrg if (!bInhibit && g_fSoftwareCursor) 51735c4bbdfSmrg ShowCursor(TRUE); 51835c4bbdfSmrg pScreenPriv->cursor.visible = TRUE; 51935c4bbdfSmrg } 52005b261ecSmrg } 52105b261ecSmrg} 52205b261ecSmrg 52305b261ecSmrg/* 5246747b715Smrg * winMoveCursor 52505b261ecSmrg * Move the cursor. This is a noop for us. 52605b261ecSmrg */ 52705b261ecSmrgstatic void 52835c4bbdfSmrgwinMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 5296747b715Smrg{ 5306747b715Smrg} 5316747b715Smrg 5326747b715Smrgstatic Bool 5336747b715SmrgwinDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) 53405b261ecSmrg{ 53535c4bbdfSmrg winScreenPriv(pScr); 53635c4bbdfSmrg return pScreenPriv->cursor.spriteFuncs->DeviceCursorInitialize(pDev, pScr); 53705b261ecSmrg} 53805b261ecSmrg 5396747b715Smrgstatic void 5406747b715SmrgwinDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr) 5416747b715Smrg{ 54235c4bbdfSmrg winScreenPriv(pScr); 54335c4bbdfSmrg pScreenPriv->cursor.spriteFuncs->DeviceCursorCleanup(pDev, pScr); 5446747b715Smrg} 54505b261ecSmrg 54605b261ecSmrgstatic miPointerSpriteFuncRec winSpriteFuncsRec = { 54735c4bbdfSmrg winRealizeCursor, 54835c4bbdfSmrg winUnrealizeCursor, 54935c4bbdfSmrg winSetCursor, 55035c4bbdfSmrg winMoveCursor, 55135c4bbdfSmrg winDeviceCursorInitialize, 55235c4bbdfSmrg winDeviceCursorCleanup 55305b261ecSmrg}; 55405b261ecSmrg 55505b261ecSmrg/* 55605b261ecSmrg=========================================================================== 55705b261ecSmrg 55805b261ecSmrg Other screen functions 55905b261ecSmrg 56005b261ecSmrg=========================================================================== 56105b261ecSmrg*/ 56205b261ecSmrg 56305b261ecSmrg/* 56405b261ecSmrg * winCursorQueryBestSize 56505b261ecSmrg * Handle queries for best cursor size 56605b261ecSmrg */ 56705b261ecSmrgstatic void 56835c4bbdfSmrgwinCursorQueryBestSize(int class, unsigned short *width, 56935c4bbdfSmrg unsigned short *height, ScreenPtr pScreen) 57005b261ecSmrg{ 57135c4bbdfSmrg winScreenPriv(pScreen); 57235c4bbdfSmrg 57335c4bbdfSmrg if (class == CursorShape) { 57435c4bbdfSmrg *width = pScreenPriv->cursor.sm_cx; 57535c4bbdfSmrg *height = pScreenPriv->cursor.sm_cy; 57605b261ecSmrg } 57735c4bbdfSmrg else { 57835c4bbdfSmrg if (pScreenPriv->cursor.QueryBestSize) 57935c4bbdfSmrg (*pScreenPriv->cursor.QueryBestSize) (class, width, height, 58035c4bbdfSmrg pScreen); 58105b261ecSmrg } 58205b261ecSmrg} 58305b261ecSmrg 58405b261ecSmrg/* 58505b261ecSmrg * winInitCursor 58605b261ecSmrg * Initialize cursor support 58705b261ecSmrg */ 58805b261ecSmrgBool 58935c4bbdfSmrgwinInitCursor(ScreenPtr pScreen) 59005b261ecSmrg{ 59135c4bbdfSmrg winScreenPriv(pScreen); 59235c4bbdfSmrg miPointerScreenPtr pPointPriv; 59335c4bbdfSmrg 59435c4bbdfSmrg /* override some screen procedures */ 59535c4bbdfSmrg pScreenPriv->cursor.QueryBestSize = pScreen->QueryBestSize; 59635c4bbdfSmrg pScreen->QueryBestSize = winCursorQueryBestSize; 59735c4bbdfSmrg 59835c4bbdfSmrg pPointPriv = (miPointerScreenPtr) 59935c4bbdfSmrg dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 60035c4bbdfSmrg 60135c4bbdfSmrg pScreenPriv->cursor.spriteFuncs = pPointPriv->spriteFuncs; 60235c4bbdfSmrg pPointPriv->spriteFuncs = &winSpriteFuncsRec; 60335c4bbdfSmrg 60435c4bbdfSmrg pScreenPriv->cursor.handle = NULL; 60535c4bbdfSmrg pScreenPriv->cursor.visible = FALSE; 60635c4bbdfSmrg 60735c4bbdfSmrg pScreenPriv->cursor.sm_cx = GetSystemMetrics(SM_CXCURSOR); 60835c4bbdfSmrg pScreenPriv->cursor.sm_cy = GetSystemMetrics(SM_CYCURSOR); 60935c4bbdfSmrg 61035c4bbdfSmrg return TRUE; 61105b261ecSmrg} 612