mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-01-29 10:00:26 +01:00
Enable hardware (==windows) cursor for all display modes
This commit is contained in:
parent
01bdcc8530
commit
e6bbc8bcc4
2 changed files with 333 additions and 1 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue