diff --git a/hw/xwin/win.h b/hw/xwin/win.h index 74dde725b..f2297188e 100644 --- a/hw/xwin/win.h +++ b/hw/xwin/win.h @@ -348,6 +348,20 @@ typedef struct PALETTEENTRY peColors[WIN_NUM_PALETTE_ENTRIES]; } winPrivCmapRec, *winPrivCmapPtr; +/* + * Windows Cursor handling. + */ + +typedef struct { + /* from GetSystemMetrics */ + int sm_cx; + int sm_cy; + + BOOL visible; + HCURSOR handle; + QueryBestSizeProcPtr QueryBestSize; + miPointerSpriteFuncPtr spriteFuncs; +} winCursorRec; /* * Screen information structure that we need before privates are available @@ -565,6 +579,8 @@ typedef struct _winPrivScreenRec #ifdef SHAPE SetShapeProcPtr SetShape; #endif + + winCursorRec cursor; } winPrivScreenRec; @@ -1399,6 +1415,12 @@ winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg, void winWindowsWMExtensionInit (void); +/* + * wincursor.c + */ + +Bool +winInitCursor (ScreenPtr pScreen); /* * END DDX and DIX Function Prototypes diff --git a/hw/xwin/wincursor.c b/hw/xwin/wincursor.c index c74901a27..6af127b97 100644 --- a/hw/xwin/wincursor.c +++ b/hw/xwin/wincursor.c @@ -33,6 +33,21 @@ /* $XFree86: xc/programs/Xserver/hw/xwin/wincursor.c,v 1.5 2002/07/05 09:19:26 alanh Exp $ */ #include "win.h" +#include "winmsg.h" +#include +#include +#include + +#ifndef MIN +#define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + +#define BYTE_COUNT(x) (((x) + 7) / 8) +#if 1 +# define WIN_DEBUG_MSG winDebug +#else +# define WIN_DEBUG_MSG(...) +#endif /* * Local function prototypes @@ -70,7 +85,7 @@ winPointerWarpCursor (ScreenPtr pScreen, int x, int y) /* Don't ignore subsequent warps */ s_fInitialWarp = FALSE; - ErrorF ("winPointerWarpCursor - Discarding first warp: %d %d\n", + winErrorFVerb (2, "winPointerWarpCursor - Discarding first warp: %d %d\n", x, y); return; @@ -110,3 +125,298 @@ 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; + double dBackY; + BOOL fReverse; + + /* We can use only White and Black, so calc brightness of color */ + dForeY = pCursor->foreRed*0.299 + pCursor->foreGreen*.587 + pCursor->foreBlue*.114; + dBackY = pCursor->backRed*0.299 + pCursor->backGreen*.587 + pCursor->backBlue*.114; + fReverse = dForeY < dBackY; + + if (pScreenPriv->cursor.sm_cx < pCursor->bits->width || + pScreenPriv->cursor.sm_cy < pCursor->bits->height) + { + winErrorFVerb (2, "winLoadCursor - Windows requires %dx%d cursor\n" + "\tbut X requires %dx%d\n", + pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, + pCursor->bits->width, pCursor->bits->height); + } + + /* round up to 8 pixel boundary so we can convert whole bytes */ + nBytes = BYTE_COUNT(pScreenPriv->cursor.sm_cx) * pScreenPriv->cursor.sm_cy; + + nCX = MIN(pScreenPriv->cursor.sm_cx, pCursor->bits->width); + nCY = MIN(pScreenPriv->cursor.sm_cy, pCursor->bits->height); + + WIN_DEBUG_MSG("winLoadCursor: Win32: %dx%d X11: %dx%d\n", + pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, + pCursor->bits->width, pCursor->bits->height); + + pAnd = malloc (nBytes); + memset (pAnd, 0xFF, nBytes); + pXor = malloc (nBytes); + memset (pXor, 0x00, nBytes); + + if (pCursor->bits->emptyMask) + { + int y; + for (y = 0; y < nCY; ++y) + { + int x; + int xmax = BYTE_COUNT(nCX); + for (x = 0; x < xmax; ++x) + { + int nWinPix = BYTE_COUNT(pScreenPriv->cursor.sm_cx) * y + x; + int nXPix = BYTE_COUNT(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 y; + for (y = 0; y < nCY; ++y) + { + int x; + int xmax = BYTE_COUNT(nCX); + for (x = 0; x < xmax; ++x) + { + int nWinPix = BYTE_COUNT(pScreenPriv->cursor.sm_cx) * y + x; + int nXPix = BitmapBytePad(pCursor->bits->width) * y + x; + + pAnd[nWinPix] = reverse (~pCursor->bits->mask[nXPix]); + if (fReverse) + { + pXor[nWinPix] = reverse (~pCursor->bits->source[nXPix] & pCursor->bits->mask[nXPix]); + } + else + { + pXor[nWinPix] = reverse (pCursor->bits->source[nXPix] & pCursor->bits->mask[nXPix]); + } + } + } + } + + hCursor = CreateCursor (g_hInstance, + pCursor->bits->xhot, pCursor->bits->yhot, + pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, + pAnd, pXor); + + free (pAnd); + free (pXor); + + if (hCursor == NULL) + { + LPVOID lpMsgBuf; + + /* Display a fancy error message */ + FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError (), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL); + + winErrorFVerb (2, "winLoadCursor - CreateCursor failed\n" + "\t%s\n", (LPSTR)lpMsgBuf); + LocalFree (lpMsgBuf); + } + return hCursor; +} + +/* +=========================================================================== + + Pointer sprite functions + +=========================================================================== +*/ + +/* + * winMWExtWMRealizeCursor + * Convert the X cursor representation to native format if possible. + */ +static Bool +winRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + WIN_DEBUG_MSG("winRealizeCursor: cursor=%p\n", pCursor); + + if(pCursor == NULL || pCursor->bits == NULL) + return FALSE; + + /* FIXME: cache ARGB8888 representation? */ + + return TRUE; +} + + +/* + * winMWExtWMUnrealizeCursor + * Free the storage space associated with a realized cursor. + */ +static Bool +winUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + WIN_DEBUG_MSG("winUnrealizeCursor: cursor=%p\n", pCursor); + return TRUE; +} + + +/* + * winMWExtWMSetCursor + * Set the cursor sprite and position. + */ +static void +winSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + winScreenPriv(pScreen); + WIN_DEBUG_MSG("winSetCursor: cursor=%p\n", pCursor); + + if (pCursor == NULL) + { + if (pScreenPriv->cursor.visible) + { + ShowCursor (FALSE); + pScreenPriv->cursor.visible = FALSE; + } + } + else + { + if (pScreenPriv->cursor.handle) + { + 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); + SetCursor (pScreenPriv->cursor.handle); + + if (!pScreenPriv->cursor.visible) + { + ShowCursor (TRUE); + pScreenPriv->cursor.visible = TRUE; + } + } +} + + +/* + * winMWExtWMReallySetCursor + * Not needed for xpr. Cursor is set from the X server thread. + */ +void +winReallySetCursor () +{ +} + + +/* + * QuartzMoveCursor + * Move the cursor. This is a noop for us. + */ +static void +winMoveCursor (ScreenPtr pScreen, int x, int y) +{ +} + + +static miPointerSpriteFuncRec winSpriteFuncsRec = { + winRealizeCursor, + winUnrealizeCursor, + winSetCursor, + winMoveCursor +}; + + +/* +=========================================================================== + + Other screen functions + +=========================================================================== +*/ + +/* + * winMWExtWMCursorQueryBestSize + * 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) pScreen->devPrivates[miPointerScreenIndex].ptr; + + 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; +}