]> git.sesse.net Git - rdpsrv/blobdiff - Xserver/programs/Xserver/hw/vnc/dispcur.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / hw / vnc / dispcur.c
diff --git a/Xserver/programs/Xserver/hw/vnc/dispcur.c b/Xserver/programs/Xserver/hw/vnc/dispcur.c
new file mode 100644 (file)
index 0000000..6a89d25
--- /dev/null
@@ -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;
+}