Enable hardware (==windows) cursor for all display modes

This commit is contained in:
Alexander Gottwald 2004-04-22 20:08:40 +00:00
parent 01bdcc8530
commit e6bbc8bcc4
2 changed files with 333 additions and 1 deletions

View file

@ -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

View file

@ -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 <cursorstr.h>
#include <mipointrst.h>
#include <servermd.h>
#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;
}