X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=Xserver%2Fprograms%2FXserver%2Fhw%2Fvnc%2Fdispcur.c;fp=Xserver%2Fprograms%2FXserver%2Fhw%2Fvnc%2Fdispcur.c;h=6a89d25b3415d76333b648a07f13db085c1eb38d;hb=b6e6afccf37f4ad0515ef2a698f714fdf1bf23b3;hp=0000000000000000000000000000000000000000;hpb=e3340a110a3b01756b8e67531395a33b40a17d37;p=rdpsrv diff --git a/Xserver/programs/Xserver/hw/vnc/dispcur.c b/Xserver/programs/Xserver/hw/vnc/dispcur.c new file mode 100644 index 0000000..6a89d25 --- /dev/null +++ b/Xserver/programs/Xserver/hw/vnc/dispcur.c @@ -0,0 +1,403 @@ +/* + * dispcur.c + * + * cursor display routines - based on midispcur.c + */ + +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + +Copyright (c) 1989 X Consortium + +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 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 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 NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM 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. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. +*/ + +#define NEED_EVENTS +# include "X.h" +# include "misc.h" +# include "input.h" +# include "cursorstr.h" +# include "windowstr.h" +# include "regionstr.h" +# include "dixstruct.h" +# include "scrnintstr.h" +# include "servermd.h" +# include "mipointer.h" +# include "sprite.h" +# include "gcstruct.h" + +extern WindowPtr *WindowTable; + +/* per-screen private data */ + +static int rfbDCScreenIndex; +static unsigned long rfbDCGeneration = 0; + +static Bool rfbDCCloseScreen(); + +typedef struct { + GCPtr pSourceGC, pMaskGC; + GCPtr pSaveGC, pRestoreGC; + GCPtr pPixSourceGC, pPixMaskGC; + CloseScreenProcPtr CloseScreen; + PixmapPtr pSave; +} rfbDCScreenRec, *rfbDCScreenPtr; + +/* per-cursor per-screen private data */ +typedef struct { + PixmapPtr sourceBits; /* source bits */ + PixmapPtr maskBits; /* mask bits */ +} rfbDCCursorRec, *rfbDCCursorPtr; + +/* + * sprite/cursor method table + */ + +static Bool rfbDCRealizeCursor(), rfbDCUnrealizeCursor(); +static Bool rfbDCPutUpCursor(), rfbDCSaveUnderCursor(); +static Bool rfbDCRestoreUnderCursor(); + +static rfbSpriteCursorFuncRec rfbDCFuncs = { + rfbDCRealizeCursor, + rfbDCUnrealizeCursor, + rfbDCPutUpCursor, + rfbDCSaveUnderCursor, + rfbDCRestoreUnderCursor, +}; + +Bool +rfbDCInitialize (pScreen, screenFuncs) + ScreenPtr pScreen; + miPointerScreenFuncPtr screenFuncs; +{ + rfbDCScreenPtr pScreenPriv; + + if (rfbDCGeneration != serverGeneration) + { + rfbDCScreenIndex = AllocateScreenPrivateIndex (); + if (rfbDCScreenIndex < 0) + return FALSE; + rfbDCGeneration = serverGeneration; + } + pScreenPriv = (rfbDCScreenPtr) xalloc (sizeof (rfbDCScreenRec)); + if (!pScreenPriv) + return FALSE; + + /* + * initialize the entire private structure to zeros + */ + + pScreenPriv->pSourceGC = + pScreenPriv->pMaskGC = + pScreenPriv->pSaveGC = + pScreenPriv->pRestoreGC = + pScreenPriv->pPixSourceGC = + pScreenPriv->pPixMaskGC = NULL; + + pScreenPriv->pSave = NULL; + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = rfbDCCloseScreen; + + pScreen->devPrivates[rfbDCScreenIndex].ptr = (pointer) pScreenPriv; + + if (!rfbSpriteInitialize (pScreen, &rfbDCFuncs, screenFuncs)) + { + xfree ((pointer) pScreenPriv); + return FALSE; + } + return TRUE; +} + +#define tossGC(gc) (gc ? FreeGC (gc, (GContext) 0) : 0) +#define tossPix(pix) (pix ? (*pScreen->DestroyPixmap) (pix) : TRUE) + +static Bool +rfbDCCloseScreen (index, pScreen) + ScreenPtr pScreen; +{ + rfbDCScreenPtr pScreenPriv; + + pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; + pScreen->CloseScreen = pScreenPriv->CloseScreen; + tossGC (pScreenPriv->pSourceGC); + tossGC (pScreenPriv->pMaskGC); + tossGC (pScreenPriv->pSaveGC); + tossGC (pScreenPriv->pRestoreGC); + tossGC (pScreenPriv->pPixSourceGC); + tossGC (pScreenPriv->pPixMaskGC); + tossPix (pScreenPriv->pSave); + xfree ((pointer) pScreenPriv); + return (*pScreen->CloseScreen) (index, pScreen); +} + +static Bool +rfbDCRealizeCursor (pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + if (pCursor->bits->refcnt <= 1) + pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; + return TRUE; +} + +static rfbDCCursorPtr +rfbDCRealize (pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + rfbDCCursorPtr pPriv; + GCPtr pGC; + XID gcvals[3]; + + pPriv = (rfbDCCursorPtr) xalloc (sizeof (rfbDCCursorRec)); + if (!pPriv) + return (rfbDCCursorPtr)NULL; + pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); + if (!pPriv->sourceBits) + { + xfree ((pointer) pPriv); + return (rfbDCCursorPtr)NULL; + } + pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); + if (!pPriv->maskBits) + { + (*pScreen->DestroyPixmap) (pPriv->sourceBits); + xfree ((pointer) pPriv); + return (rfbDCCursorPtr)NULL; + } + pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv; + + /* create the two sets of bits, clipping as appropriate */ + + pGC = GetScratchGC (1, pScreen); + if (!pGC) + { + (void) rfbDCUnrealizeCursor (pScreen, pCursor); + return (rfbDCCursorPtr)NULL; + } + + ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->source); + gcvals[0] = GXand; + ChangeGC (pGC, GCFunction, gcvals); + ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->mask); + + /* mask bits -- pCursor->mask & ~pCursor->source */ + gcvals[0] = GXcopy; + ChangeGC (pGC, GCFunction, gcvals); + ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->mask); + gcvals[0] = GXandInverted; + ChangeGC (pGC, GCFunction, gcvals); + ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->source); + FreeScratchGC (pGC); + return pPriv; +} + +static Bool +rfbDCUnrealizeCursor (pScreen, pCursor) + ScreenPtr pScreen; + CursorPtr pCursor; +{ + rfbDCCursorPtr pPriv; + + pPriv = (rfbDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; + if (pPriv && (pCursor->bits->refcnt <= 1)) + { + (*pScreen->DestroyPixmap) (pPriv->sourceBits); + (*pScreen->DestroyPixmap) (pPriv->maskBits); + xfree ((pointer) pPriv); + pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; + } + return TRUE; +} + +static void +rfbDCPutBits (pDrawable, pPriv, sourceGC, maskGC, x, y, w, h, source, mask) + DrawablePtr pDrawable; + GCPtr sourceGC, maskGC; + int x, y; + unsigned w, h; + rfbDCCursorPtr pPriv; + unsigned long source, mask; +{ + XID gcvals[1]; + + if (sourceGC->fgPixel != source) + { + gcvals[0] = source; + DoChangeGC (sourceGC, GCForeground, gcvals, 0); + } + if (sourceGC->serialNumber != pDrawable->serialNumber) + ValidateGC (pDrawable, sourceGC); + (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y); + if (maskGC->fgPixel != mask) + { + gcvals[0] = mask; + DoChangeGC (maskGC, GCForeground, gcvals, 0); + } + if (maskGC->serialNumber != pDrawable->serialNumber) + ValidateGC (pDrawable, maskGC); + (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); +} + +#define EnsureGC(gc,win) (gc || rfbDCMakeGC(&gc, win)) + +static GCPtr +rfbDCMakeGC(ppGC, pWin) + GCPtr *ppGC; + WindowPtr pWin; +{ + GCPtr pGC; + int status; + XID gcvals[2]; + + gcvals[0] = IncludeInferiors; + gcvals[1] = FALSE; + pGC = CreateGC((DrawablePtr)pWin, + GCSubwindowMode|GCGraphicsExposures, gcvals, &status); + if (pGC) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + *ppGC = pGC; + return pGC; +} + +static Bool +rfbDCPutUpCursor (pScreen, pCursor, x, y, source, mask) + ScreenPtr pScreen; + CursorPtr pCursor; + int x, y; + unsigned long source, mask; +{ + rfbDCScreenPtr pScreenPriv; + rfbDCCursorPtr pPriv; + WindowPtr pWin; + + pPriv = (rfbDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; + if (!pPriv) + { + pPriv = rfbDCRealize(pScreen, pCursor); + if (!pPriv) + return FALSE; + } + pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; + pWin = WindowTable[pScreen->myNum]; + if (!EnsureGC(pScreenPriv->pSourceGC, pWin)) + return FALSE; + if (!EnsureGC(pScreenPriv->pMaskGC, pWin)) + { + FreeGC (pScreenPriv->pSourceGC, (GContext) 0); + pScreenPriv->pSourceGC = 0; + return FALSE; + } + rfbDCPutBits ((DrawablePtr)pWin, pPriv, + pScreenPriv->pSourceGC, pScreenPriv->pMaskGC, + x, y, pCursor->bits->width, pCursor->bits->height, + source, mask); + return TRUE; +} + +static Bool +rfbDCSaveUnderCursor (pScreen, x, y, w, h) + ScreenPtr pScreen; + int x, y, w, h; +{ + rfbDCScreenPtr pScreenPriv; + PixmapPtr pSave; + WindowPtr pWin; + GCPtr pGC; + + pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; + pSave = pScreenPriv->pSave; + pWin = WindowTable[pScreen->myNum]; + if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) + { + if (pSave) + (*pScreen->DestroyPixmap) (pSave); + pScreenPriv->pSave = pSave = + (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth); + if (!pSave) + return FALSE; + } + if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) + return FALSE; + pGC = pScreenPriv->pSaveGC; + if (pSave->drawable.serialNumber != pGC->serialNumber) + ValidateGC ((DrawablePtr) pSave, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, + x, y, w, h, 0, 0); + return TRUE; +} + +static Bool +rfbDCRestoreUnderCursor (pScreen, x, y, w, h) + ScreenPtr pScreen; + int x, y, w, h; +{ + rfbDCScreenPtr pScreenPriv; + PixmapPtr pSave; + WindowPtr pWin; + GCPtr pGC; + + pScreenPriv = (rfbDCScreenPtr) pScreen->devPrivates[rfbDCScreenIndex].ptr; + pSave = pScreenPriv->pSave; + pWin = WindowTable[pScreen->myNum]; + if (!pSave) + return FALSE; + if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) + return FALSE; + pGC = pScreenPriv->pRestoreGC; + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC ((DrawablePtr) pWin, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, + 0, 0, w, h, x, y); + return TRUE; +}