xserver/hw/dmx/dmxcursor.c

414 lines
9.7 KiB
C

/*
* Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
*
* 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 on 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 (including the
* next paragraph) 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
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
* 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.
*/
/*
* Authors:
* David H. Dawes <dawes@xfree86.org>
* Kevin E. Martin <kem@redhat.com>
* Rickard E. (Rik) Faith <faith@redhat.com>
*
*/
#ifdef HAVE_DMX_CONFIG_H
#include <dmx-config.h>
#endif
#include "dmx.h"
#include "dmxsync.h"
#include "dmxcursor.h"
#include "dmxlog.h"
#include "dmxprop.h"
#include "dmxinput.h"
#include "dmxgrab.h"
#include "mipointer.h"
#include "windowstr.h"
#include "globals.h"
#include "cursorstr.h"
Bool
dmxInitCursor (ScreenPtr pScreen)
{
if (!dixRequestPrivate (CursorScreenKey (pScreen), sizeof (dmxCursorPrivRec)))
return FALSE;
if (!dixRequestPrivate (dmxDevicePrivateKey, sizeof (dmxDevicePrivRec)))
return FALSE;
return TRUE;
}
static Bool
dmxCursorOffScreen (ScreenPtr *ppScreen,
int *x,
int *y)
{
return FALSE;
}
static void
dmxCrossScreen (ScreenPtr pScreen,
Bool entering)
{
}
static void
dmxWarpCursor (DeviceIntPtr pDev,
ScreenPtr pScreen,
int x,
int y)
{
int i;
for (i = 0; i < dmxNumScreens; i++)
{
DMXScreenInfo *dmxScreen = &dmxScreens[i];
if (!dmxScreen->beDisplay)
continue;
dmxInputWarpPointer (&dmxScreen->input, pDev, x, y);
}
}
miPointerScreenFuncRec dmxPointerCursorFuncs = {
dmxCursorOffScreen,
dmxCrossScreen,
dmxWarpCursor
};
#ifdef ARGB_CURSOR
static Cursor
dmxCreateARGBCursor (ScreenPtr pScreen,
CursorPtr pCursor);
#endif
/** Create \a pCursor on the back-end associated with \a pScreen. */
void
dmxBECreateCursor (ScreenPtr pScreen,
CursorPtr pCursor)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
CursorBitsPtr pBits = pCursor->bits;
Pixmap src, msk;
XColor fg, bg;
XImage *img;
XlibGC gc = NULL;
XGCValues v;
unsigned long m;
int i;
if (pCursorPriv->cursor)
return;
if (IsAnimCur (pCursor))
{
AnimCurPtr ac = GetAnimCur (pCursor);
XAnimCursor *cursors;
int i;
cursors = xalloc (sizeof (*cursors) * ac->nelt);
if (!cursors)
return;
for (i = 0; i < ac->nelt; i++)
{
dmxCursorPrivPtr pEltPriv = DMX_GET_CURSOR_PRIV (ac->elts[i].pCursor,
pScreen);
dmxBECreateCursor (pScreen, ac->elts[i].pCursor);
cursors[i].cursor = pEltPriv->cursor;
cursors[i].delay = ac->elts[i].delay;
}
pCursorPriv->cursor = XRenderCreateAnimCursor (dmxScreen->beDisplay,
ac->nelt,
cursors);
xfree (cursors);
if (pCursorPriv->cursor)
return;
}
#ifdef ARGB_CURSOR
if (pCursor->bits->argb)
{
pCursorPriv->cursor = dmxCreateARGBCursor (pScreen, pCursor);
if (pCursorPriv->cursor)
return;
}
#endif
m = GCFunction | GCPlaneMask | GCForeground | GCBackground | GCClipMask;
v.function = GXcopy;
v.plane_mask = AllPlanes;
v.foreground = 1L;
v.background = 0L;
v.clip_mask = None;
for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
if (dmxScreen->bePixmapFormats[i].depth == 1) {
/* Create GC in the back-end servers */
XLIB_PROLOGUE (dmxScreen);
gc = XCreateGC(dmxScreen->beDisplay, dmxScreen->scrnDefDrawables[i],
m, &v);
XLIB_EPILOGUE (dmxScreen);
break;
}
}
if (!gc)
dmxLog(dmxFatal, "dmxRealizeCursor: gc not initialized\n");
XLIB_PROLOGUE (dmxScreen);
src = XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
pBits->width, pBits->height, 1);
msk = XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
pBits->width, pBits->height, 1);
img = XCreateImage(dmxScreen->beDisplay,
dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
1, XYBitmap, 0, (char *)pBits->source,
pBits->width, pBits->height,
BitmapPad(dmxScreen->beDisplay), 0);
XPutImage(dmxScreen->beDisplay, src, gc, img, 0, 0, 0, 0,
pBits->width, pBits->height);
XFree(img);
img = XCreateImage(dmxScreen->beDisplay,
dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
1, XYBitmap, 0, (char *)pBits->mask,
pBits->width, pBits->height,
BitmapPad(dmxScreen->beDisplay), 0);
XPutImage(dmxScreen->beDisplay, msk, gc, img, 0, 0, 0, 0,
pBits->width, pBits->height);
XFree(img);
fg.red = pCursor->foreRed;
fg.green = pCursor->foreGreen;
fg.blue = pCursor->foreBlue;
bg.red = pCursor->backRed;
bg.green = pCursor->backGreen;
bg.blue = pCursor->backBlue;
pCursorPriv->cursor = XCreatePixmapCursor(dmxScreen->beDisplay,
src, msk,
&fg, &bg,
pBits->xhot, pBits->yhot);
XFreePixmap(dmxScreen->beDisplay, src);
XFreePixmap(dmxScreen->beDisplay, msk);
XFreeGC(dmxScreen->beDisplay, gc);
XLIB_EPILOGUE (dmxScreen);
}
static Bool
_dmxRealizeCursor (ScreenPtr pScreen,
CursorPtr pCursor)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
dmxCursorPrivPtr pCursorPriv;
pCursorPriv = DMX_GET_CURSOR_PRIV (pCursor, pScreen);
pCursorPriv->cursor = (Cursor) 0;
if (dmxScreen->beDisplay)
dmxBECreateCursor (pScreen, pCursor);
return TRUE;
}
/** Free \a pCursor on the back-end associated with \a pScreen. */
Bool
dmxBEFreeCursor (ScreenPtr pScreen,
CursorPtr pCursor)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV (pCursor, pScreen);
if (pCursorPriv->cursor)
{
XLIB_PROLOGUE (dmxScreen);
XFreeCursor (dmxScreen->beDisplay, pCursorPriv->cursor);
XLIB_EPILOGUE (dmxScreen);
pCursorPriv->cursor = (Cursor) 0;
if (IsAnimCur (pCursor))
{
AnimCurPtr ac = GetAnimCur (pCursor);
int i;
for (i = 0; i < ac->nelt; i++)
dmxBEFreeCursor (pScreen, ac->elts[i].pCursor);
}
return TRUE;
}
return FALSE;
}
static Bool
_dmxUnrealizeCursor (ScreenPtr pScreen,
CursorPtr pCursor)
{
dmxBEFreeCursor (pScreen, pCursor);
return TRUE;
}
static Bool
dmxRealizeCursor (DeviceIntPtr pDev,
ScreenPtr pScreen,
CursorPtr pCursor)
{
if (pDev == inputInfo.pointer)
return _dmxRealizeCursor (pScreen, pCursor);
return TRUE;
}
static Bool
dmxUnrealizeCursor (DeviceIntPtr pDev,
ScreenPtr pScreen,
CursorPtr pCursor)
{
if (pDev == inputInfo.pointer)
return _dmxUnrealizeCursor (pScreen, pCursor);
return TRUE;
}
static void
dmxMoveCursor (DeviceIntPtr pDev,
ScreenPtr pScreen,
int x,
int y)
{
}
static void
dmxSetCursor (DeviceIntPtr pDev,
ScreenPtr pScreen,
CursorPtr pCursor,
int x,
int y)
{
}
static Bool
dmxDeviceCursorInitialize (DeviceIntPtr pDev,
ScreenPtr pScr)
{
return TRUE;
}
static void
dmxDeviceCursorCleanup (DeviceIntPtr pDev,
ScreenPtr pScr)
{
}
miPointerSpriteFuncRec dmxPointerSpriteFuncs =
{
dmxRealizeCursor,
dmxUnrealizeCursor,
dmxSetCursor,
dmxMoveCursor,
dmxDeviceCursorInitialize,
dmxDeviceCursorCleanup
};
#ifdef ARGB_CURSOR
#include <X11/extensions/Xrender.h>
static Cursor
dmxCreateARGBCursor (ScreenPtr pScreen,
CursorPtr pCursor)
{
Pixmap xpixmap;
XlibGC xgc;
XImage *ximage;
XRenderPictFormat *xformat;
Picture xpicture;
Cursor cursor = None;
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
XLIB_PROLOGUE (dmxScreen);
xpixmap = XCreatePixmap (dmxScreen->beDisplay,
dmxScreen->scrnWin,
pCursor->bits->width,
pCursor->bits->height,
32);
xgc = XCreateGC (dmxScreen->beDisplay, xpixmap, 0, NULL);
ximage = XCreateImage (dmxScreen->beDisplay,
DefaultVisual (dmxScreen->beDisplay, 0),
32, ZPixmap, 0,
(char *) pCursor->bits->argb,
pCursor->bits->width,
pCursor->bits->height,
32, pCursor->bits->width * 4);
XPutImage (dmxScreen->beDisplay, xpixmap, xgc, ximage,
0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
XFree (ximage);
XFreeGC (dmxScreen->beDisplay, xgc);
xformat = XRenderFindStandardFormat (dmxScreen->beDisplay,
PictStandardARGB32);
xpicture = XRenderCreatePicture (dmxScreen->beDisplay, xpixmap,
xformat, 0, 0);
cursor = XRenderCreateCursor (dmxScreen->beDisplay, xpicture,
pCursor->bits->xhot,
pCursor->bits->yhot);
XRenderFreePicture (dmxScreen->beDisplay, xpicture);
XFreePixmap (dmxScreen->beDisplay, xpixmap);
XLIB_EPILOGUE (dmxScreen);
return cursor;
}
#endif