diff options
Diffstat (limited to 'xorg-server/hw/kdrive')
22 files changed, 5302 insertions, 5292 deletions
diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.c b/xorg-server/hw/kdrive/ephyr/ephyr.c index ac8e5bef9..7ebf1c253 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyr.c +++ b/xorg-server/hw/kdrive/ephyr/ephyr.c @@ -2,7 +2,7 @@ * Xephyr - A kdrive X server thats runs in a host X window. * Authored by Matthew Allum <mallum@openedhand.com> * - * Copyright © 2004 Nokia + * Copyright © 2004 Nokia * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.h b/xorg-server/hw/kdrive/ephyr/ephyr.h index 41a82bf9d..23848004c 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyr.h +++ b/xorg-server/hw/kdrive/ephyr/ephyr.h @@ -2,7 +2,7 @@ * Xephyr - A kdrive X server thats runs in a host X window. * Authored by Matthew Allum <mallum@o-hand.com> * - * Copyright © 2004 Nokia + * Copyright © 2004 Nokia * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg-server/hw/kdrive/ephyr/ephyr_draw.c b/xorg-server/hw/kdrive/ephyr/ephyr_draw.c index f3e2be6eb..cf5f55394 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyr_draw.c +++ b/xorg-server/hw/kdrive/ephyr/ephyr_draw.c @@ -1,523 +1,523 @@ -/*
- * Copyright © 2006 Intel Corporation
- *
- * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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:
- * Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-
-#include "ephyr.h"
-#include "exa_priv.h"
-#include "fbpict.h"
-
-#define EPHYR_TRACE_DRAW 0
-
-#if EPHYR_TRACE_DRAW
-#define TRACE_DRAW() ErrorF("%s\n", __FUNCTION__);
-#else
-#define TRACE_DRAW() do { } while (0)
-#endif
-
-/* Use some oddball alignments, to expose issues in alignment handling in EXA. */
-#define EPHYR_OFFSET_ALIGN 24
-#define EPHYR_PITCH_ALIGN 24
-
-#define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024)
-#define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024)
-
-/**
- * Forces a real devPrivate.ptr for hidden pixmaps, so that we can call down to
- * fb functions.
- */
-static void
-ephyrPreparePipelinedAccess(PixmapPtr pPix, int index)
-{
- KdScreenPriv(pPix->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- assert(fakexa->saved_ptrs[index] == NULL);
- fakexa->saved_ptrs[index] = pPix->devPrivate.ptr;
-
- if (pPix->devPrivate.ptr != NULL)
- return;
-
- pPix->devPrivate.ptr = fakexa->exa->memoryBase + exaGetPixmapOffset(pPix);
-}
-
-/**
- * Restores the original devPrivate.ptr of the pixmap from before we messed with
- * it.
- */
-static void
-ephyrFinishPipelinedAccess(PixmapPtr pPix, int index)
-{
- KdScreenPriv(pPix->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- pPix->devPrivate.ptr = fakexa->saved_ptrs[index];
- fakexa->saved_ptrs[index] = NULL;
-}
-
-/**
- * Sets up a scratch GC for fbFill, and saves other parameters for the
- * ephyrSolid implementation.
- */
-static Bool
-ephyrPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
-{
- ScreenPtr pScreen = pPix->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
- ChangeGCVal tmpval[3];
-
- ephyrPreparePipelinedAccess(pPix, EXA_PREPARE_DEST);
-
- fakexa->pDst = pPix;
- fakexa->pGC = GetScratchGC(pPix->drawable.depth, pScreen);
-
- tmpval[0].val = alu;
- tmpval[1].val = pm;
- tmpval[2].val = fg;
- ChangeGC(NullClient, fakexa->pGC, GCFunction | GCPlaneMask | GCForeground, tmpval);
-
- ValidateGC(&pPix->drawable, fakexa->pGC);
-
- TRACE_DRAW();
-
- return TRUE;
-}
-
-/**
- * Does an fbFill of the rectangle to be drawn.
- */
-static void
-ephyrSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
-{
- ScreenPtr pScreen = pPix->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- fbFill(&fakexa->pDst->drawable, fakexa->pGC, x1, y1, x2 - x1, y2 - y1);
-}
-
-/**
- * Cleans up the scratch GC created in ephyrPrepareSolid.
- */
-static void
-ephyrDoneSolid(PixmapPtr pPix)
-{
- ScreenPtr pScreen = pPix->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- FreeScratchGC(fakexa->pGC);
-
- ephyrFinishPipelinedAccess(pPix, EXA_PREPARE_DEST);
-}
-
-/**
- * Sets up a scratch GC for fbCopyArea, and saves other parameters for the
- * ephyrCopy implementation.
- */
-static Bool
-ephyrPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu,
- Pixel pm)
-{
- ScreenPtr pScreen = pDst->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
- ChangeGCVal tmpval[2];
-
- ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
- ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
-
- fakexa->pSrc = pSrc;
- fakexa->pDst = pDst;
- fakexa->pGC = GetScratchGC(pDst->drawable.depth, pScreen);
-
- tmpval[0].val = alu;
- tmpval[1].val = pm;
- ChangeGC (NullClient, fakexa->pGC, GCFunction | GCPlaneMask, tmpval);
-
- ValidateGC(&pDst->drawable, fakexa->pGC);
-
- TRACE_DRAW();
-
- return TRUE;
-}
-
-/**
- * Does an fbCopyArea to take care of the requested copy.
- */
-static void
-ephyrCopy(PixmapPtr pDst, int srcX, int srcY, int dstX, int dstY, int w, int h)
-{
- ScreenPtr pScreen = pDst->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- fbCopyArea(&fakexa->pSrc->drawable, &fakexa->pDst->drawable, fakexa->pGC,
- srcX, srcY, w, h, dstX, dstY);
-}
-
-/**
- * Cleans up the scratch GC created in ephyrPrepareCopy.
- */
-static void
-ephyrDoneCopy(PixmapPtr pDst)
-{
- ScreenPtr pScreen = pDst->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- FreeScratchGC (fakexa->pGC);
-
- ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC);
- ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST);
-}
-
-/**
- * Reports that we can always accelerate the given operation. This may not be
- * desirable from an EXA testing standpoint -- testing the fallback paths would
- * be useful, too.
- */
-static Bool
-ephyrCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
- PicturePtr pDstPicture)
-{
- /* Exercise the component alpha helper, so fail on this case like a normal
- * driver
- */
- if (pMaskPicture && pMaskPicture->componentAlpha && op == PictOpOver)
- return FALSE;
-
- return TRUE;
-}
-
-/**
- * Saves off the parameters for ephyrComposite.
- */
-static Bool
-ephyrPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
- PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask,
- PixmapPtr pDst)
-{
- KdScreenPriv(pDst->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
- ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
- if (pMask != NULL)
- ephyrPreparePipelinedAccess(pMask, EXA_PREPARE_MASK);
-
- fakexa->op = op;
- fakexa->pSrcPicture = pSrcPicture;
- fakexa->pMaskPicture = pMaskPicture;
- fakexa->pDstPicture = pDstPicture;
- fakexa->pSrc = pSrc;
- fakexa->pMask = pMask;
- fakexa->pDst = pDst;
-
- TRACE_DRAW();
-
- return TRUE;
-}
-
-/**
- * Does an fbComposite to complete the requested drawing operation.
- */
-static void
-ephyrComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
- int dstX, int dstY, int w, int h)
-{
- KdScreenPriv(pDst->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- fbComposite(fakexa->op, fakexa->pSrcPicture, fakexa->pMaskPicture,
- fakexa->pDstPicture, srcX, srcY, maskX, maskY, dstX, dstY,
- w, h);
-}
-
-static void
-ephyrDoneComposite(PixmapPtr pDst)
-{
- KdScreenPriv(pDst->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- if (fakexa->pMask != NULL)
- ephyrFinishPipelinedAccess(fakexa->pMask, EXA_PREPARE_MASK);
- ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC);
- ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST);
-}
-
-/**
- * Does fake acceleration of DownloadFromScren using memcpy.
- */
-static Bool
-ephyrDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst,
- int dst_pitch)
-{
- KdScreenPriv(pSrc->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
- unsigned char *src;
- int src_pitch, cpp;
-
- if (pSrc->drawable.bitsPerPixel < 8)
- return FALSE;
-
- ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
-
- cpp = pSrc->drawable.bitsPerPixel / 8;
- src_pitch = exaGetPixmapPitch(pSrc);
- src = fakexa->exa->memoryBase + exaGetPixmapOffset(pSrc);
- src += y * src_pitch + x * cpp;
-
- for (; h > 0; h--) {
- memcpy(dst, src, w * cpp);
- dst += dst_pitch;
- src += src_pitch;
- }
-
- exaMarkSync(pSrc->drawable.pScreen);
-
- ephyrFinishPipelinedAccess(pSrc, EXA_PREPARE_SRC);
-
- return TRUE;
-}
-
-/**
- * Does fake acceleration of UploadToScreen using memcpy.
- */
-static Bool
-ephyrUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
- int src_pitch)
-{
- KdScreenPriv(pDst->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
- unsigned char *dst;
- int dst_pitch, cpp;
-
- if (pDst->drawable.bitsPerPixel < 8)
- return FALSE;
-
- ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
-
- cpp = pDst->drawable.bitsPerPixel / 8;
- dst_pitch = exaGetPixmapPitch(pDst);
- dst = fakexa->exa->memoryBase + exaGetPixmapOffset(pDst);
- dst += y * dst_pitch + x * cpp;
-
- for (; h > 0; h--) {
- memcpy(dst, src, w * cpp);
- dst += dst_pitch;
- src += src_pitch;
- }
-
- exaMarkSync(pDst->drawable.pScreen);
-
- ephyrFinishPipelinedAccess(pDst, EXA_PREPARE_DEST);
-
- return TRUE;
-}
-
-static Bool
-ephyrPrepareAccess(PixmapPtr pPix, int index)
-{
- /* Make sure we don't somehow end up with a pointer that is in framebuffer
- * and hasn't been readied for us.
- */
- assert(pPix->devPrivate.ptr != NULL);
-
- return TRUE;
-}
-
-/**
- * In fakexa, we currently only track whether we have synced to the latest
- * "accelerated" drawing that has happened or not. It's not used for anything
- * yet.
- */
-static int
-ephyrMarkSync(ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- fakexa->is_synced = FALSE;
-
- return 0;
-}
-
-/**
- * Assumes that we're waiting on the latest marker. When EXA gets smarter and
- * starts using markers in a fine-grained way (for example, waiting on drawing
- * to required pixmaps to complete, rather than waiting for all drawing to
- * complete), we'll want to make the ephyrMarkSync/ephyrWaitMarker
- * implementation fine-grained as well.
- */
-static void
-ephyrWaitMarker(ScreenPtr pScreen, int marker)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- fakexa->is_synced = TRUE;
-}
-
-/**
- * This function initializes EXA to use the fake acceleration implementation
- * which just falls through to software. The purpose is to have a reliable,
- * correct driver with which to test changes to the EXA core.
- */
-Bool
-ephyrDrawInit(ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrPriv *priv = screen->card->driver;
- EphyrFakexaPriv *fakexa;
- Bool success;
-
- fakexa = calloc(1, sizeof(*fakexa));
- if (fakexa == NULL)
- return FALSE;
-
- fakexa->exa = exaDriverAlloc();
- if (fakexa->exa == NULL) {
- free(fakexa);
- return FALSE;
- }
-
- fakexa->exa->memoryBase = (CARD8 *) (priv->base);
- fakexa->exa->memorySize = priv->bytes_per_line * ephyrBufferHeight(screen);
- fakexa->exa->offScreenBase = priv->bytes_per_line * screen->height;
-
- /* Since we statically link against EXA, we shouldn't have to be smart about
- * versioning.
- */
- fakexa->exa->exa_major = 2;
- fakexa->exa->exa_minor = 0;
-
- fakexa->exa->PrepareSolid = ephyrPrepareSolid;
- fakexa->exa->Solid = ephyrSolid;
- fakexa->exa->DoneSolid = ephyrDoneSolid;
-
- fakexa->exa->PrepareCopy = ephyrPrepareCopy;
- fakexa->exa->Copy = ephyrCopy;
- fakexa->exa->DoneCopy = ephyrDoneCopy;
-
- fakexa->exa->CheckComposite = ephyrCheckComposite;
- fakexa->exa->PrepareComposite = ephyrPrepareComposite;
- fakexa->exa->Composite = ephyrComposite;
- fakexa->exa->DoneComposite = ephyrDoneComposite;
-
- fakexa->exa->DownloadFromScreen = ephyrDownloadFromScreen;
- fakexa->exa->UploadToScreen = ephyrUploadToScreen;
-
- fakexa->exa->MarkSync = ephyrMarkSync;
- fakexa->exa->WaitMarker = ephyrWaitMarker;
-
- fakexa->exa->PrepareAccess = ephyrPrepareAccess;
-
- fakexa->exa->pixmapOffsetAlign = EPHYR_OFFSET_ALIGN;
- fakexa->exa->pixmapPitchAlign = EPHYR_PITCH_ALIGN;
-
- fakexa->exa->maxX = 1023;
- fakexa->exa->maxY = 1023;
-
- fakexa->exa->flags = EXA_OFFSCREEN_PIXMAPS;
-
- success = exaDriverInit(pScreen, fakexa->exa);
- if (success) {
- ErrorF("Initialized fake EXA acceleration\n");
- scrpriv->fakexa = fakexa;
- } else {
- ErrorF("Failed to initialize EXA\n");
- free(fakexa->exa);
- free(fakexa);
- }
-
- return success;
-}
-
-void
-ephyrDrawEnable(ScreenPtr pScreen)
-{
-}
-
-void
-ephyrDrawDisable(ScreenPtr pScreen)
-{
-}
-
-void
-ephyrDrawFini(ScreenPtr pScreen)
-{
-}
-
-/**
- * exaDDXDriverInit is required by the top-level EXA module, and is used by
- * the xorg DDX to hook in its EnableDisableFB wrapper. We don't need it, since
- * we won't be enabling/disabling the FB.
- */
-void
-exaDDXDriverInit(ScreenPtr pScreen)
-{
- ExaScreenPriv(pScreen);
-
- pExaScr->migration = ExaMigrationSmart;
- pExaScr->checkDirtyCorrectness = TRUE;
-}
+/* + * Copyright © 2006 Intel Corporation + * + * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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: + * Eric Anholt <eric@anholt.net> + * + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#include "ephyr.h" +#include "exa_priv.h" +#include "fbpict.h" + +#define EPHYR_TRACE_DRAW 0 + +#if EPHYR_TRACE_DRAW +#define TRACE_DRAW() ErrorF("%s\n", __FUNCTION__); +#else +#define TRACE_DRAW() do { } while (0) +#endif + +/* Use some oddball alignments, to expose issues in alignment handling in EXA. */ +#define EPHYR_OFFSET_ALIGN 24 +#define EPHYR_PITCH_ALIGN 24 + +#define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024) +#define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024) + +/** + * Forces a real devPrivate.ptr for hidden pixmaps, so that we can call down to + * fb functions. + */ +static void +ephyrPreparePipelinedAccess(PixmapPtr pPix, int index) +{ + KdScreenPriv(pPix->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + assert(fakexa->saved_ptrs[index] == NULL); + fakexa->saved_ptrs[index] = pPix->devPrivate.ptr; + + if (pPix->devPrivate.ptr != NULL) + return; + + pPix->devPrivate.ptr = fakexa->exa->memoryBase + exaGetPixmapOffset(pPix); +} + +/** + * Restores the original devPrivate.ptr of the pixmap from before we messed with + * it. + */ +static void +ephyrFinishPipelinedAccess(PixmapPtr pPix, int index) +{ + KdScreenPriv(pPix->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + pPix->devPrivate.ptr = fakexa->saved_ptrs[index]; + fakexa->saved_ptrs[index] = NULL; +} + +/** + * Sets up a scratch GC for fbFill, and saves other parameters for the + * ephyrSolid implementation. + */ +static Bool +ephyrPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + ChangeGCVal tmpval[3]; + + ephyrPreparePipelinedAccess(pPix, EXA_PREPARE_DEST); + + fakexa->pDst = pPix; + fakexa->pGC = GetScratchGC(pPix->drawable.depth, pScreen); + + tmpval[0].val = alu; + tmpval[1].val = pm; + tmpval[2].val = fg; + ChangeGC(NullClient, fakexa->pGC, GCFunction | GCPlaneMask | GCForeground, tmpval); + + ValidateGC(&pPix->drawable, fakexa->pGC); + + TRACE_DRAW(); + + return TRUE; +} + +/** + * Does an fbFill of the rectangle to be drawn. + */ +static void +ephyrSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + fbFill(&fakexa->pDst->drawable, fakexa->pGC, x1, y1, x2 - x1, y2 - y1); +} + +/** + * Cleans up the scratch GC created in ephyrPrepareSolid. + */ +static void +ephyrDoneSolid(PixmapPtr pPix) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + FreeScratchGC(fakexa->pGC); + + ephyrFinishPipelinedAccess(pPix, EXA_PREPARE_DEST); +} + +/** + * Sets up a scratch GC for fbCopyArea, and saves other parameters for the + * ephyrCopy implementation. + */ +static Bool +ephyrPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu, + Pixel pm) +{ + ScreenPtr pScreen = pDst->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + ChangeGCVal tmpval[2]; + + ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); + ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); + + fakexa->pSrc = pSrc; + fakexa->pDst = pDst; + fakexa->pGC = GetScratchGC(pDst->drawable.depth, pScreen); + + tmpval[0].val = alu; + tmpval[1].val = pm; + ChangeGC (NullClient, fakexa->pGC, GCFunction | GCPlaneMask, tmpval); + + ValidateGC(&pDst->drawable, fakexa->pGC); + + TRACE_DRAW(); + + return TRUE; +} + +/** + * Does an fbCopyArea to take care of the requested copy. + */ +static void +ephyrCopy(PixmapPtr pDst, int srcX, int srcY, int dstX, int dstY, int w, int h) +{ + ScreenPtr pScreen = pDst->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + fbCopyArea(&fakexa->pSrc->drawable, &fakexa->pDst->drawable, fakexa->pGC, + srcX, srcY, w, h, dstX, dstY); +} + +/** + * Cleans up the scratch GC created in ephyrPrepareCopy. + */ +static void +ephyrDoneCopy(PixmapPtr pDst) +{ + ScreenPtr pScreen = pDst->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + FreeScratchGC (fakexa->pGC); + + ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC); + ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST); +} + +/** + * Reports that we can always accelerate the given operation. This may not be + * desirable from an EXA testing standpoint -- testing the fallback paths would + * be useful, too. + */ +static Bool +ephyrCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + /* Exercise the component alpha helper, so fail on this case like a normal + * driver + */ + if (pMaskPicture && pMaskPicture->componentAlpha && op == PictOpOver) + return FALSE; + + return TRUE; +} + +/** + * Saves off the parameters for ephyrComposite. + */ +static Bool +ephyrPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, + PixmapPtr pDst) +{ + KdScreenPriv(pDst->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); + ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); + if (pMask != NULL) + ephyrPreparePipelinedAccess(pMask, EXA_PREPARE_MASK); + + fakexa->op = op; + fakexa->pSrcPicture = pSrcPicture; + fakexa->pMaskPicture = pMaskPicture; + fakexa->pDstPicture = pDstPicture; + fakexa->pSrc = pSrc; + fakexa->pMask = pMask; + fakexa->pDst = pDst; + + TRACE_DRAW(); + + return TRUE; +} + +/** + * Does an fbComposite to complete the requested drawing operation. + */ +static void +ephyrComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int w, int h) +{ + KdScreenPriv(pDst->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + fbComposite(fakexa->op, fakexa->pSrcPicture, fakexa->pMaskPicture, + fakexa->pDstPicture, srcX, srcY, maskX, maskY, dstX, dstY, + w, h); +} + +static void +ephyrDoneComposite(PixmapPtr pDst) +{ + KdScreenPriv(pDst->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + if (fakexa->pMask != NULL) + ephyrFinishPipelinedAccess(fakexa->pMask, EXA_PREPARE_MASK); + ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC); + ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST); +} + +/** + * Does fake acceleration of DownloadFromScren using memcpy. + */ +static Bool +ephyrDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, + int dst_pitch) +{ + KdScreenPriv(pSrc->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + unsigned char *src; + int src_pitch, cpp; + + if (pSrc->drawable.bitsPerPixel < 8) + return FALSE; + + ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); + + cpp = pSrc->drawable.bitsPerPixel / 8; + src_pitch = exaGetPixmapPitch(pSrc); + src = fakexa->exa->memoryBase + exaGetPixmapOffset(pSrc); + src += y * src_pitch + x * cpp; + + for (; h > 0; h--) { + memcpy(dst, src, w * cpp); + dst += dst_pitch; + src += src_pitch; + } + + exaMarkSync(pSrc->drawable.pScreen); + + ephyrFinishPipelinedAccess(pSrc, EXA_PREPARE_SRC); + + return TRUE; +} + +/** + * Does fake acceleration of UploadToScreen using memcpy. + */ +static Bool +ephyrUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, + int src_pitch) +{ + KdScreenPriv(pDst->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + unsigned char *dst; + int dst_pitch, cpp; + + if (pDst->drawable.bitsPerPixel < 8) + return FALSE; + + ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); + + cpp = pDst->drawable.bitsPerPixel / 8; + dst_pitch = exaGetPixmapPitch(pDst); + dst = fakexa->exa->memoryBase + exaGetPixmapOffset(pDst); + dst += y * dst_pitch + x * cpp; + + for (; h > 0; h--) { + memcpy(dst, src, w * cpp); + dst += dst_pitch; + src += src_pitch; + } + + exaMarkSync(pDst->drawable.pScreen); + + ephyrFinishPipelinedAccess(pDst, EXA_PREPARE_DEST); + + return TRUE; +} + +static Bool +ephyrPrepareAccess(PixmapPtr pPix, int index) +{ + /* Make sure we don't somehow end up with a pointer that is in framebuffer + * and hasn't been readied for us. + */ + assert(pPix->devPrivate.ptr != NULL); + + return TRUE; +} + +/** + * In fakexa, we currently only track whether we have synced to the latest + * "accelerated" drawing that has happened or not. It's not used for anything + * yet. + */ +static int +ephyrMarkSync(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + fakexa->is_synced = FALSE; + + return 0; +} + +/** + * Assumes that we're waiting on the latest marker. When EXA gets smarter and + * starts using markers in a fine-grained way (for example, waiting on drawing + * to required pixmaps to complete, rather than waiting for all drawing to + * complete), we'll want to make the ephyrMarkSync/ephyrWaitMarker + * implementation fine-grained as well. + */ +static void +ephyrWaitMarker(ScreenPtr pScreen, int marker) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + fakexa->is_synced = TRUE; +} + +/** + * This function initializes EXA to use the fake acceleration implementation + * which just falls through to software. The purpose is to have a reliable, + * correct driver with which to test changes to the EXA core. + */ +Bool +ephyrDrawInit(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrPriv *priv = screen->card->driver; + EphyrFakexaPriv *fakexa; + Bool success; + + fakexa = calloc(1, sizeof(*fakexa)); + if (fakexa == NULL) + return FALSE; + + fakexa->exa = exaDriverAlloc(); + if (fakexa->exa == NULL) { + free(fakexa); + return FALSE; + } + + fakexa->exa->memoryBase = (CARD8 *) (priv->base); + fakexa->exa->memorySize = priv->bytes_per_line * ephyrBufferHeight(screen); + fakexa->exa->offScreenBase = priv->bytes_per_line * screen->height; + + /* Since we statically link against EXA, we shouldn't have to be smart about + * versioning. + */ + fakexa->exa->exa_major = 2; + fakexa->exa->exa_minor = 0; + + fakexa->exa->PrepareSolid = ephyrPrepareSolid; + fakexa->exa->Solid = ephyrSolid; + fakexa->exa->DoneSolid = ephyrDoneSolid; + + fakexa->exa->PrepareCopy = ephyrPrepareCopy; + fakexa->exa->Copy = ephyrCopy; + fakexa->exa->DoneCopy = ephyrDoneCopy; + + fakexa->exa->CheckComposite = ephyrCheckComposite; + fakexa->exa->PrepareComposite = ephyrPrepareComposite; + fakexa->exa->Composite = ephyrComposite; + fakexa->exa->DoneComposite = ephyrDoneComposite; + + fakexa->exa->DownloadFromScreen = ephyrDownloadFromScreen; + fakexa->exa->UploadToScreen = ephyrUploadToScreen; + + fakexa->exa->MarkSync = ephyrMarkSync; + fakexa->exa->WaitMarker = ephyrWaitMarker; + + fakexa->exa->PrepareAccess = ephyrPrepareAccess; + + fakexa->exa->pixmapOffsetAlign = EPHYR_OFFSET_ALIGN; + fakexa->exa->pixmapPitchAlign = EPHYR_PITCH_ALIGN; + + fakexa->exa->maxX = 1023; + fakexa->exa->maxY = 1023; + + fakexa->exa->flags = EXA_OFFSCREEN_PIXMAPS; + + success = exaDriverInit(pScreen, fakexa->exa); + if (success) { + ErrorF("Initialized fake EXA acceleration\n"); + scrpriv->fakexa = fakexa; + } else { + ErrorF("Failed to initialize EXA\n"); + free(fakexa->exa); + free(fakexa); + } + + return success; +} + +void +ephyrDrawEnable(ScreenPtr pScreen) +{ +} + +void +ephyrDrawDisable(ScreenPtr pScreen) +{ +} + +void +ephyrDrawFini(ScreenPtr pScreen) +{ +} + +/** + * exaDDXDriverInit is required by the top-level EXA module, and is used by + * the xorg DDX to hook in its EnableDisableFB wrapper. We don't need it, since + * we won't be enabling/disabling the FB. + */ +void +exaDDXDriverInit(ScreenPtr pScreen) +{ + ExaScreenPriv(pScreen); + + pExaScr->migration = ExaMigrationSmart; + pExaScr->checkDirtyCorrectness = TRUE; +} diff --git a/xorg-server/hw/kdrive/ephyr/ephyrinit.c b/xorg-server/hw/kdrive/ephyr/ephyrinit.c index 2deb7b81d..b674bb8d0 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrinit.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrinit.c @@ -2,7 +2,7 @@ * Xephyr - A kdrive X server thats runs in a host X window. * Authored by Matthew Allum <mallum@o-hand.com> * - * Copyright © 2004 Nokia + * Copyright © 2004 Nokia * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -97,6 +97,7 @@ InitInput (int argc, char **argv) void CloseInput (void) { + KdCloseInput(); } #ifdef DDXBEFORERESET diff --git a/xorg-server/hw/kdrive/ephyr/hostx.c b/xorg-server/hw/kdrive/ephyr/hostx.c index 648368124..4caf4516d 100644 --- a/xorg-server/hw/kdrive/ephyr/hostx.c +++ b/xorg-server/hw/kdrive/ephyr/hostx.c @@ -1,1447 +1,1447 @@ -/*
- * Xephyr - A kdrive X server thats runs in a host X window.
- * Authored by Matthew Allum <mallum@o-hand.com>
- *
- * Copyright © 2004 Nokia
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Nokia not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Nokia makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-
-/*
- * including some server headers (like kdrive-config.h)
- * might define the macro _XSERVER64
- * on 64 bits machines. That macro must _NOT_ be defined for Xlib
- * client code, otherwise bad things happen.
- * So let's undef that macro if necessary.
- */
-#ifdef _XSERVER64
-#undef _XSERVER64
-#endif
-
-
-#include "hostx.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h> /* for memset */
-#include <time.h>
-
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/time.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#include <X11/extensions/XShm.h>
-#include <X11/extensions/shape.h>
-#ifdef XF86DRI
-#include <GL/glx.h>
-#endif /* XF86DRI */
-#include "ephyrlog.h"
-
-#ifdef XF86DRI
-extern Bool XF86DRIQueryExtension (Display *dpy,
- int *event_basep,
- int *error_basep);
-#endif
-
-/*
- * All xlib calls go here, which gets built as its own .a .
- * Mixing kdrive and xlib headers causes all sorts of types
- * to get clobbered.
- */
-
-struct EphyrHostScreen
-{
- Window win;
- Window win_pre_existing; /* Set via -parent option like xnest */
- Window peer_win; /* Used for GL; should be at most one */
- XImage *ximg;
- int win_width, win_height;
- int server_depth;
- unsigned char *fb_data; /* only used when host bpp != server bpp */
- XShmSegmentInfo shminfo;
-
- void *info; /* Pointer to the screen this is associated with */
- int mynum; /* Screen number */
-};
-
-struct EphyrHostXVars
-{
- char *server_dpy_name;
- Display *dpy;
- int screen;
- Visual *visual;
- Window winroot;
- GC gc;
- int depth;
- Bool use_host_cursor;
- Bool use_fullscreen;
- Bool have_shm;
-
- int n_screens;
- struct EphyrHostScreen *screens;
-
- long damage_debug_msec;
-
- unsigned long cmap[256];
-};
-
-/* memset ( missing> ) instead of below */
-/*static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};*/
-static EphyrHostXVars HostX;
-
-static int HostXWantDamageDebug = 0;
-
-extern EphyrKeySyms ephyrKeySyms;
-
-extern int monitorResolution;
-
-char *ephyrResName = NULL;
-int ephyrResNameFromCmd = 0;
-char *ephyrTitle = NULL;
-
-static void
-hostx_set_fullscreen_hint(void);
-
-/* X Error traps */
-
-static int trapped_error_code = 0;
-static int (*old_error_handler) (Display *d, XErrorEvent *e);
-
-#define host_depth_matches_server(_vars) (HostX.depth == (_vars)->server_depth)
-
-static struct EphyrHostScreen *
-host_screen_from_screen_info (EphyrScreenInfo *screen)
-{
- int i;
-
- for (i = 0 ; i < HostX.n_screens ; i++)
- {
- if ( HostX.screens[i].info == screen)
- {
- return &HostX.screens[i];
- }
- }
- return NULL;
-}
-
-static int
-error_handler(Display *display,
- XErrorEvent *error)
-{
- trapped_error_code = error->error_code;
- return 0;
-}
-
-static void
-hostx_errors_trap(void)
-{
- trapped_error_code = 0;
- old_error_handler = XSetErrorHandler(error_handler);
-}
-
-static int
-hostx_errors_untrap(void)
-{
- XSetErrorHandler(old_error_handler);
- return trapped_error_code;
-}
-
-int
-hostx_want_screen_size (EphyrScreenInfo screen, int *width, int *height )
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (host_screen &&
- (host_screen->win_pre_existing != None ||
- HostX.use_fullscreen == True))
- {
- *width = host_screen->win_width;
- *height = host_screen->win_height;
- return 1;
- }
-
- return 0;
-}
-
-void
-hostx_add_screen (EphyrScreenInfo screen,
- unsigned long win_id,
- int screen_num)
-{
- int index = HostX.n_screens;
-
- HostX.n_screens += 1;
- HostX.screens = realloc (HostX.screens,
- HostX.n_screens * sizeof(struct EphyrHostScreen));
- memset (&HostX.screens[index], 0, sizeof (struct EphyrHostScreen));
-
- HostX.screens[index].info = screen;
- HostX.screens[index].win_pre_existing = win_id;
-}
-
-
-void
-hostx_set_display_name (char *name)
-{
- HostX.server_dpy_name = strdup (name);
-}
-
-void
-hostx_set_screen_number(EphyrScreenInfo screen, int number)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
- if (host_screen) {
- host_screen->mynum = number;
- hostx_set_win_title (host_screen->info, "") ;
- }}
-
-void
-hostx_set_win_title (EphyrScreenInfo screen, char *extra_text)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (!host_screen)
- return;
-
- if (ephyrTitle) {
- XStoreName(HostX.dpy, host_screen->win, ephyrTitle);
- } else {
-#define BUF_LEN 256
- char buf[BUF_LEN+1];
-
- memset (buf, 0, BUF_LEN+1) ;
- snprintf (buf, BUF_LEN, "Xephyr on %s.%d %s",
- HostX.server_dpy_name,
- host_screen->mynum,
- (extra_text != NULL) ? extra_text : "");
-
- XStoreName (HostX.dpy, host_screen->win, buf);
- }
-}
-
-int
-hostx_want_host_cursor (void)
-{
- return HostX.use_host_cursor;
-}
-
-void
-hostx_use_host_cursor (void)
-{
- HostX.use_host_cursor = True;
-}
-
-int
-hostx_want_preexisting_window (EphyrScreenInfo screen)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (host_screen && host_screen->win_pre_existing)
- {
- return 1;
- }
- else
- {
- return 0;
- }
-}
-
-void
-hostx_use_fullscreen (void)
-{
- HostX.use_fullscreen = True;
-}
-
-int
-hostx_want_fullscreen (void)
-{
- return HostX.use_fullscreen;
-}
-
-static void
-hostx_set_fullscreen_hint (void)
-{
- Atom atom_WINDOW_STATE, atom_WINDOW_STATE_FULLSCREEN;
- int index;
-
- atom_WINDOW_STATE
- = XInternAtom(HostX.dpy, "_NET_WM_STATE", False);
- atom_WINDOW_STATE_FULLSCREEN
- = XInternAtom(HostX.dpy, "_NET_WM_STATE_FULLSCREEN",False);
-
- for (index = 0 ; index < HostX.n_screens ; index++)
- {
- XChangeProperty (HostX.dpy, HostX.screens[index].win,
- atom_WINDOW_STATE, XA_ATOM, 32,
- PropModeReplace,
- (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1);
- }
-}
-
-
-static void
-hostx_toggle_damage_debug (void)
-{
- HostXWantDamageDebug ^= 1;
-}
-
-void
-hostx_handle_signal (int signum)
-{
- hostx_toggle_damage_debug();
- EPHYR_DBG ("Signal caught. Damage Debug:%i\n",
- HostXWantDamageDebug);
-}
-
-void
-hostx_use_resname (char *name, int fromcmd)
-{
- ephyrResName = name;
- ephyrResNameFromCmd = fromcmd;
-}
-
-void
-hostx_set_title (char *title)
-{
- ephyrTitle = title;
-}
-
-int
-hostx_init (void)
-{
- XSetWindowAttributes attr;
- Cursor empty_cursor;
- Pixmap cursor_pxm;
- XColor col;
- int index;
- char *tmpstr;
- XClassHint *class_hint;
-
- attr.event_mask =
- ButtonPressMask
- |ButtonReleaseMask
- |PointerMotionMask
- |KeyPressMask
- |KeyReleaseMask
- |ExposureMask;
-
- EPHYR_DBG("mark");
-
- if ((HostX.dpy = XOpenDisplay(getenv("DISPLAY"))) == NULL)
- {
- fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n");
- exit(1);
- }
-
- HostX.screen = DefaultScreen(HostX.dpy);
- HostX.winroot = RootWindow(HostX.dpy, HostX.screen);
- HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL);
- HostX.depth = DefaultDepth(HostX.dpy, HostX.screen);
- HostX.visual = DefaultVisual(HostX.dpy, HostX.screen);
-
- class_hint = XAllocClassHint();
-
- for (index = 0 ; index < HostX.n_screens ; index++)
- {
- struct EphyrHostScreen *host_screen = &HostX.screens[index];
-
- host_screen->server_depth = HostX.depth;
- if (host_screen->win_pre_existing != None)
- {
- Status result;
- XWindowAttributes prewin_attr;
-
- /* Get screen size from existing window */
-
- hostx_errors_trap();
-
- result = XGetWindowAttributes (HostX.dpy,
- host_screen->win_pre_existing,
- &prewin_attr);
-
-
- if (hostx_errors_untrap() || !result)
- {
- fprintf (stderr, "\nXephyr -parent window' does not exist!\n");
- exit (1);
- }
-
- host_screen->win_width = prewin_attr.width;
- host_screen->win_height = prewin_attr.height;
-
- host_screen->win = XCreateWindow (HostX.dpy,
- host_screen->win_pre_existing,
- 0,0,
- host_screen->win_width,
- host_screen->win_height,
- 0,
- CopyFromParent,
- CopyFromParent,
- CopyFromParent,
- CWEventMask,
- &attr);
- }
- else
- {
- host_screen->win = XCreateWindow (HostX.dpy,
- HostX.winroot,
- 0,0,100,100, /* will resize */
- 0,
- CopyFromParent,
- CopyFromParent,
- CopyFromParent,
- CWEventMask,
- &attr);
-
- hostx_set_win_title (host_screen->info,
- "(ctrl+shift grabs mouse and keyboard)");
-
- if (HostX.use_fullscreen)
- {
- host_screen->win_width = DisplayWidth(HostX.dpy, HostX.screen);
- host_screen->win_height = DisplayHeight(HostX.dpy, HostX.screen);
-
- hostx_set_fullscreen_hint();
- }
-
- if (class_hint)
- {
- tmpstr = getenv("RESOURCE_NAME");
- if (tmpstr && (!ephyrResNameFromCmd))
- ephyrResName = tmpstr;
- class_hint->res_name = ephyrResName;
- class_hint->res_class = "Xephyr";
- XSetClassHint(hostx_get_display(), host_screen->win, class_hint);
-
- }
-
- }
- }
-
- if (class_hint)
- XFree(class_hint);
-
- XParseColor (HostX.dpy, DefaultColormap (HostX.dpy,HostX.screen),
- "red", &col);
- XAllocColor (HostX.dpy, DefaultColormap (HostX.dpy, HostX.screen),
- &col);
- XSetForeground (HostX.dpy, HostX.gc, col.pixel);
-
- if (!hostx_want_host_cursor ())
- {
- /* Ditch the cursor, we provide our 'own' */
- cursor_pxm = XCreatePixmap (HostX.dpy, HostX.winroot, 1, 1, 1);
- memset (&col, 0, sizeof (col));
- empty_cursor = XCreatePixmapCursor (HostX.dpy,
- cursor_pxm, cursor_pxm,
- &col, &col, 1, 1);
- for ( index = 0 ; index < HostX.n_screens ; index++ )
- {
- XDefineCursor (HostX.dpy,
- HostX.screens[index].win,
- empty_cursor);
- }
- XFreePixmap (HostX.dpy, cursor_pxm);
- }
-
- for (index = 0 ; index < HostX.n_screens ; index++)
- {
- HostX.screens[index].ximg = NULL;
- }
- /* Try to get share memory ximages for a little bit more speed */
-
- if (!XShmQueryExtension(HostX.dpy) || getenv("XEPHYR_NO_SHM"))
- {
- fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
- HostX.have_shm = False;
- }
- else
- {
- /* Really really check we have shm - better way ?*/
- XShmSegmentInfo shminfo;
-
- HostX.have_shm = True;
-
- shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777);
- shminfo.shmaddr=shmat(shminfo.shmid,0,0);
- shminfo.readOnly=True;
-
- hostx_errors_trap();
-
- XShmAttach(HostX.dpy, &shminfo);
- XSync(HostX.dpy, False);
-
- if (hostx_errors_untrap())
- {
- fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
- HostX.have_shm = False;
- }
-
- shmdt(shminfo.shmaddr);
- shmctl(shminfo.shmid, IPC_RMID, 0);
-}
-
- XFlush(HostX.dpy);
-
- /* Setup the pause time between paints when debugging updates */
-
- HostX.damage_debug_msec = 20000; /* 1/50 th of a second */
-
- if (getenv ("XEPHYR_PAUSE"))
- {
- HostX.damage_debug_msec = strtol (getenv ("XEPHYR_PAUSE"), NULL, 0);
- EPHYR_DBG ("pause is %li\n", HostX.damage_debug_msec);
- }
-
- return 1;
-}
-
-int
-hostx_get_depth (void)
-{
- return HostX.depth;
-}
-
-int
-hostx_get_server_depth (EphyrScreenInfo screen)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- return host_screen ? host_screen->server_depth : 0;
-}
-
-void
-hostx_set_server_depth (EphyrScreenInfo screen, int depth)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (host_screen)
- host_screen->server_depth = depth;
-}
-
-int
-hostx_get_bpp (EphyrScreenInfo screen)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (!host_screen)
- return 0;
-
- if (host_depth_matches_server (host_screen))
- return HostX.visual->bits_per_rgb;
- else
- return host_screen->server_depth; /*XXX correct ?*/
-}
-
-void
-hostx_get_visual_masks (EphyrScreenInfo screen,
- CARD32 *rmsk,
- CARD32 *gmsk,
- CARD32 *bmsk)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (!host_screen)
- return;
-
- if (host_depth_matches_server(host_screen))
- {
- *rmsk = HostX.visual->red_mask;
- *gmsk = HostX.visual->green_mask;
- *bmsk = HostX.visual->blue_mask;
- }
- else if (host_screen->server_depth == 16)
- {
- /* Assume 16bpp 565 */
- *rmsk = 0xf800;
- *gmsk = 0x07e0;
- *bmsk = 0x001f;
- }
- else
- {
- *rmsk = 0x0;
- *gmsk = 0x0;
- *bmsk = 0x0;
- }
-}
-
-static int
-hostx_calculate_color_shift(unsigned long mask)
-{
- int shift = 1;
- /* count # of bits in mask */
- while ((mask = (mask >> 1))) shift++;
- /* cmap entry is an unsigned char so adjust it by size of that */
- shift = shift - sizeof(unsigned char) * 8;
- if (shift < 0) shift = 0;
- return shift;
-}
-
-void
-hostx_set_cmap_entry(unsigned char idx,
- unsigned char r,
- unsigned char g,
- unsigned char b)
-{
-/* need to calculate the shifts for RGB because server could be BGR. */
-/* XXX Not sure if this is correct for 8 on 16, but this works for 8 on 24.*/
- static int rshift, bshift, gshift = 0;
- static int first_time = 1;
- if (first_time) {
- first_time = 0;
- rshift = hostx_calculate_color_shift(HostX.visual->red_mask);
- gshift = hostx_calculate_color_shift(HostX.visual->green_mask);
- bshift = hostx_calculate_color_shift(HostX.visual->blue_mask);
- }
- HostX.cmap[idx] = ((r << rshift) & HostX.visual->red_mask) |
- ((g << gshift) & HostX.visual->green_mask) |
- ((b << bshift) & HostX.visual->blue_mask);
-}
-
-/**
- * hostx_screen_init creates the XImage that will contain the front buffer of
- * the ephyr screen, and possibly offscreen memory.
- *
- * @param width width of the screen
- * @param height height of the screen
- * @param buffer_height height of the rectangle to be allocated.
- *
- * hostx_screen_init() creates an XImage, using MIT-SHM if it's available.
- * buffer_height can be used to create a larger offscreen buffer, which is used
- * by fakexa for storing offscreen pixmap data.
- */
-void*
-hostx_screen_init (EphyrScreenInfo screen,
- int width, int height,
- int buffer_height)
-{
- int bitmap_pad;
- Bool shm_success = False;
- XSizeHints *size_hints;
-
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
- if (!host_screen)
- {
- fprintf (stderr, "%s: Error in accessing hostx data\n", __func__ );
- exit(1);
- }
-
- EPHYR_DBG ("host_screen=%p wxh=%dx%d, buffer_height=%d",
- host_screen, width, height, buffer_height);
-
- if (host_screen->ximg != NULL)
- {
- /* Free up the image data if previously used
- * i.ie called by server reset
- */
-
- if (HostX.have_shm)
- {
- XShmDetach(HostX.dpy, &host_screen->shminfo);
- XDestroyImage (host_screen->ximg);
- shmdt(host_screen->shminfo.shmaddr);
- shmctl(host_screen->shminfo.shmid, IPC_RMID, 0);
- }
- else
- {
- free(host_screen->ximg->data);
- host_screen->ximg->data = NULL;
-
- XDestroyImage(host_screen->ximg);
- }
- }
-
- if (HostX.have_shm)
- {
- host_screen->ximg = XShmCreateImage (HostX.dpy, HostX.visual, HostX.depth,
- ZPixmap, NULL, &host_screen->shminfo,
- width, buffer_height );
-
- host_screen->shminfo.shmid =
- shmget(IPC_PRIVATE,
- host_screen->ximg->bytes_per_line * buffer_height,
- IPC_CREAT|0777);
- host_screen->ximg->data = shmat(host_screen->shminfo.shmid, 0, 0);
- host_screen->shminfo.shmaddr = host_screen->ximg->data;
-
- if (host_screen->ximg->data == (char *)-1)
- {
- EPHYR_DBG("Can't attach SHM Segment, falling back to plain XImages");
- HostX.have_shm = False;
- XDestroyImage(host_screen->ximg);
- shmctl(host_screen->shminfo.shmid, IPC_RMID, 0);
- }
- else
- {
- EPHYR_DBG("SHM segment attached %p", host_screen->shminfo.shmaddr);
- host_screen->shminfo.readOnly = False;
- XShmAttach(HostX.dpy, &host_screen->shminfo);
- shm_success = True;
- }
- }
-
- if (!shm_success)
- {
- bitmap_pad = ( HostX.depth > 16 )? 32 : (( HostX.depth > 8 )? 16 : 8 );
-
- EPHYR_DBG("Creating image %dx%d for screen host_screen=%p\n",
- width, buffer_height, host_screen );
- host_screen->ximg = XCreateImage (HostX.dpy,
- HostX.visual,
- HostX.depth,
- ZPixmap, 0, 0,
- width,
- buffer_height,
- bitmap_pad,
- 0);
-
- host_screen->ximg->data =
- malloc (host_screen->ximg->bytes_per_line * buffer_height);
- }
-
- XResizeWindow (HostX.dpy, host_screen->win, width, height);
-
- /* Ask the WM to keep our size static */
- size_hints = XAllocSizeHints();
- size_hints->max_width = size_hints->min_width = width;
- size_hints->max_height = size_hints->min_height = height;
- size_hints->flags = PMinSize|PMaxSize;
- XSetWMNormalHints(HostX.dpy, host_screen->win, size_hints);
- XFree(size_hints);
-
- XMapWindow(HostX.dpy, host_screen->win);
-
- XSync(HostX.dpy, False);
-
- host_screen->win_width = width;
- host_screen->win_height = height;
-
- if (host_depth_matches_server(host_screen))
- {
- EPHYR_DBG("Host matches server");
- return host_screen->ximg->data;
- }
- else
- {
- EPHYR_DBG("server bpp %i", host_screen->server_depth>>3);
- host_screen->fb_data = malloc(width*buffer_height*(host_screen->server_depth>>3));
- return host_screen->fb_data;
- }
-}
-
-static void hostx_paint_debug_rect (struct EphyrHostScreen *host_screen,
- int x, int y,
- int width, int height);
-
-void
-hostx_paint_rect (EphyrScreenInfo screen,
- int sx, int sy,
- int dx, int dy,
- int width, int height)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- EPHYR_DBG ("painting in screen %d\n", host_screen->mynum) ;
-
- /*
- * Copy the image data updated by the shadow layer
- * on to the window
- */
-
- if (HostXWantDamageDebug)
- {
- hostx_paint_debug_rect(host_screen, dx, dy, width, height);
- }
-
- /*
- * If the depth of the ephyr server is less than that of the host,
- * the kdrive fb does not point to the ximage data but to a buffer
- * ( fb_data ), we shift the various bits from this onto the XImage
- * so they match the host.
- *
- * Note, This code is pretty new ( and simple ) so may break on
- * endian issues, 32 bpp host etc.
- * Not sure if 8bpp case is right either.
- * ... and it will be slower than the matching depth case.
- */
-
- if (!host_depth_matches_server(host_screen))
- {
- int x,y,idx, bytes_per_pixel = (host_screen->server_depth>>3);
- unsigned char r,g,b;
- unsigned long host_pixel;
-
- EPHYR_DBG("Unmatched host depth host_screen=%p\n", host_screen);
- for (y=sy; y<sy+height; y++)
- for (x=sx; x<sx+width; x++)
- {
- idx = (host_screen->win_width*y*bytes_per_pixel)+(x*bytes_per_pixel);
-
- switch (host_screen->server_depth)
- {
- case 16:
- {
- unsigned short pixel = *(unsigned short*)(host_screen->fb_data+idx);
-
- r = ((pixel & 0xf800) >> 8);
- g = ((pixel & 0x07e0) >> 3);
- b = ((pixel & 0x001f) << 3);
-
- host_pixel = (r << 16) | (g << 8) | (b);
-
- XPutPixel(host_screen->ximg, x, y, host_pixel);
- break;
- }
- case 8:
- {
- unsigned char pixel = *(unsigned char*)(host_screen->fb_data+idx);
- XPutPixel(host_screen->ximg, x, y, HostX.cmap[pixel]);
- break;
- }
- default:
- break;
- }
- }
- }
-
- if (HostX.have_shm)
- {
- XShmPutImage (HostX.dpy, host_screen->win,
- HostX.gc, host_screen->ximg,
- sx, sy, dx, dy, width, height, False);
- }
- else
- {
- XPutImage (HostX.dpy, host_screen->win, HostX.gc, host_screen->ximg,
- sx, sy, dx, dy, width, height);
- }
-
- XSync (HostX.dpy, False);
-}
-
-static void
-hostx_paint_debug_rect (struct EphyrHostScreen *host_screen,
- int x, int y,
- int width, int height)
-{
- struct timespec tspec;
-
- tspec.tv_sec = HostX.damage_debug_msec / (1000000);
- tspec.tv_nsec = (HostX.damage_debug_msec % 1000000) * 1000;
-
- EPHYR_DBG("msec: %li tv_sec %li, tv_msec %li",
- HostX.damage_debug_msec, tspec.tv_sec, tspec.tv_nsec);
-
- /* fprintf(stderr, "Xephyr updating: %i+%i %ix%i\n", x, y, width, height); */
-
- XFillRectangle (HostX.dpy, host_screen->win, HostX.gc, x, y, width,height);
- XSync (HostX.dpy, False);
-
- /* nanosleep seems to work better than usleep for me... */
- nanosleep(&tspec, NULL);
-}
-
-void
-hostx_load_keymap(void)
-{
- XID *keymap;
- int host_width, min_keycode, max_keycode, width;
- int i,j;
-
- XDisplayKeycodes (HostX.dpy, &min_keycode, &max_keycode);
-
- EPHYR_DBG ("min: %d, max: %d", min_keycode, max_keycode);
-
- keymap = XGetKeyboardMapping (HostX.dpy,
- min_keycode,
- max_keycode - min_keycode + 1,
- &host_width);
-
- /* Try and copy the hosts keymap into our keymap to avoid loads
- * of messing around.
- *
- * kdrive cannot can have more than 4 keysyms per keycode
- * so we only copy at most the first 4 ( xorg has 6 per keycode, XVNC 2 )
- */
- width = (host_width > 4) ? 4 : host_width;
-
- ephyrKeySyms.map = (CARD32 *)calloc(sizeof(CARD32),
- (max_keycode - min_keycode + 1) *
- width);
- if (!ephyrKeySyms.map)
- return;
-
- for (i=0; i<(max_keycode - min_keycode+1); i++)
- for (j=0; j<width; j++)
- ephyrKeySyms.map[(i*width)+j] = (CARD32) keymap[(i*host_width) + j];
-
- EPHYR_DBG("keymap width, host:%d kdrive:%d", host_width, width);
-
- ephyrKeySyms.minKeyCode = min_keycode;
- ephyrKeySyms.maxKeyCode = max_keycode;
- ephyrKeySyms.mapWidth = width;
-
- XFree(keymap);
-}
-
-static struct EphyrHostScreen *
-host_screen_from_window (Window w)
-{
- int index = 0;
- struct EphyrHostScreen *result = NULL;
-
- for (index = 0 ; index < HostX.n_screens ; index++)
- {
- if (HostX.screens[index].win == w || HostX.screens[index].peer_win == w)
- {
- result = &HostX.screens[index];
- goto out;
- }
- }
-
-out:
- return result;
-}
-
-int
-hostx_get_event(EphyrHostXEvent *ev)
-{
- XEvent xev;
- static int grabbed_screen = -1;
-
- if (XPending(HostX.dpy))
- {
- XNextEvent(HostX.dpy, &xev);
-
- switch (xev.type)
- {
- case Expose:
- /* Not so great event compression, but works ok */
- while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window,
- Expose, &xev));
- {
- struct EphyrHostScreen *host_screen =
- host_screen_from_window (xev.xexpose.window);
- if (host_screen)
- {
- hostx_paint_rect (host_screen->info, 0, 0, 0, 0,
- host_screen->win_width,
- host_screen->win_height);
- }
- else
- {
- EPHYR_LOG_ERROR ("failed to get host screen\n");
- ev->type = EPHYR_EV_EXPOSE;
- ev->data.expose.window = xev.xexpose.window;
- return 1;
- }
- }
- return 0;
-
- case MotionNotify:
- {
- struct EphyrHostScreen *host_screen =
- host_screen_from_window (xev.xmotion.window);
-
- ev->type = EPHYR_EV_MOUSE_MOTION;
- ev->data.mouse_motion.x = xev.xmotion.x;
- ev->data.mouse_motion.y = xev.xmotion.y;
- ev->data.mouse_motion.window = xev.xmotion.window;
- ev->data.mouse_motion.screen = (host_screen ? host_screen->mynum : -1);
- }
- return 1;
-
- case ButtonPress:
- ev->type = EPHYR_EV_MOUSE_PRESS;
- ev->key_state = xev.xkey.state;
- /*
- * This is a bit hacky. will break for button 5 ( defined as 0x10 )
- * Check KD_BUTTON defines in kdrive.h
- */
- ev->data.mouse_down.button_num = 1<<(xev.xbutton.button-1);
- return 1;
-
- case ButtonRelease:
- ev->type = EPHYR_EV_MOUSE_RELEASE;
- ev->key_state = xev.xkey.state;
- ev->data.mouse_up.button_num = 1<<(xev.xbutton.button-1);
- return 1;
-
- case KeyPress:
- {
- ev->type = EPHYR_EV_KEY_PRESS;
- ev->key_state = xev.xkey.state;
- ev->data.key_down.scancode = xev.xkey.keycode;
- return 1;
- }
- case KeyRelease:
-
- if ((XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) == XK_Shift_L
- || XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) == XK_Shift_R)
- && (xev.xkey.state & ControlMask))
- {
- struct EphyrHostScreen *host_screen =
- host_screen_from_window (xev.xexpose.window);
-
- if (grabbed_screen != -1)
- {
- XUngrabKeyboard (HostX.dpy, CurrentTime);
- XUngrabPointer (HostX.dpy, CurrentTime);
- grabbed_screen = -1;
- hostx_set_win_title (host_screen->info,
- "(ctrl+shift grabs mouse and keyboard)");
- }
- else
- {
- /* Attempt grab */
- if (XGrabKeyboard (HostX.dpy, host_screen->win, True,
- GrabModeAsync,
- GrabModeAsync,
- CurrentTime) == 0)
- {
- if (XGrabPointer (HostX.dpy, host_screen->win, True,
- NoEventMask,
- GrabModeAsync,
- GrabModeAsync,
- host_screen->win, None, CurrentTime) == 0)
- {
- grabbed_screen = host_screen->mynum;
- hostx_set_win_title
- (host_screen->info,
- "(ctrl+shift releases mouse and keyboard)");
- }
- else /* Failed pointer grabm ungrab keyboard */
- XUngrabKeyboard (HostX.dpy, CurrentTime);
- }
- }
- }
-
- /* Still send the release event even if above has happened
- * server will get confused with just an up event.
- * Maybe it would be better to just block shift+ctrls getting to
- * kdrive all togeather.
- */
- ev->type = EPHYR_EV_KEY_RELEASE;
- ev->key_state = xev.xkey.state;
- ev->data.key_up.scancode = xev.xkey.keycode;
- return 1;
-
- default:
- break;
-
- }
- }
- return 0;
-}
-
-void*
-hostx_get_display(void)
-{
- return HostX.dpy ;
-}
-
-int
-hostx_get_window (int a_screen_number)
-{
- if (a_screen_number < 0 || a_screen_number >= HostX.n_screens) {
- EPHYR_LOG_ERROR ("bad screen number:%d\n", a_screen_number) ;
- return 0;
- }
- return HostX.screens[a_screen_number].win ;
-}
-
-int
-hostx_get_window_attributes (int a_window, EphyrHostWindowAttributes *a_attrs)
-{
- XWindowAttributes attrs ;
-
- memset (&attrs, 0, sizeof (attrs)) ;
-
- if (!XGetWindowAttributes (hostx_get_display (),
- a_window,
- &attrs)) {
- return FALSE ;
- }
- a_attrs->x = attrs.x ;
- a_attrs->y = attrs.y ;
- a_attrs->width = attrs.width ;
- a_attrs->height = attrs.height ;
- if (attrs.visual)
- a_attrs->visualid = attrs.visual->visualid ;
- return TRUE ;
-}
-
-int
-hostx_get_extension_info (const char *a_ext_name,
- int *a_major_opcode,
- int *a_first_event,
- int *a_first_error)
-{
- if (!a_ext_name || !a_major_opcode || !a_first_event || !a_first_error)
- return 0 ;
- if (!XQueryExtension (HostX.dpy,
- a_ext_name,
- a_major_opcode,
- a_first_event,
- a_first_error))
- {
- return 0 ;
- }
- return 1 ;
-}
-
-int
-hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals,
- int *a_num_entries)
-{
- Display *dpy=hostx_get_display () ;
- Bool is_ok=False ;
- XVisualInfo templ, *visuals=NULL;
- EphyrHostVisualInfo *host_visuals=NULL ;
- int nb_items=0, i=0;
-
- EPHYR_RETURN_VAL_IF_FAIL (a_visuals && a_num_entries && dpy,
- False) ;
- EPHYR_LOG ("enter\n") ;
- memset (&templ, 0, sizeof (templ)) ;
- visuals = XGetVisualInfo (dpy, VisualNoMask, &templ, &nb_items) ;
- if (!visuals) {
- EPHYR_LOG_ERROR ("host does not advertise any visual\n") ;
- goto out ;
- }
- EPHYR_LOG ("host advertises %d visuals\n", nb_items) ;
- host_visuals = calloc (nb_items, sizeof (EphyrHostVisualInfo)) ;
- for (i=0; i<nb_items; i++) {
- host_visuals[i].visualid = visuals[i].visualid ;
- host_visuals[i].screen = visuals[i].screen ;
- host_visuals[i].depth = visuals[i].depth ;
- host_visuals[i].class = visuals[i].class ;
- host_visuals[i].red_mask = visuals[i].red_mask ;
- host_visuals[i].green_mask = visuals[i].green_mask ;
- host_visuals[i].blue_mask = visuals[i].blue_mask ;
- host_visuals[i].colormap_size = visuals[i].colormap_size ;
- host_visuals[i].bits_per_rgb = visuals[i].bits_per_rgb ;
- }
- *a_visuals = host_visuals ;
- *a_num_entries = nb_items;
- host_visuals=NULL;
-
- is_ok = TRUE;
-out:
- if (visuals) {
- XFree (visuals) ;
- visuals = NULL;
- }
- free(host_visuals);
- host_visuals = NULL;
- EPHYR_LOG ("leave\n") ;
- return is_ok ;
-
-}
-
-int
-hostx_create_window (int a_screen_number,
- EphyrBox *a_geometry,
- int a_visual_id,
- int *a_host_peer /*out parameter*/)
-{
- Bool is_ok=FALSE ;
- Display *dpy=hostx_get_display () ;
- XVisualInfo *visual_info=NULL, visual_info_templ;
- int visual_mask=VisualIDMask ;
- Window win=None ;
- int nb_visuals=0, winmask=0;
- XSetWindowAttributes attrs;
-
- EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geometry, FALSE) ;
-
- EPHYR_LOG ("enter\n") ;
-
- /*get visual*/
- memset (&visual_info, 0, sizeof (visual_info)) ;
- visual_info_templ.visualid = a_visual_id ;
- visual_info = XGetVisualInfo (dpy, visual_mask,
- &visual_info_templ,
- &nb_visuals) ;
- if (!visual_info) {
- EPHYR_LOG_ERROR ("argh, could not find a remote visual with id:%d\n",
- a_visual_id) ;
- goto out ;
- }
- memset (&attrs, 0, sizeof (attrs)) ;
- attrs.colormap = XCreateColormap (dpy,
- RootWindow (dpy,
- visual_info->screen),
- visual_info->visual,
- AllocNone) ;
- attrs.event_mask = ButtonPressMask
- |ButtonReleaseMask
- |PointerMotionMask
- |KeyPressMask
- |KeyReleaseMask
- |ExposureMask;
- winmask = CWColormap|CWEventMask;
-
- win = XCreateWindow (dpy, hostx_get_window (a_screen_number),
- a_geometry->x, a_geometry->y,
- a_geometry->width, a_geometry->height, 0,
- visual_info->depth, CopyFromParent,
- visual_info->visual, winmask, &attrs) ;
- if (win == None) {
- EPHYR_LOG_ERROR ("failed to create peer window\n") ;
- goto out ;
- }
- if (HostX.screens[a_screen_number].peer_win == None) {
- HostX.screens[a_screen_number].peer_win = win;
- } else {
- EPHYR_LOG_ERROR ("multiple peer windows created for same screen\n") ;
- }
- XFlush (dpy) ;
- XMapWindow (dpy, win) ;
- *a_host_peer = win ;
- is_ok = TRUE ;
-out:
- EPHYR_LOG ("leave\n") ;
- return is_ok ;
-}
-
-int
-hostx_destroy_window (int a_win)
-{
- Display *dpy=hostx_get_display () ;
-
- EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ;
- XDestroyWindow (dpy, a_win) ;
- XFlush (dpy) ;
- return TRUE ;
-}
-
-int
-hostx_set_window_geometry (int a_win, EphyrBox *a_geo)
-{
- Display *dpy=hostx_get_display ();
-
- EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geo, FALSE) ;
-
- EPHYR_LOG ("enter. x,y,w,h:(%d,%d,%d,%d)\n",
- a_geo->x, a_geo->y,
- a_geo->width, a_geo->height) ;
-
- XMoveWindow (dpy, a_win, a_geo->x, a_geo->y) ;
- XResizeWindow (dpy, a_win, a_geo->width, a_geo->height) ;
- EPHYR_LOG ("leave\n") ;
- return TRUE;
-}
-
-int
-hostx_set_window_bounding_rectangles (int a_window,
- EphyrRect *a_rects,
- int a_num_rects)
-{
- Bool is_ok=FALSE;
- Display *dpy=hostx_get_display () ;
- int i=0 ;
- XRectangle *rects=NULL ;
-
- EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ;
-
- EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ;
-
- rects = calloc (a_num_rects, sizeof (XRectangle)) ;
- for (i=0; i<a_num_rects; i++) {
- rects[i].x = a_rects[i].x1 ;
- rects[i].y = a_rects[i].y1 ;
- rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1);
- rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ;
- EPHYR_LOG ("borders clipped to rect[x:%d,y:%d,w:%d,h:%d]\n",
- rects[i].x, rects[i].y,
- rects[i].width, rects[i].height) ;
- }
- /*this aways returns 1*/
- XShapeCombineRectangles (dpy, a_window, ShapeBounding, 0, 0,
- rects, a_num_rects, ShapeSet, YXBanded) ;
- is_ok = TRUE ;
-
- free(rects);
- rects = NULL;
- EPHYR_LOG ("leave\n") ;
- return is_ok;
-}
-
-int
-hostx_set_window_clipping_rectangles (int a_window,
- EphyrRect *a_rects,
- int a_num_rects)
-{
- Bool is_ok=FALSE;
- Display *dpy=hostx_get_display () ;
- int i=0 ;
- XRectangle *rects=NULL ;
-
- EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ;
-
- EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ;
-
- rects = calloc (a_num_rects, sizeof (XRectangle)) ;
- for (i=0; i<a_num_rects; i++) {
- rects[i].x = a_rects[i].x1 ;
- rects[i].y = a_rects[i].y1 ;
- rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1);
- rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ;
- EPHYR_LOG ("clipped to rect[x:%d,y:%d,w:%d,h:%d]\n",
- rects[i].x, rects[i].y,
- rects[i].width, rects[i].height) ;
- }
- /*this aways returns 1*/
- XShapeCombineRectangles (dpy, a_window, ShapeClip, 0, 0,
- rects, a_num_rects, ShapeSet, YXBanded) ;
- is_ok = TRUE ;
-
- free(rects);
- rects = NULL;
- EPHYR_LOG ("leave\n") ;
- return is_ok;
-}
-
-int
-hostx_has_xshape (void)
-{
- int event_base=0, error_base=0 ;
- Display *dpy=hostx_get_display () ;
- if (!XShapeQueryExtension (dpy,
- &event_base,
- &error_base)) {
- return FALSE ;
- }
- return TRUE;
-}
-
-#ifdef XF86DRI
-typedef struct {
- int is_valid ;
- int local_id ;
- int remote_id ;
-} ResourcePair ;
-
-#define RESOURCE_PEERS_SIZE 1024*10
-static ResourcePair resource_peers[RESOURCE_PEERS_SIZE] ;
-
-
-int
-hostx_allocate_resource_id_peer (int a_local_resource_id,
- int *a_remote_resource_id)
-{
- int i=0 ;
- ResourcePair *peer=NULL ;
- Display *dpy=hostx_get_display ();
-
- /*
- * first make sure a resource peer
- * does not exist already for
- * a_local_resource_id
- */
- for (i=0; i<RESOURCE_PEERS_SIZE; i++) {
- if (resource_peers[i].is_valid
- && resource_peers[i].local_id == a_local_resource_id) {
- peer = &resource_peers[i] ;
- break ;
- }
- }
- /*
- * find one free peer entry, an feed it with
- */
- if (!peer) {
- for (i=0; i<RESOURCE_PEERS_SIZE; i++) {
- if (!resource_peers[i].is_valid) {
- peer = &resource_peers[i] ;
- break ;
- }
- }
- if (peer) {
- peer->remote_id = XAllocID (dpy);
- peer->local_id = a_local_resource_id ;
- peer->is_valid = TRUE ;
- }
- }
- if (peer) {
- *a_remote_resource_id = peer->remote_id ;
- return TRUE ;
- }
- return FALSE ;
-}
-
-int
-hostx_get_resource_id_peer (int a_local_resource_id,
- int *a_remote_resource_id)
-{
- int i=0 ;
- ResourcePair *peer=NULL ;
- for (i=0; i<RESOURCE_PEERS_SIZE; i++) {
- if (resource_peers[i].is_valid
- && resource_peers[i].local_id == a_local_resource_id) {
- peer = &resource_peers[i] ;
- break ;
- }
- }
- if (peer) {
- *a_remote_resource_id = peer->remote_id ;
- return TRUE ;
- }
- return FALSE ;
-}
-
-int
-hostx_has_dri (void)
-{
- int event_base=0, error_base=0 ;
- Display *dpy=hostx_get_display () ;
-
- if (!dpy)
- return FALSE ;
-
- if (!XF86DRIQueryExtension (dpy,
- &event_base,
- &error_base)) {
- return FALSE ;
- }
- return TRUE ;
-}
-
-int
-hostx_has_glx (void)
-{
- Display *dpy=hostx_get_display () ;
- int event_base=0, error_base=0 ;
-
- if (!glXQueryExtension (dpy, &event_base, &error_base)) {
- return FALSE ;
- }
- return TRUE ;
-}
-
-#endif /* XF86DRI */
+/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum <mallum@o-hand.com> + * + * Copyright © 2004 Nokia + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Nokia not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Nokia makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif + +/* + * including some server headers (like kdrive-config.h) + * might define the macro _XSERVER64 + * on 64 bits machines. That macro must _NOT_ be defined for Xlib + * client code, otherwise bad things happen. + * So let's undef that macro if necessary. + */ +#ifdef _XSERVER64 +#undef _XSERVER64 +#endif + + +#include "hostx.h" + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> /* for memset */ +#include <time.h> + +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/time.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> +#include <X11/extensions/XShm.h> +#include <X11/extensions/shape.h> +#ifdef XF86DRI +#include <GL/glx.h> +#endif /* XF86DRI */ +#include "ephyrlog.h" + +#ifdef XF86DRI +extern Bool XF86DRIQueryExtension (Display *dpy, + int *event_basep, + int *error_basep); +#endif + +/* + * All xlib calls go here, which gets built as its own .a . + * Mixing kdrive and xlib headers causes all sorts of types + * to get clobbered. + */ + +struct EphyrHostScreen +{ + Window win; + Window win_pre_existing; /* Set via -parent option like xnest */ + Window peer_win; /* Used for GL; should be at most one */ + XImage *ximg; + int win_width, win_height; + int server_depth; + unsigned char *fb_data; /* only used when host bpp != server bpp */ + XShmSegmentInfo shminfo; + + void *info; /* Pointer to the screen this is associated with */ + int mynum; /* Screen number */ +}; + +struct EphyrHostXVars +{ + char *server_dpy_name; + Display *dpy; + int screen; + Visual *visual; + Window winroot; + GC gc; + int depth; + Bool use_host_cursor; + Bool use_fullscreen; + Bool have_shm; + + int n_screens; + struct EphyrHostScreen *screens; + + long damage_debug_msec; + + unsigned long cmap[256]; +}; + +/* memset ( missing> ) instead of below */ +/*static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};*/ +static EphyrHostXVars HostX; + +static int HostXWantDamageDebug = 0; + +extern EphyrKeySyms ephyrKeySyms; + +extern int monitorResolution; + +char *ephyrResName = NULL; +int ephyrResNameFromCmd = 0; +char *ephyrTitle = NULL; + +static void +hostx_set_fullscreen_hint(void); + +/* X Error traps */ + +static int trapped_error_code = 0; +static int (*old_error_handler) (Display *d, XErrorEvent *e); + +#define host_depth_matches_server(_vars) (HostX.depth == (_vars)->server_depth) + +static struct EphyrHostScreen * +host_screen_from_screen_info (EphyrScreenInfo *screen) +{ + int i; + + for (i = 0 ; i < HostX.n_screens ; i++) + { + if ( HostX.screens[i].info == screen) + { + return &HostX.screens[i]; + } + } + return NULL; +} + +static int +error_handler(Display *display, + XErrorEvent *error) +{ + trapped_error_code = error->error_code; + return 0; +} + +static void +hostx_errors_trap(void) +{ + trapped_error_code = 0; + old_error_handler = XSetErrorHandler(error_handler); +} + +static int +hostx_errors_untrap(void) +{ + XSetErrorHandler(old_error_handler); + return trapped_error_code; +} + +int +hostx_want_screen_size (EphyrScreenInfo screen, int *width, int *height ) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (host_screen && + (host_screen->win_pre_existing != None || + HostX.use_fullscreen == True)) + { + *width = host_screen->win_width; + *height = host_screen->win_height; + return 1; + } + + return 0; +} + +void +hostx_add_screen (EphyrScreenInfo screen, + unsigned long win_id, + int screen_num) +{ + int index = HostX.n_screens; + + HostX.n_screens += 1; + HostX.screens = realloc (HostX.screens, + HostX.n_screens * sizeof(struct EphyrHostScreen)); + memset (&HostX.screens[index], 0, sizeof (struct EphyrHostScreen)); + + HostX.screens[index].info = screen; + HostX.screens[index].win_pre_existing = win_id; +} + + +void +hostx_set_display_name (char *name) +{ + HostX.server_dpy_name = strdup (name); +} + +void +hostx_set_screen_number(EphyrScreenInfo screen, int number) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + if (host_screen) { + host_screen->mynum = number; + hostx_set_win_title (host_screen->info, "") ; + }} + +void +hostx_set_win_title (EphyrScreenInfo screen, char *extra_text) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (!host_screen) + return; + + if (ephyrTitle) { + XStoreName(HostX.dpy, host_screen->win, ephyrTitle); + } else { +#define BUF_LEN 256 + char buf[BUF_LEN+1]; + + memset (buf, 0, BUF_LEN+1) ; + snprintf (buf, BUF_LEN, "Xephyr on %s.%d %s", + HostX.server_dpy_name, + host_screen->mynum, + (extra_text != NULL) ? extra_text : ""); + + XStoreName (HostX.dpy, host_screen->win, buf); + } +} + +int +hostx_want_host_cursor (void) +{ + return HostX.use_host_cursor; +} + +void +hostx_use_host_cursor (void) +{ + HostX.use_host_cursor = True; +} + +int +hostx_want_preexisting_window (EphyrScreenInfo screen) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (host_screen && host_screen->win_pre_existing) + { + return 1; + } + else + { + return 0; + } +} + +void +hostx_use_fullscreen (void) +{ + HostX.use_fullscreen = True; +} + +int +hostx_want_fullscreen (void) +{ + return HostX.use_fullscreen; +} + +static void +hostx_set_fullscreen_hint (void) +{ + Atom atom_WINDOW_STATE, atom_WINDOW_STATE_FULLSCREEN; + int index; + + atom_WINDOW_STATE + = XInternAtom(HostX.dpy, "_NET_WM_STATE", False); + atom_WINDOW_STATE_FULLSCREEN + = XInternAtom(HostX.dpy, "_NET_WM_STATE_FULLSCREEN",False); + + for (index = 0 ; index < HostX.n_screens ; index++) + { + XChangeProperty (HostX.dpy, HostX.screens[index].win, + atom_WINDOW_STATE, XA_ATOM, 32, + PropModeReplace, + (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1); + } +} + + +static void +hostx_toggle_damage_debug (void) +{ + HostXWantDamageDebug ^= 1; +} + +void +hostx_handle_signal (int signum) +{ + hostx_toggle_damage_debug(); + EPHYR_DBG ("Signal caught. Damage Debug:%i\n", + HostXWantDamageDebug); +} + +void +hostx_use_resname (char *name, int fromcmd) +{ + ephyrResName = name; + ephyrResNameFromCmd = fromcmd; +} + +void +hostx_set_title (char *title) +{ + ephyrTitle = title; +} + +int +hostx_init (void) +{ + XSetWindowAttributes attr; + Cursor empty_cursor; + Pixmap cursor_pxm; + XColor col; + int index; + char *tmpstr; + XClassHint *class_hint; + + attr.event_mask = + ButtonPressMask + |ButtonReleaseMask + |PointerMotionMask + |KeyPressMask + |KeyReleaseMask + |ExposureMask; + + EPHYR_DBG("mark"); + + if ((HostX.dpy = XOpenDisplay(getenv("DISPLAY"))) == NULL) + { + fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n"); + exit(1); + } + + HostX.screen = DefaultScreen(HostX.dpy); + HostX.winroot = RootWindow(HostX.dpy, HostX.screen); + HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL); + HostX.depth = DefaultDepth(HostX.dpy, HostX.screen); + HostX.visual = DefaultVisual(HostX.dpy, HostX.screen); + + class_hint = XAllocClassHint(); + + for (index = 0 ; index < HostX.n_screens ; index++) + { + struct EphyrHostScreen *host_screen = &HostX.screens[index]; + + host_screen->server_depth = HostX.depth; + if (host_screen->win_pre_existing != None) + { + Status result; + XWindowAttributes prewin_attr; + + /* Get screen size from existing window */ + + hostx_errors_trap(); + + result = XGetWindowAttributes (HostX.dpy, + host_screen->win_pre_existing, + &prewin_attr); + + + if (hostx_errors_untrap() || !result) + { + fprintf (stderr, "\nXephyr -parent window' does not exist!\n"); + exit (1); + } + + host_screen->win_width = prewin_attr.width; + host_screen->win_height = prewin_attr.height; + + host_screen->win = XCreateWindow (HostX.dpy, + host_screen->win_pre_existing, + 0,0, + host_screen->win_width, + host_screen->win_height, + 0, + CopyFromParent, + CopyFromParent, + CopyFromParent, + CWEventMask, + &attr); + } + else + { + host_screen->win = XCreateWindow (HostX.dpy, + HostX.winroot, + 0,0,100,100, /* will resize */ + 0, + CopyFromParent, + CopyFromParent, + CopyFromParent, + CWEventMask, + &attr); + + hostx_set_win_title (host_screen->info, + "(ctrl+shift grabs mouse and keyboard)"); + + if (HostX.use_fullscreen) + { + host_screen->win_width = DisplayWidth(HostX.dpy, HostX.screen); + host_screen->win_height = DisplayHeight(HostX.dpy, HostX.screen); + + hostx_set_fullscreen_hint(); + } + + if (class_hint) + { + tmpstr = getenv("RESOURCE_NAME"); + if (tmpstr && (!ephyrResNameFromCmd)) + ephyrResName = tmpstr; + class_hint->res_name = ephyrResName; + class_hint->res_class = "Xephyr"; + XSetClassHint(hostx_get_display(), host_screen->win, class_hint); + + } + + } + } + + if (class_hint) + XFree(class_hint); + + XParseColor (HostX.dpy, DefaultColormap (HostX.dpy,HostX.screen), + "red", &col); + XAllocColor (HostX.dpy, DefaultColormap (HostX.dpy, HostX.screen), + &col); + XSetForeground (HostX.dpy, HostX.gc, col.pixel); + + if (!hostx_want_host_cursor ()) + { + /* Ditch the cursor, we provide our 'own' */ + cursor_pxm = XCreatePixmap (HostX.dpy, HostX.winroot, 1, 1, 1); + memset (&col, 0, sizeof (col)); + empty_cursor = XCreatePixmapCursor (HostX.dpy, + cursor_pxm, cursor_pxm, + &col, &col, 1, 1); + for ( index = 0 ; index < HostX.n_screens ; index++ ) + { + XDefineCursor (HostX.dpy, + HostX.screens[index].win, + empty_cursor); + } + XFreePixmap (HostX.dpy, cursor_pxm); + } + + for (index = 0 ; index < HostX.n_screens ; index++) + { + HostX.screens[index].ximg = NULL; + } + /* Try to get share memory ximages for a little bit more speed */ + + if (!XShmQueryExtension(HostX.dpy) || getenv("XEPHYR_NO_SHM")) + { + fprintf(stderr, "\nXephyr unable to use SHM XImages\n"); + HostX.have_shm = False; + } + else + { + /* Really really check we have shm - better way ?*/ + XShmSegmentInfo shminfo; + + HostX.have_shm = True; + + shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777); + shminfo.shmaddr=shmat(shminfo.shmid,0,0); + shminfo.readOnly=True; + + hostx_errors_trap(); + + XShmAttach(HostX.dpy, &shminfo); + XSync(HostX.dpy, False); + + if (hostx_errors_untrap()) + { + fprintf(stderr, "\nXephyr unable to use SHM XImages\n"); + HostX.have_shm = False; + } + + shmdt(shminfo.shmaddr); + shmctl(shminfo.shmid, IPC_RMID, 0); +} + + XFlush(HostX.dpy); + + /* Setup the pause time between paints when debugging updates */ + + HostX.damage_debug_msec = 20000; /* 1/50 th of a second */ + + if (getenv ("XEPHYR_PAUSE")) + { + HostX.damage_debug_msec = strtol (getenv ("XEPHYR_PAUSE"), NULL, 0); + EPHYR_DBG ("pause is %li\n", HostX.damage_debug_msec); + } + + return 1; +} + +int +hostx_get_depth (void) +{ + return HostX.depth; +} + +int +hostx_get_server_depth (EphyrScreenInfo screen) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + return host_screen ? host_screen->server_depth : 0; +} + +void +hostx_set_server_depth (EphyrScreenInfo screen, int depth) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (host_screen) + host_screen->server_depth = depth; +} + +int +hostx_get_bpp (EphyrScreenInfo screen) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (!host_screen) + return 0; + + if (host_depth_matches_server (host_screen)) + return HostX.visual->bits_per_rgb; + else + return host_screen->server_depth; /*XXX correct ?*/ +} + +void +hostx_get_visual_masks (EphyrScreenInfo screen, + CARD32 *rmsk, + CARD32 *gmsk, + CARD32 *bmsk) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (!host_screen) + return; + + if (host_depth_matches_server(host_screen)) + { + *rmsk = HostX.visual->red_mask; + *gmsk = HostX.visual->green_mask; + *bmsk = HostX.visual->blue_mask; + } + else if (host_screen->server_depth == 16) + { + /* Assume 16bpp 565 */ + *rmsk = 0xf800; + *gmsk = 0x07e0; + *bmsk = 0x001f; + } + else + { + *rmsk = 0x0; + *gmsk = 0x0; + *bmsk = 0x0; + } +} + +static int +hostx_calculate_color_shift(unsigned long mask) +{ + int shift = 1; + /* count # of bits in mask */ + while ((mask = (mask >> 1))) shift++; + /* cmap entry is an unsigned char so adjust it by size of that */ + shift = shift - sizeof(unsigned char) * 8; + if (shift < 0) shift = 0; + return shift; +} + +void +hostx_set_cmap_entry(unsigned char idx, + unsigned char r, + unsigned char g, + unsigned char b) +{ +/* need to calculate the shifts for RGB because server could be BGR. */ +/* XXX Not sure if this is correct for 8 on 16, but this works for 8 on 24.*/ + static int rshift, bshift, gshift = 0; + static int first_time = 1; + if (first_time) { + first_time = 0; + rshift = hostx_calculate_color_shift(HostX.visual->red_mask); + gshift = hostx_calculate_color_shift(HostX.visual->green_mask); + bshift = hostx_calculate_color_shift(HostX.visual->blue_mask); + } + HostX.cmap[idx] = ((r << rshift) & HostX.visual->red_mask) | + ((g << gshift) & HostX.visual->green_mask) | + ((b << bshift) & HostX.visual->blue_mask); +} + +/** + * hostx_screen_init creates the XImage that will contain the front buffer of + * the ephyr screen, and possibly offscreen memory. + * + * @param width width of the screen + * @param height height of the screen + * @param buffer_height height of the rectangle to be allocated. + * + * hostx_screen_init() creates an XImage, using MIT-SHM if it's available. + * buffer_height can be used to create a larger offscreen buffer, which is used + * by fakexa for storing offscreen pixmap data. + */ +void* +hostx_screen_init (EphyrScreenInfo screen, + int width, int height, + int buffer_height) +{ + int bitmap_pad; + Bool shm_success = False; + XSizeHints *size_hints; + + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + if (!host_screen) + { + fprintf (stderr, "%s: Error in accessing hostx data\n", __func__ ); + exit(1); + } + + EPHYR_DBG ("host_screen=%p wxh=%dx%d, buffer_height=%d", + host_screen, width, height, buffer_height); + + if (host_screen->ximg != NULL) + { + /* Free up the image data if previously used + * i.ie called by server reset + */ + + if (HostX.have_shm) + { + XShmDetach(HostX.dpy, &host_screen->shminfo); + XDestroyImage (host_screen->ximg); + shmdt(host_screen->shminfo.shmaddr); + shmctl(host_screen->shminfo.shmid, IPC_RMID, 0); + } + else + { + free(host_screen->ximg->data); + host_screen->ximg->data = NULL; + + XDestroyImage(host_screen->ximg); + } + } + + if (HostX.have_shm) + { + host_screen->ximg = XShmCreateImage (HostX.dpy, HostX.visual, HostX.depth, + ZPixmap, NULL, &host_screen->shminfo, + width, buffer_height ); + + host_screen->shminfo.shmid = + shmget(IPC_PRIVATE, + host_screen->ximg->bytes_per_line * buffer_height, + IPC_CREAT|0777); + host_screen->ximg->data = shmat(host_screen->shminfo.shmid, 0, 0); + host_screen->shminfo.shmaddr = host_screen->ximg->data; + + if (host_screen->ximg->data == (char *)-1) + { + EPHYR_DBG("Can't attach SHM Segment, falling back to plain XImages"); + HostX.have_shm = False; + XDestroyImage(host_screen->ximg); + shmctl(host_screen->shminfo.shmid, IPC_RMID, 0); + } + else + { + EPHYR_DBG("SHM segment attached %p", host_screen->shminfo.shmaddr); + host_screen->shminfo.readOnly = False; + XShmAttach(HostX.dpy, &host_screen->shminfo); + shm_success = True; + } + } + + if (!shm_success) + { + bitmap_pad = ( HostX.depth > 16 )? 32 : (( HostX.depth > 8 )? 16 : 8 ); + + EPHYR_DBG("Creating image %dx%d for screen host_screen=%p\n", + width, buffer_height, host_screen ); + host_screen->ximg = XCreateImage (HostX.dpy, + HostX.visual, + HostX.depth, + ZPixmap, 0, 0, + width, + buffer_height, + bitmap_pad, + 0); + + host_screen->ximg->data = + malloc (host_screen->ximg->bytes_per_line * buffer_height); + } + + XResizeWindow (HostX.dpy, host_screen->win, width, height); + + /* Ask the WM to keep our size static */ + size_hints = XAllocSizeHints(); + size_hints->max_width = size_hints->min_width = width; + size_hints->max_height = size_hints->min_height = height; + size_hints->flags = PMinSize|PMaxSize; + XSetWMNormalHints(HostX.dpy, host_screen->win, size_hints); + XFree(size_hints); + + XMapWindow(HostX.dpy, host_screen->win); + + XSync(HostX.dpy, False); + + host_screen->win_width = width; + host_screen->win_height = height; + + if (host_depth_matches_server(host_screen)) + { + EPHYR_DBG("Host matches server"); + return host_screen->ximg->data; + } + else + { + EPHYR_DBG("server bpp %i", host_screen->server_depth>>3); + host_screen->fb_data = malloc(width*buffer_height*(host_screen->server_depth>>3)); + return host_screen->fb_data; + } +} + +static void hostx_paint_debug_rect (struct EphyrHostScreen *host_screen, + int x, int y, + int width, int height); + +void +hostx_paint_rect (EphyrScreenInfo screen, + int sx, int sy, + int dx, int dy, + int width, int height) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + EPHYR_DBG ("painting in screen %d\n", host_screen->mynum) ; + + /* + * Copy the image data updated by the shadow layer + * on to the window + */ + + if (HostXWantDamageDebug) + { + hostx_paint_debug_rect(host_screen, dx, dy, width, height); + } + + /* + * If the depth of the ephyr server is less than that of the host, + * the kdrive fb does not point to the ximage data but to a buffer + * ( fb_data ), we shift the various bits from this onto the XImage + * so they match the host. + * + * Note, This code is pretty new ( and simple ) so may break on + * endian issues, 32 bpp host etc. + * Not sure if 8bpp case is right either. + * ... and it will be slower than the matching depth case. + */ + + if (!host_depth_matches_server(host_screen)) + { + int x,y,idx, bytes_per_pixel = (host_screen->server_depth>>3); + unsigned char r,g,b; + unsigned long host_pixel; + + EPHYR_DBG("Unmatched host depth host_screen=%p\n", host_screen); + for (y=sy; y<sy+height; y++) + for (x=sx; x<sx+width; x++) + { + idx = (host_screen->win_width*y*bytes_per_pixel)+(x*bytes_per_pixel); + + switch (host_screen->server_depth) + { + case 16: + { + unsigned short pixel = *(unsigned short*)(host_screen->fb_data+idx); + + r = ((pixel & 0xf800) >> 8); + g = ((pixel & 0x07e0) >> 3); + b = ((pixel & 0x001f) << 3); + + host_pixel = (r << 16) | (g << 8) | (b); + + XPutPixel(host_screen->ximg, x, y, host_pixel); + break; + } + case 8: + { + unsigned char pixel = *(unsigned char*)(host_screen->fb_data+idx); + XPutPixel(host_screen->ximg, x, y, HostX.cmap[pixel]); + break; + } + default: + break; + } + } + } + + if (HostX.have_shm) + { + XShmPutImage (HostX.dpy, host_screen->win, + HostX.gc, host_screen->ximg, + sx, sy, dx, dy, width, height, False); + } + else + { + XPutImage (HostX.dpy, host_screen->win, HostX.gc, host_screen->ximg, + sx, sy, dx, dy, width, height); + } + + XSync (HostX.dpy, False); +} + +static void +hostx_paint_debug_rect (struct EphyrHostScreen *host_screen, + int x, int y, + int width, int height) +{ + struct timespec tspec; + + tspec.tv_sec = HostX.damage_debug_msec / (1000000); + tspec.tv_nsec = (HostX.damage_debug_msec % 1000000) * 1000; + + EPHYR_DBG("msec: %li tv_sec %li, tv_msec %li", + HostX.damage_debug_msec, tspec.tv_sec, tspec.tv_nsec); + + /* fprintf(stderr, "Xephyr updating: %i+%i %ix%i\n", x, y, width, height); */ + + XFillRectangle (HostX.dpy, host_screen->win, HostX.gc, x, y, width,height); + XSync (HostX.dpy, False); + + /* nanosleep seems to work better than usleep for me... */ + nanosleep(&tspec, NULL); +} + +void +hostx_load_keymap(void) +{ + XID *keymap; + int host_width, min_keycode, max_keycode, width; + int i,j; + + XDisplayKeycodes (HostX.dpy, &min_keycode, &max_keycode); + + EPHYR_DBG ("min: %d, max: %d", min_keycode, max_keycode); + + keymap = XGetKeyboardMapping (HostX.dpy, + min_keycode, + max_keycode - min_keycode + 1, + &host_width); + + /* Try and copy the hosts keymap into our keymap to avoid loads + * of messing around. + * + * kdrive cannot can have more than 4 keysyms per keycode + * so we only copy at most the first 4 ( xorg has 6 per keycode, XVNC 2 ) + */ + width = (host_width > 4) ? 4 : host_width; + + ephyrKeySyms.map = (CARD32 *)calloc(sizeof(CARD32), + (max_keycode - min_keycode + 1) * + width); + if (!ephyrKeySyms.map) + return; + + for (i=0; i<(max_keycode - min_keycode+1); i++) + for (j=0; j<width; j++) + ephyrKeySyms.map[(i*width)+j] = (CARD32) keymap[(i*host_width) + j]; + + EPHYR_DBG("keymap width, host:%d kdrive:%d", host_width, width); + + ephyrKeySyms.minKeyCode = min_keycode; + ephyrKeySyms.maxKeyCode = max_keycode; + ephyrKeySyms.mapWidth = width; + + XFree(keymap); +} + +static struct EphyrHostScreen * +host_screen_from_window (Window w) +{ + int index = 0; + struct EphyrHostScreen *result = NULL; + + for (index = 0 ; index < HostX.n_screens ; index++) + { + if (HostX.screens[index].win == w || HostX.screens[index].peer_win == w) + { + result = &HostX.screens[index]; + goto out; + } + } + +out: + return result; +} + +int +hostx_get_event(EphyrHostXEvent *ev) +{ + XEvent xev; + static int grabbed_screen = -1; + + if (XPending(HostX.dpy)) + { + XNextEvent(HostX.dpy, &xev); + + switch (xev.type) + { + case Expose: + /* Not so great event compression, but works ok */ + while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window, + Expose, &xev)); + { + struct EphyrHostScreen *host_screen = + host_screen_from_window (xev.xexpose.window); + if (host_screen) + { + hostx_paint_rect (host_screen->info, 0, 0, 0, 0, + host_screen->win_width, + host_screen->win_height); + } + else + { + EPHYR_LOG_ERROR ("failed to get host screen\n"); + ev->type = EPHYR_EV_EXPOSE; + ev->data.expose.window = xev.xexpose.window; + return 1; + } + } + return 0; + + case MotionNotify: + { + struct EphyrHostScreen *host_screen = + host_screen_from_window (xev.xmotion.window); + + ev->type = EPHYR_EV_MOUSE_MOTION; + ev->data.mouse_motion.x = xev.xmotion.x; + ev->data.mouse_motion.y = xev.xmotion.y; + ev->data.mouse_motion.window = xev.xmotion.window; + ev->data.mouse_motion.screen = (host_screen ? host_screen->mynum : -1); + } + return 1; + + case ButtonPress: + ev->type = EPHYR_EV_MOUSE_PRESS; + ev->key_state = xev.xkey.state; + /* + * This is a bit hacky. will break for button 5 ( defined as 0x10 ) + * Check KD_BUTTON defines in kdrive.h + */ + ev->data.mouse_down.button_num = 1<<(xev.xbutton.button-1); + return 1; + + case ButtonRelease: + ev->type = EPHYR_EV_MOUSE_RELEASE; + ev->key_state = xev.xkey.state; + ev->data.mouse_up.button_num = 1<<(xev.xbutton.button-1); + return 1; + + case KeyPress: + { + ev->type = EPHYR_EV_KEY_PRESS; + ev->key_state = xev.xkey.state; + ev->data.key_down.scancode = xev.xkey.keycode; + return 1; + } + case KeyRelease: + + if ((XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) == XK_Shift_L + || XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) == XK_Shift_R) + && (xev.xkey.state & ControlMask)) + { + struct EphyrHostScreen *host_screen = + host_screen_from_window (xev.xexpose.window); + + if (grabbed_screen != -1) + { + XUngrabKeyboard (HostX.dpy, CurrentTime); + XUngrabPointer (HostX.dpy, CurrentTime); + grabbed_screen = -1; + hostx_set_win_title (host_screen->info, + "(ctrl+shift grabs mouse and keyboard)"); + } + else + { + /* Attempt grab */ + if (XGrabKeyboard (HostX.dpy, host_screen->win, True, + GrabModeAsync, + GrabModeAsync, + CurrentTime) == 0) + { + if (XGrabPointer (HostX.dpy, host_screen->win, True, + NoEventMask, + GrabModeAsync, + GrabModeAsync, + host_screen->win, None, CurrentTime) == 0) + { + grabbed_screen = host_screen->mynum; + hostx_set_win_title + (host_screen->info, + "(ctrl+shift releases mouse and keyboard)"); + } + else /* Failed pointer grabm ungrab keyboard */ + XUngrabKeyboard (HostX.dpy, CurrentTime); + } + } + } + + /* Still send the release event even if above has happened + * server will get confused with just an up event. + * Maybe it would be better to just block shift+ctrls getting to + * kdrive all togeather. + */ + ev->type = EPHYR_EV_KEY_RELEASE; + ev->key_state = xev.xkey.state; + ev->data.key_up.scancode = xev.xkey.keycode; + return 1; + + default: + break; + + } + } + return 0; +} + +void* +hostx_get_display(void) +{ + return HostX.dpy ; +} + +int +hostx_get_window (int a_screen_number) +{ + if (a_screen_number < 0 || a_screen_number >= HostX.n_screens) { + EPHYR_LOG_ERROR ("bad screen number:%d\n", a_screen_number) ; + return 0; + } + return HostX.screens[a_screen_number].win ; +} + +int +hostx_get_window_attributes (int a_window, EphyrHostWindowAttributes *a_attrs) +{ + XWindowAttributes attrs ; + + memset (&attrs, 0, sizeof (attrs)) ; + + if (!XGetWindowAttributes (hostx_get_display (), + a_window, + &attrs)) { + return FALSE ; + } + a_attrs->x = attrs.x ; + a_attrs->y = attrs.y ; + a_attrs->width = attrs.width ; + a_attrs->height = attrs.height ; + if (attrs.visual) + a_attrs->visualid = attrs.visual->visualid ; + return TRUE ; +} + +int +hostx_get_extension_info (const char *a_ext_name, + int *a_major_opcode, + int *a_first_event, + int *a_first_error) +{ + if (!a_ext_name || !a_major_opcode || !a_first_event || !a_first_error) + return 0 ; + if (!XQueryExtension (HostX.dpy, + a_ext_name, + a_major_opcode, + a_first_event, + a_first_error)) + { + return 0 ; + } + return 1 ; +} + +int +hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals, + int *a_num_entries) +{ + Display *dpy=hostx_get_display () ; + Bool is_ok=False ; + XVisualInfo templ, *visuals=NULL; + EphyrHostVisualInfo *host_visuals=NULL ; + int nb_items=0, i=0; + + EPHYR_RETURN_VAL_IF_FAIL (a_visuals && a_num_entries && dpy, + False) ; + EPHYR_LOG ("enter\n") ; + memset (&templ, 0, sizeof (templ)) ; + visuals = XGetVisualInfo (dpy, VisualNoMask, &templ, &nb_items) ; + if (!visuals) { + EPHYR_LOG_ERROR ("host does not advertise any visual\n") ; + goto out ; + } + EPHYR_LOG ("host advertises %d visuals\n", nb_items) ; + host_visuals = calloc (nb_items, sizeof (EphyrHostVisualInfo)) ; + for (i=0; i<nb_items; i++) { + host_visuals[i].visualid = visuals[i].visualid ; + host_visuals[i].screen = visuals[i].screen ; + host_visuals[i].depth = visuals[i].depth ; + host_visuals[i].class = visuals[i].class ; + host_visuals[i].red_mask = visuals[i].red_mask ; + host_visuals[i].green_mask = visuals[i].green_mask ; + host_visuals[i].blue_mask = visuals[i].blue_mask ; + host_visuals[i].colormap_size = visuals[i].colormap_size ; + host_visuals[i].bits_per_rgb = visuals[i].bits_per_rgb ; + } + *a_visuals = host_visuals ; + *a_num_entries = nb_items; + host_visuals=NULL; + + is_ok = TRUE; +out: + if (visuals) { + XFree (visuals) ; + visuals = NULL; + } + free(host_visuals); + host_visuals = NULL; + EPHYR_LOG ("leave\n") ; + return is_ok ; + +} + +int +hostx_create_window (int a_screen_number, + EphyrBox *a_geometry, + int a_visual_id, + int *a_host_peer /*out parameter*/) +{ + Bool is_ok=FALSE ; + Display *dpy=hostx_get_display () ; + XVisualInfo *visual_info=NULL, visual_info_templ; + int visual_mask=VisualIDMask ; + Window win=None ; + int nb_visuals=0, winmask=0; + XSetWindowAttributes attrs; + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geometry, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + /*get visual*/ + memset (&visual_info, 0, sizeof (visual_info)) ; + visual_info_templ.visualid = a_visual_id ; + visual_info = XGetVisualInfo (dpy, visual_mask, + &visual_info_templ, + &nb_visuals) ; + if (!visual_info) { + EPHYR_LOG_ERROR ("argh, could not find a remote visual with id:%d\n", + a_visual_id) ; + goto out ; + } + memset (&attrs, 0, sizeof (attrs)) ; + attrs.colormap = XCreateColormap (dpy, + RootWindow (dpy, + visual_info->screen), + visual_info->visual, + AllocNone) ; + attrs.event_mask = ButtonPressMask + |ButtonReleaseMask + |PointerMotionMask + |KeyPressMask + |KeyReleaseMask + |ExposureMask; + winmask = CWColormap|CWEventMask; + + win = XCreateWindow (dpy, hostx_get_window (a_screen_number), + a_geometry->x, a_geometry->y, + a_geometry->width, a_geometry->height, 0, + visual_info->depth, CopyFromParent, + visual_info->visual, winmask, &attrs) ; + if (win == None) { + EPHYR_LOG_ERROR ("failed to create peer window\n") ; + goto out ; + } + if (HostX.screens[a_screen_number].peer_win == None) { + HostX.screens[a_screen_number].peer_win = win; + } else { + EPHYR_LOG_ERROR ("multiple peer windows created for same screen\n") ; + } + XFlush (dpy) ; + XMapWindow (dpy, win) ; + *a_host_peer = win ; + is_ok = TRUE ; +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +int +hostx_destroy_window (int a_win) +{ + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + XDestroyWindow (dpy, a_win) ; + XFlush (dpy) ; + return TRUE ; +} + +int +hostx_set_window_geometry (int a_win, EphyrBox *a_geo) +{ + Display *dpy=hostx_get_display (); + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geo, FALSE) ; + + EPHYR_LOG ("enter. x,y,w,h:(%d,%d,%d,%d)\n", + a_geo->x, a_geo->y, + a_geo->width, a_geo->height) ; + + XMoveWindow (dpy, a_win, a_geo->x, a_geo->y) ; + XResizeWindow (dpy, a_win, a_geo->width, a_geo->height) ; + EPHYR_LOG ("leave\n") ; + return TRUE; +} + +int +hostx_set_window_bounding_rectangles (int a_window, + EphyrRect *a_rects, + int a_num_rects) +{ + Bool is_ok=FALSE; + Display *dpy=hostx_get_display () ; + int i=0 ; + XRectangle *rects=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ; + + EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ; + + rects = calloc (a_num_rects, sizeof (XRectangle)) ; + for (i=0; i<a_num_rects; i++) { + rects[i].x = a_rects[i].x1 ; + rects[i].y = a_rects[i].y1 ; + rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1); + rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ; + EPHYR_LOG ("borders clipped to rect[x:%d,y:%d,w:%d,h:%d]\n", + rects[i].x, rects[i].y, + rects[i].width, rects[i].height) ; + } + /*this aways returns 1*/ + XShapeCombineRectangles (dpy, a_window, ShapeBounding, 0, 0, + rects, a_num_rects, ShapeSet, YXBanded) ; + is_ok = TRUE ; + + free(rects); + rects = NULL; + EPHYR_LOG ("leave\n") ; + return is_ok; +} + +int +hostx_set_window_clipping_rectangles (int a_window, + EphyrRect *a_rects, + int a_num_rects) +{ + Bool is_ok=FALSE; + Display *dpy=hostx_get_display () ; + int i=0 ; + XRectangle *rects=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ; + + EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ; + + rects = calloc (a_num_rects, sizeof (XRectangle)) ; + for (i=0; i<a_num_rects; i++) { + rects[i].x = a_rects[i].x1 ; + rects[i].y = a_rects[i].y1 ; + rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1); + rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ; + EPHYR_LOG ("clipped to rect[x:%d,y:%d,w:%d,h:%d]\n", + rects[i].x, rects[i].y, + rects[i].width, rects[i].height) ; + } + /*this aways returns 1*/ + XShapeCombineRectangles (dpy, a_window, ShapeClip, 0, 0, + rects, a_num_rects, ShapeSet, YXBanded) ; + is_ok = TRUE ; + + free(rects); + rects = NULL; + EPHYR_LOG ("leave\n") ; + return is_ok; +} + +int +hostx_has_xshape (void) +{ + int event_base=0, error_base=0 ; + Display *dpy=hostx_get_display () ; + if (!XShapeQueryExtension (dpy, + &event_base, + &error_base)) { + return FALSE ; + } + return TRUE; +} + +#ifdef XF86DRI +typedef struct { + int is_valid ; + int local_id ; + int remote_id ; +} ResourcePair ; + +#define RESOURCE_PEERS_SIZE 1024*10 +static ResourcePair resource_peers[RESOURCE_PEERS_SIZE] ; + + +int +hostx_allocate_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) +{ + int i=0 ; + ResourcePair *peer=NULL ; + Display *dpy=hostx_get_display (); + + /* + * first make sure a resource peer + * does not exist already for + * a_local_resource_id + */ + for (i=0; i<RESOURCE_PEERS_SIZE; i++) { + if (resource_peers[i].is_valid + && resource_peers[i].local_id == a_local_resource_id) { + peer = &resource_peers[i] ; + break ; + } + } + /* + * find one free peer entry, an feed it with + */ + if (!peer) { + for (i=0; i<RESOURCE_PEERS_SIZE; i++) { + if (!resource_peers[i].is_valid) { + peer = &resource_peers[i] ; + break ; + } + } + if (peer) { + peer->remote_id = XAllocID (dpy); + peer->local_id = a_local_resource_id ; + peer->is_valid = TRUE ; + } + } + if (peer) { + *a_remote_resource_id = peer->remote_id ; + return TRUE ; + } + return FALSE ; +} + +int +hostx_get_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) +{ + int i=0 ; + ResourcePair *peer=NULL ; + for (i=0; i<RESOURCE_PEERS_SIZE; i++) { + if (resource_peers[i].is_valid + && resource_peers[i].local_id == a_local_resource_id) { + peer = &resource_peers[i] ; + break ; + } + } + if (peer) { + *a_remote_resource_id = peer->remote_id ; + return TRUE ; + } + return FALSE ; +} + +int +hostx_has_dri (void) +{ + int event_base=0, error_base=0 ; + Display *dpy=hostx_get_display () ; + + if (!dpy) + return FALSE ; + + if (!XF86DRIQueryExtension (dpy, + &event_base, + &error_base)) { + return FALSE ; + } + return TRUE ; +} + +int +hostx_has_glx (void) +{ + Display *dpy=hostx_get_display () ; + int event_base=0, error_base=0 ; + + if (!glXQueryExtension (dpy, &event_base, &error_base)) { + return FALSE ; + } + return TRUE ; +} + +#endif /* XF86DRI */ diff --git a/xorg-server/hw/kdrive/ephyr/hostx.h b/xorg-server/hw/kdrive/ephyr/hostx.h index e65e0c9bc..42578576a 100644 --- a/xorg-server/hw/kdrive/ephyr/hostx.h +++ b/xorg-server/hw/kdrive/ephyr/hostx.h @@ -2,7 +2,7 @@ * Xephyr - A kdrive X server thats runs in a host X window. * Authored by Matthew Allum <mallum@o-hand.com> * - * Copyright © 2004 Nokia + * Copyright © 2004 Nokia * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg-server/hw/kdrive/ephyr/os.c b/xorg-server/hw/kdrive/ephyr/os.c index 4bf6e8858..e4dc6787d 100644 --- a/xorg-server/hw/kdrive/ephyr/os.c +++ b/xorg-server/hw/kdrive/ephyr/os.c @@ -2,7 +2,7 @@ * Xephyr - A kdrive X server thats runs in a host X window. * Authored by Matthew Allum <mallum@o-hand.com> * - * Copyright © 2004 Nokia + * Copyright © 2004 Nokia * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg-server/hw/kdrive/fake/fakeinit.c b/xorg-server/hw/kdrive/fake/fakeinit.c index ba61959ef..e25093fbf 100644 --- a/xorg-server/hw/kdrive/fake/fakeinit.c +++ b/xorg-server/hw/kdrive/fake/fakeinit.c @@ -61,6 +61,7 @@ InitInput (int argc, char **argv) void CloseInput (void) { + KdCloseInput (); } #ifdef DDXBEFORERESET diff --git a/xorg-server/hw/kdrive/fake/kbd.c b/xorg-server/hw/kdrive/fake/kbd.c index 51fba044d..769730d64 100644 --- a/xorg-server/hw/kdrive/fake/kbd.c +++ b/xorg-server/hw/kdrive/fake/kbd.c @@ -1,5 +1,5 @@ /* - * Copyright © 1999 Keith Packard + * Copyright © 1999 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg-server/hw/kdrive/fbdev/fbdev.c b/xorg-server/hw/kdrive/fbdev/fbdev.c index b127ab89b..661e5b491 100644 --- a/xorg-server/hw/kdrive/fbdev/fbdev.c +++ b/xorg-server/hw/kdrive/fbdev/fbdev.c @@ -1,826 +1,826 @@ -/*
- * Copyright © 1999 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include "fbdev.h"
-#include <sys/ioctl.h>
-
-#include <errno.h>
-
-extern int KdTsPhyScreen;
-
-char *fbdevDevicePath = NULL;
-
-static Bool
-fbdevInitialize (KdCardInfo *card, FbdevPriv *priv)
-{
- unsigned long off;
-
- if (fbdevDevicePath == NULL)
- fbdevDevicePath = "/dev/fb0";
-
- if ((priv->fd = open(fbdevDevicePath, O_RDWR)) < 0)
- {
- ErrorF("Error opening framebuffer %s: %s\n",
- fbdevDevicePath, strerror(errno));
- return FALSE;
- }
-
- /* quiet valgrind */
- memset (&priv->fix, '\0', sizeof (priv->fix));
- if (ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix) < 0) {
- perror("Error with /dev/fb ioctl FIOGET_FSCREENINFO");
- close (priv->fd);
- return FALSE;
- }
- /* quiet valgrind */
- memset (&priv->var, '\0', sizeof (priv->var));
- if (ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var) < 0) {
- perror("Error with /dev/fb ioctl FIOGET_VSCREENINFO");
- close (priv->fd);
- return FALSE;
- }
-
- priv->fb_base = (char *) mmap ((caddr_t) NULL,
- priv->fix.smem_len,
- PROT_READ|PROT_WRITE,
- MAP_SHARED,
- priv->fd, 0);
-
- if (priv->fb_base == (char *)-1)
- {
- perror("ERROR: mmap framebuffer fails!");
- close (priv->fd);
- return FALSE;
- }
- off = (unsigned long) priv->fix.smem_start % (unsigned long) getpagesize();
- priv->fb = priv->fb_base + off;
- return TRUE;
-}
-
-Bool
-fbdevCardInit (KdCardInfo *card)
-{
- FbdevPriv *priv;
-
- priv = (FbdevPriv *) malloc(sizeof (FbdevPriv));
- if (!priv)
- return FALSE;
-
- if (!fbdevInitialize (card, priv))
- {
- free(priv);
- return FALSE;
- }
- card->driver = priv;
-
- return TRUE;
-}
-
-static Pixel
-fbdevMakeContig (Pixel orig, Pixel others)
-{
- Pixel low;
-
- low = lowbit (orig) >> 1;
- while (low && (others & low) == 0)
- {
- orig |= low;
- low >>= 1;
- }
- return orig;
-}
-
-static Bool
-fbdevModeSupported (KdScreenInfo *screen,
- const KdMonitorTiming *t)
-{
- return TRUE;
-}
-
-static void
-fbdevConvertMonitorTiming (const KdMonitorTiming *t, struct fb_var_screeninfo *var)
-{
- memset (var, 0, sizeof (struct fb_var_screeninfo));
-
- var->xres = t->horizontal;
- var->yres = t->vertical;
- var->xres_virtual = t->horizontal;
- var->yres_virtual = t->vertical;
- var->xoffset = 0;
- var->yoffset = 0;
- var->pixclock = t->clock ? 1000000000 / t->clock : 0;
- var->left_margin = t->hbp;
- var->right_margin = t->hfp;
- var->upper_margin = t->vbp;
- var->lower_margin = t->vfp;
- var->hsync_len = t->hblank - t->hfp - t->hbp;
- var->vsync_len = t->vblank - t->vfp - t->vbp;
-
- var->sync = 0;
- var->vmode = 0;
-
- if (t->hpol == KdSyncPositive)
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (t->vpol == KdSyncPositive)
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
-}
-
-static Bool
-fbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv)
-{
- FbdevPriv *priv = screen->card->driver;
- Pixel allbits;
- int depth;
- Bool gray;
- struct fb_var_screeninfo var;
- const KdMonitorTiming *t;
- int k;
-
- k = ioctl (priv->fd, FBIOGET_VSCREENINFO, &var);
-
- if (!screen->width || !screen->height)
- {
- if (k >= 0)
- {
- screen->width = var.xres;
- screen->height = var.yres;
- }
- else
- {
- screen->width = 1024;
- screen->height = 768;
- }
- screen->rate = 103; /* FIXME: should get proper value from fb driver */
- }
- if (!screen->fb.depth)
- {
- if (k >= 0)
- screen->fb.depth = var.bits_per_pixel;
- else
- screen->fb.depth = 16;
- }
-
- if ((screen->width != var.xres) || (screen->height != var.yres))
- {
- t = KdFindMode (screen, fbdevModeSupported);
- screen->rate = t->rate;
- screen->width = t->horizontal;
- screen->height = t->vertical;
-
- /* Now try setting the mode */
- if (k < 0 || (t->horizontal != var.xres || t->vertical != var.yres))
- fbdevConvertMonitorTiming (t, &var);
- }
-
- var.activate = FB_ACTIVATE_NOW;
- var.bits_per_pixel = screen->fb.depth;
- var.nonstd = 0;
- var.grayscale = 0;
-
- k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &var);
-
- if (k < 0)
- {
- fprintf (stderr, "error: %s\n", strerror (errno));
- return FALSE;
- }
-
- /* Re-get the "fixed" parameters since they might have changed */
- k = ioctl (priv->fd, FBIOGET_FSCREENINFO, &priv->fix);
- if (k < 0)
- perror ("FBIOGET_FSCREENINFO");
-
- /* Now get the new screeninfo */
- ioctl (priv->fd, FBIOGET_VSCREENINFO, &priv->var);
- depth = priv->var.bits_per_pixel;
- gray = priv->var.grayscale;
-
- switch (priv->fix.visual) {
- case FB_VISUAL_PSEUDOCOLOR:
- if (gray)
- {
- screen->fb.visuals = (1 << StaticGray);
- /* could also support GrayScale, but what's the point? */
- }
- else
- {
- screen->fb.visuals = ((1 << StaticGray) |
- (1 << GrayScale) |
- (1 << StaticColor) |
- (1 << PseudoColor) |
- (1 << TrueColor) |
- (1 << DirectColor));
- }
- screen->fb.blueMask = 0x00;
- screen->fb.greenMask = 0x00;
- screen->fb.redMask = 0x00;
- break;
- case FB_VISUAL_STATIC_PSEUDOCOLOR:
- if (gray)
- {
- screen->fb.visuals = (1 << StaticGray);
- }
- else
- {
- screen->fb.visuals = (1 << StaticColor);
- }
- screen->fb.blueMask = 0x00;
- screen->fb.greenMask = 0x00;
- screen->fb.redMask = 0x00;
- break;
- case FB_VISUAL_TRUECOLOR:
- case FB_VISUAL_DIRECTCOLOR:
- screen->fb.visuals = (1 << TrueColor);
-#define Mask(o,l) (((1 << l) - 1) << o)
- screen->fb.redMask = Mask (priv->var.red.offset, priv->var.red.length);
- screen->fb.greenMask = Mask (priv->var.green.offset, priv->var.green.length);
- screen->fb.blueMask = Mask (priv->var.blue.offset, priv->var.blue.length);
-
- /*
- * This is a kludge so that Render will work -- fill in the gaps
- * in the pixel
- */
- screen->fb.redMask = fbdevMakeContig (screen->fb.redMask,
- screen->fb.greenMask|
- screen->fb.blueMask);
-
- screen->fb.greenMask = fbdevMakeContig (screen->fb.greenMask,
- screen->fb.redMask|
- screen->fb.blueMask);
-
- screen->fb.blueMask = fbdevMakeContig (screen->fb.blueMask,
- screen->fb.redMask|
- screen->fb.greenMask);
-
- allbits = screen->fb.redMask | screen->fb.greenMask | screen->fb.blueMask;
- depth = 32;
- while (depth && !(allbits & (1 << (depth - 1))))
- depth--;
- break;
- default:
- return FALSE;
- break;
- }
- screen->fb.depth = depth;
- screen->fb.bitsPerPixel = priv->var.bits_per_pixel;
-
- scrpriv->randr = screen->randr;
-
- return fbdevMapFramebuffer (screen);
-}
-
-Bool
-fbdevScreenInit (KdScreenInfo *screen)
-{
- FbdevScrPriv *scrpriv;
-
- scrpriv = calloc(1, sizeof (FbdevScrPriv));
- if (!scrpriv)
- return FALSE;
- screen->driver = scrpriv;
- if (!fbdevScreenInitialize (screen, scrpriv))
- {
- screen->driver = 0;
- free(scrpriv);
- return FALSE;
- }
- return TRUE;
-}
-
-static void *
-fbdevWindowLinear (ScreenPtr pScreen,
- CARD32 row,
- CARD32 offset,
- int mode,
- CARD32 *size,
- void *closure)
-{
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
-
- if (!pScreenPriv->enabled)
- return 0;
- *size = priv->fix.line_length;
- return (CARD8 *) priv->fb + row * priv->fix.line_length + offset;
-}
-
-Bool
-fbdevMapFramebuffer (KdScreenInfo *screen)
-{
- FbdevScrPriv *scrpriv = screen->driver;
- KdPointerMatrix m;
- FbdevPriv *priv = screen->card->driver;
-
- if (scrpriv->randr != RR_Rotate_0)
- scrpriv->shadow = TRUE;
- else
- scrpriv->shadow = FALSE;
-
- KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height);
-
- KdSetPointerMatrix (&m);
-
- screen->width = priv->var.xres;
- screen->height = priv->var.yres;
-
- if (scrpriv->shadow)
- {
- if (!KdShadowFbAlloc (screen,
- scrpriv->randr & (RR_Rotate_90|RR_Rotate_270)))
- return FALSE;
- }
- else
- {
- screen->fb.byteStride = priv->fix.line_length;
- screen->fb.pixelStride = (priv->fix.line_length * 8 /
- priv->var.bits_per_pixel);
- screen->fb.frameBuffer = (CARD8 *) (priv->fb);
- }
-
- return TRUE;
-}
-
-static void
-fbdevSetScreenSizes (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- FbdevScrPriv *scrpriv = screen->driver;
- FbdevPriv *priv = screen->card->driver;
-
- if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180))
- {
- pScreen->width = priv->var.xres;
- pScreen->height = priv->var.yres;
- pScreen->mmWidth = screen->width_mm;
- pScreen->mmHeight = screen->height_mm;
- }
- else
- {
- pScreen->width = priv->var.yres;
- pScreen->height = priv->var.xres;
- pScreen->mmWidth = screen->height_mm;
- pScreen->mmHeight = screen->width_mm;
- }
-}
-
-static Bool
-fbdevUnmapFramebuffer (KdScreenInfo *screen)
-{
- KdShadowFbFree (screen);
- return TRUE;
-}
-
-static Bool
-fbdevSetShadow (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- FbdevScrPriv *scrpriv = screen->driver;
- FbdevPriv *priv = screen->card->driver;
- ShadowUpdateProc update;
- ShadowWindowProc window;
- int useYX = 0;
-
-#ifdef __arm__
- /* Use variant copy routines that always read left to right in the
- shadow framebuffer. Reading vertical strips is exceptionally
- slow on XScale due to cache effects. */
- useYX = 1;
-#endif
-
- window = fbdevWindowLinear;
- update = 0;
- if (scrpriv->randr)
- if (priv->var.bits_per_pixel == 16) {
- switch (scrpriv->randr) {
- case RR_Rotate_90:
- if (useYX)
- update = shadowUpdateRotate16_90YX;
- else
- update = shadowUpdateRotate16_90;
- break;
- case RR_Rotate_180:
- update = shadowUpdateRotate16_180;
- break;
- case RR_Rotate_270:
- if (useYX)
- update = shadowUpdateRotate16_270YX;
- else
- update = shadowUpdateRotate16_270;
- break;
- default:
- update = shadowUpdateRotate16;
- break;
- }
- } else
- update = shadowUpdateRotatePacked;
- else
- update = shadowUpdatePacked;
- return KdShadowSet (pScreen, scrpriv->randr, update, window);
-}
-
-
-#ifdef RANDR
-static Bool
-fbdevRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- FbdevScrPriv *scrpriv = screen->driver;
- RRScreenSizePtr pSize;
- Rotation randr;
- int n;
-
- *rotations = RR_Rotate_All|RR_Reflect_All;
-
- for (n = 0; n < pScreen->numDepths; n++)
- if (pScreen->allowedDepths[n].numVids)
- break;
- if (n == pScreen->numDepths)
- return FALSE;
-
- pSize = RRRegisterSize (pScreen,
- screen->width,
- screen->height,
- screen->width_mm,
- screen->height_mm);
-
- randr = KdSubRotation (scrpriv->randr, screen->randr);
-
- RRSetCurrentConfig (pScreen, randr, 0, pSize);
-
- return TRUE;
-}
-
-static Bool
-fbdevRandRSetConfig (ScreenPtr pScreen,
- Rotation randr,
- int rate,
- RRScreenSizePtr pSize)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- FbdevScrPriv *scrpriv = screen->driver;
- Bool wasEnabled = pScreenPriv->enabled;
- FbdevScrPriv oldscr;
- int oldwidth;
- int oldheight;
- int oldmmwidth;
- int oldmmheight;
- int newwidth, newheight;
-
- if (screen->randr & (RR_Rotate_0|RR_Rotate_180))
- {
- newwidth = pSize->width;
- newheight = pSize->height;
- }
- else
- {
- newwidth = pSize->height;
- newheight = pSize->width;
- }
-
- if (wasEnabled)
- KdDisableScreen (pScreen);
-
- oldscr = *scrpriv;
-
- oldwidth = screen->width;
- oldheight = screen->height;
- oldmmwidth = pScreen->mmWidth;
- oldmmheight = pScreen->mmHeight;
-
- /*
- * Set new configuration
- */
-
- scrpriv->randr = KdAddRotation (screen->randr, randr);
-
- fbdevUnmapFramebuffer (screen);
-
- if (!fbdevMapFramebuffer (screen))
- goto bail4;
-
- KdShadowUnset (screen->pScreen);
-
- if (!fbdevSetShadow (screen->pScreen))
- goto bail4;
-
- fbdevSetScreenSizes (screen->pScreen);
-
- /*
- * Set frame buffer mapping
- */
- (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen),
- pScreen->width,
- pScreen->height,
- screen->fb.depth,
- screen->fb.bitsPerPixel,
- screen->fb.byteStride,
- screen->fb.frameBuffer);
-
- /* set the subpixel order */
-
- KdSetSubpixelOrder (pScreen, scrpriv->randr);
- if (wasEnabled)
- KdEnableScreen (pScreen);
-
- return TRUE;
-
-bail4:
- fbdevUnmapFramebuffer (screen);
- *scrpriv = oldscr;
- (void) fbdevMapFramebuffer (screen);
- pScreen->width = oldwidth;
- pScreen->height = oldheight;
- pScreen->mmWidth = oldmmwidth;
- pScreen->mmHeight = oldmmheight;
-
- if (wasEnabled)
- KdEnableScreen (pScreen);
- return FALSE;
-}
-
-static Bool
-fbdevRandRInit (ScreenPtr pScreen)
-{
- rrScrPrivPtr pScrPriv;
-
- if (!RRScreenInit (pScreen))
- return FALSE;
-
- pScrPriv = rrGetScrPriv(pScreen);
- pScrPriv->rrGetInfo = fbdevRandRGetInfo;
- pScrPriv->rrSetConfig = fbdevRandRSetConfig;
- return TRUE;
-}
-#endif
-
-static Bool
-fbdevCreateColormap (ColormapPtr pmap)
-{
- ScreenPtr pScreen = pmap->pScreen;
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
- VisualPtr pVisual;
- int i;
- int nent;
- xColorItem *pdefs;
-
- switch (priv->fix.visual) {
- case FB_VISUAL_STATIC_PSEUDOCOLOR:
- pVisual = pmap->pVisual;
- nent = pVisual->ColormapEntries;
- pdefs = malloc(nent * sizeof (xColorItem));
- if (!pdefs)
- return FALSE;
- for (i = 0; i < nent; i++)
- pdefs[i].pixel = i;
- fbdevGetColors (pScreen, nent, pdefs);
- for (i = 0; i < nent; i++)
- {
- pmap->red[i].co.local.red = pdefs[i].red;
- pmap->red[i].co.local.green = pdefs[i].green;
- pmap->red[i].co.local.blue = pdefs[i].blue;
- }
- free(pdefs);
- return TRUE;
- default:
- return fbInitializeColormap (pmap);
- }
-}
-
-Bool
-fbdevInitScreen (ScreenPtr pScreen)
-{
-#ifdef TOUCHSCREEN
- KdTsPhyScreen = pScreen->myNum;
-#endif
-
- pScreen->CreateColormap = fbdevCreateColormap;
- return TRUE;
-}
-
-Bool
-fbdevFinishInitScreen (ScreenPtr pScreen)
-{
- if (!shadowSetup (pScreen))
- return FALSE;
-
-#ifdef RANDR
- if (!fbdevRandRInit (pScreen))
- return FALSE;
-#endif
-
- return TRUE;
-}
-
-
-Bool
-fbdevCreateResources (ScreenPtr pScreen)
-{
- return fbdevSetShadow (pScreen);
-}
-
-void
-fbdevPreserve (KdCardInfo *card)
-{
-}
-
-static int
-fbdevUpdateFbColormap(FbdevPriv *priv, int minidx, int maxidx)
-{
- struct fb_cmap cmap;
-
- cmap.start = minidx;
- cmap.len = maxidx - minidx + 1;
- cmap.red = &priv->red[minidx];
- cmap.green = &priv->green[minidx];
- cmap.blue = &priv->blue[minidx];
- cmap.transp = 0;
-
- return ioctl(priv->fd, FBIOPUTCMAP, &cmap);
-}
-
-Bool
-fbdevEnable (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
- int k;
-
- priv->var.activate = FB_ACTIVATE_NOW|FB_CHANGE_CMAP_VBL;
-
- /* display it on the LCD */
- k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &priv->var);
- if (k < 0)
- {
- perror ("FBIOPUT_VSCREENINFO");
- return FALSE;
- }
-
- if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR)
- {
- int i;
-
- for (i = 0;
- i < (1 << priv->var.red.length) ||
- i < (1 << priv->var.green.length) ||
- i < (1 << priv->var.blue.length); i++)
- {
- priv->red[i] = i * 65535 / ((1 << priv->var.red.length) - 1);
- priv->green[i] = i * 65535 / ((1 << priv->var.green.length) - 1);
- priv->blue[i] = i * 65535 / ((1 << priv->var.blue.length) - 1);
- }
-
- fbdevUpdateFbColormap(priv, 0, i);
- }
- return TRUE;
-}
-
-Bool
-fbdevDPMS (ScreenPtr pScreen, int mode)
-{
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
- static int oldmode = -1;
-
- if (mode == oldmode)
- return TRUE;
-#ifdef FBIOPUT_POWERMODE
- if (ioctl (priv->fd, FBIOPUT_POWERMODE, &mode) >= 0)
- {
- oldmode = mode;
- return TRUE;
- }
-#endif
-#ifdef FBIOBLANK
- if (ioctl (priv->fd, FBIOBLANK, mode ? mode + 1 : 0) >= 0)
- {
- oldmode = mode;
- return TRUE;
- }
-#endif
- return FALSE;
-}
-
-void
-fbdevDisable (ScreenPtr pScreen)
-{
-}
-
-void
-fbdevRestore (KdCardInfo *card)
-{
-}
-
-void
-fbdevScreenFini (KdScreenInfo *screen)
-{
-}
-
-void
-fbdevCardFini (KdCardInfo *card)
-{
- FbdevPriv *priv = card->driver;
-
- munmap (priv->fb_base, priv->fix.smem_len);
- close (priv->fd);
- free(priv);
-}
-
-/*
- * Retrieve actual colormap and return selected n entries in pdefs.
- */
-void
-fbdevGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs)
-{
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
- struct fb_cmap cmap;
- int p;
- int k;
- int min, max;
-
- min = 256;
- max = 0;
- for (k = 0; k < n; k++)
- {
- if (pdefs[k].pixel < min)
- min = pdefs[k].pixel;
- if (pdefs[k].pixel > max)
- max = pdefs[k].pixel;
- }
- cmap.start = min;
- cmap.len = max - min + 1;
- cmap.red = &priv->red[min];
- cmap.green = &priv->green[min];
- cmap.blue = &priv->blue[min];
- cmap.transp = 0;
- k = ioctl (priv->fd, FBIOGETCMAP, &cmap);
- if (k < 0)
- {
- perror ("can't get colormap");
- return;
- }
- while (n--)
- {
- p = pdefs->pixel;
- pdefs->red = priv->red[p];
- pdefs->green = priv->green[p];
- pdefs->blue = priv->blue[p];
- pdefs++;
- }
-}
-
-/*
- * Change colormap by updating n entries described in pdefs.
- */
-void
-fbdevPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs)
-{
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
- int p;
- int min, max;
-
- min = 256;
- max = 0;
- while (n--)
- {
- p = pdefs->pixel;
- priv->red[p] = pdefs->red;
- priv->green[p] = pdefs->green;
- priv->blue[p] = pdefs->blue;
- if (p < min)
- min = p;
- if (p > max)
- max = p;
- pdefs++;
- }
-
- fbdevUpdateFbColormap(priv, min, max);
-}
+/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "fbdev.h" +#include <sys/ioctl.h> + +#include <errno.h> + +extern int KdTsPhyScreen; + +char *fbdevDevicePath = NULL; + +static Bool +fbdevInitialize (KdCardInfo *card, FbdevPriv *priv) +{ + unsigned long off; + + if (fbdevDevicePath == NULL) + fbdevDevicePath = "/dev/fb0"; + + if ((priv->fd = open(fbdevDevicePath, O_RDWR)) < 0) + { + ErrorF("Error opening framebuffer %s: %s\n", + fbdevDevicePath, strerror(errno)); + return FALSE; + } + + /* quiet valgrind */ + memset (&priv->fix, '\0', sizeof (priv->fix)); + if (ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix) < 0) { + perror("Error with /dev/fb ioctl FIOGET_FSCREENINFO"); + close (priv->fd); + return FALSE; + } + /* quiet valgrind */ + memset (&priv->var, '\0', sizeof (priv->var)); + if (ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var) < 0) { + perror("Error with /dev/fb ioctl FIOGET_VSCREENINFO"); + close (priv->fd); + return FALSE; + } + + priv->fb_base = (char *) mmap ((caddr_t) NULL, + priv->fix.smem_len, + PROT_READ|PROT_WRITE, + MAP_SHARED, + priv->fd, 0); + + if (priv->fb_base == (char *)-1) + { + perror("ERROR: mmap framebuffer fails!"); + close (priv->fd); + return FALSE; + } + off = (unsigned long) priv->fix.smem_start % (unsigned long) getpagesize(); + priv->fb = priv->fb_base + off; + return TRUE; +} + +Bool +fbdevCardInit (KdCardInfo *card) +{ + FbdevPriv *priv; + + priv = (FbdevPriv *) malloc(sizeof (FbdevPriv)); + if (!priv) + return FALSE; + + if (!fbdevInitialize (card, priv)) + { + free(priv); + return FALSE; + } + card->driver = priv; + + return TRUE; +} + +static Pixel +fbdevMakeContig (Pixel orig, Pixel others) +{ + Pixel low; + + low = lowbit (orig) >> 1; + while (low && (others & low) == 0) + { + orig |= low; + low >>= 1; + } + return orig; +} + +static Bool +fbdevModeSupported (KdScreenInfo *screen, + const KdMonitorTiming *t) +{ + return TRUE; +} + +static void +fbdevConvertMonitorTiming (const KdMonitorTiming *t, struct fb_var_screeninfo *var) +{ + memset (var, 0, sizeof (struct fb_var_screeninfo)); + + var->xres = t->horizontal; + var->yres = t->vertical; + var->xres_virtual = t->horizontal; + var->yres_virtual = t->vertical; + var->xoffset = 0; + var->yoffset = 0; + var->pixclock = t->clock ? 1000000000 / t->clock : 0; + var->left_margin = t->hbp; + var->right_margin = t->hfp; + var->upper_margin = t->vbp; + var->lower_margin = t->vfp; + var->hsync_len = t->hblank - t->hfp - t->hbp; + var->vsync_len = t->vblank - t->vfp - t->vbp; + + var->sync = 0; + var->vmode = 0; + + if (t->hpol == KdSyncPositive) + var->sync |= FB_SYNC_HOR_HIGH_ACT; + if (t->vpol == KdSyncPositive) + var->sync |= FB_SYNC_VERT_HIGH_ACT; +} + +static Bool +fbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv) +{ + FbdevPriv *priv = screen->card->driver; + Pixel allbits; + int depth; + Bool gray; + struct fb_var_screeninfo var; + const KdMonitorTiming *t; + int k; + + k = ioctl (priv->fd, FBIOGET_VSCREENINFO, &var); + + if (!screen->width || !screen->height) + { + if (k >= 0) + { + screen->width = var.xres; + screen->height = var.yres; + } + else + { + screen->width = 1024; + screen->height = 768; + } + screen->rate = 103; /* FIXME: should get proper value from fb driver */ + } + if (!screen->fb.depth) + { + if (k >= 0) + screen->fb.depth = var.bits_per_pixel; + else + screen->fb.depth = 16; + } + + if ((screen->width != var.xres) || (screen->height != var.yres)) + { + t = KdFindMode (screen, fbdevModeSupported); + screen->rate = t->rate; + screen->width = t->horizontal; + screen->height = t->vertical; + + /* Now try setting the mode */ + if (k < 0 || (t->horizontal != var.xres || t->vertical != var.yres)) + fbdevConvertMonitorTiming (t, &var); + } + + var.activate = FB_ACTIVATE_NOW; + var.bits_per_pixel = screen->fb.depth; + var.nonstd = 0; + var.grayscale = 0; + + k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &var); + + if (k < 0) + { + fprintf (stderr, "error: %s\n", strerror (errno)); + return FALSE; + } + + /* Re-get the "fixed" parameters since they might have changed */ + k = ioctl (priv->fd, FBIOGET_FSCREENINFO, &priv->fix); + if (k < 0) + perror ("FBIOGET_FSCREENINFO"); + + /* Now get the new screeninfo */ + ioctl (priv->fd, FBIOGET_VSCREENINFO, &priv->var); + depth = priv->var.bits_per_pixel; + gray = priv->var.grayscale; + + switch (priv->fix.visual) { + case FB_VISUAL_PSEUDOCOLOR: + if (gray) + { + screen->fb.visuals = (1 << StaticGray); + /* could also support GrayScale, but what's the point? */ + } + else + { + screen->fb.visuals = ((1 << StaticGray) | + (1 << GrayScale) | + (1 << StaticColor) | + (1 << PseudoColor) | + (1 << TrueColor) | + (1 << DirectColor)); + } + screen->fb.blueMask = 0x00; + screen->fb.greenMask = 0x00; + screen->fb.redMask = 0x00; + break; + case FB_VISUAL_STATIC_PSEUDOCOLOR: + if (gray) + { + screen->fb.visuals = (1 << StaticGray); + } + else + { + screen->fb.visuals = (1 << StaticColor); + } + screen->fb.blueMask = 0x00; + screen->fb.greenMask = 0x00; + screen->fb.redMask = 0x00; + break; + case FB_VISUAL_TRUECOLOR: + case FB_VISUAL_DIRECTCOLOR: + screen->fb.visuals = (1 << TrueColor); +#define Mask(o,l) (((1 << l) - 1) << o) + screen->fb.redMask = Mask (priv->var.red.offset, priv->var.red.length); + screen->fb.greenMask = Mask (priv->var.green.offset, priv->var.green.length); + screen->fb.blueMask = Mask (priv->var.blue.offset, priv->var.blue.length); + + /* + * This is a kludge so that Render will work -- fill in the gaps + * in the pixel + */ + screen->fb.redMask = fbdevMakeContig (screen->fb.redMask, + screen->fb.greenMask| + screen->fb.blueMask); + + screen->fb.greenMask = fbdevMakeContig (screen->fb.greenMask, + screen->fb.redMask| + screen->fb.blueMask); + + screen->fb.blueMask = fbdevMakeContig (screen->fb.blueMask, + screen->fb.redMask| + screen->fb.greenMask); + + allbits = screen->fb.redMask | screen->fb.greenMask | screen->fb.blueMask; + depth = 32; + while (depth && !(allbits & (1 << (depth - 1)))) + depth--; + break; + default: + return FALSE; + break; + } + screen->fb.depth = depth; + screen->fb.bitsPerPixel = priv->var.bits_per_pixel; + + scrpriv->randr = screen->randr; + + return fbdevMapFramebuffer (screen); +} + +Bool +fbdevScreenInit (KdScreenInfo *screen) +{ + FbdevScrPriv *scrpriv; + + scrpriv = calloc(1, sizeof (FbdevScrPriv)); + if (!scrpriv) + return FALSE; + screen->driver = scrpriv; + if (!fbdevScreenInitialize (screen, scrpriv)) + { + screen->driver = 0; + free(scrpriv); + return FALSE; + } + return TRUE; +} + +static void * +fbdevWindowLinear (ScreenPtr pScreen, + CARD32 row, + CARD32 offset, + int mode, + CARD32 *size, + void *closure) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + + if (!pScreenPriv->enabled) + return 0; + *size = priv->fix.line_length; + return (CARD8 *) priv->fb + row * priv->fix.line_length + offset; +} + +Bool +fbdevMapFramebuffer (KdScreenInfo *screen) +{ + FbdevScrPriv *scrpriv = screen->driver; + KdPointerMatrix m; + FbdevPriv *priv = screen->card->driver; + + if (scrpriv->randr != RR_Rotate_0) + scrpriv->shadow = TRUE; + else + scrpriv->shadow = FALSE; + + KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); + + KdSetPointerMatrix (&m); + + screen->width = priv->var.xres; + screen->height = priv->var.yres; + + if (scrpriv->shadow) + { + if (!KdShadowFbAlloc (screen, + scrpriv->randr & (RR_Rotate_90|RR_Rotate_270))) + return FALSE; + } + else + { + screen->fb.byteStride = priv->fix.line_length; + screen->fb.pixelStride = (priv->fix.line_length * 8 / + priv->var.bits_per_pixel); + screen->fb.frameBuffer = (CARD8 *) (priv->fb); + } + + return TRUE; +} + +static void +fbdevSetScreenSizes (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + FbdevPriv *priv = screen->card->driver; + + if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180)) + { + pScreen->width = priv->var.xres; + pScreen->height = priv->var.yres; + pScreen->mmWidth = screen->width_mm; + pScreen->mmHeight = screen->height_mm; + } + else + { + pScreen->width = priv->var.yres; + pScreen->height = priv->var.xres; + pScreen->mmWidth = screen->height_mm; + pScreen->mmHeight = screen->width_mm; + } +} + +static Bool +fbdevUnmapFramebuffer (KdScreenInfo *screen) +{ + KdShadowFbFree (screen); + return TRUE; +} + +static Bool +fbdevSetShadow (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + FbdevPriv *priv = screen->card->driver; + ShadowUpdateProc update; + ShadowWindowProc window; + int useYX = 0; + +#ifdef __arm__ + /* Use variant copy routines that always read left to right in the + shadow framebuffer. Reading vertical strips is exceptionally + slow on XScale due to cache effects. */ + useYX = 1; +#endif + + window = fbdevWindowLinear; + update = 0; + if (scrpriv->randr) + if (priv->var.bits_per_pixel == 16) { + switch (scrpriv->randr) { + case RR_Rotate_90: + if (useYX) + update = shadowUpdateRotate16_90YX; + else + update = shadowUpdateRotate16_90; + break; + case RR_Rotate_180: + update = shadowUpdateRotate16_180; + break; + case RR_Rotate_270: + if (useYX) + update = shadowUpdateRotate16_270YX; + else + update = shadowUpdateRotate16_270; + break; + default: + update = shadowUpdateRotate16; + break; + } + } else + update = shadowUpdateRotatePacked; + else + update = shadowUpdatePacked; + return KdShadowSet (pScreen, scrpriv->randr, update, window); +} + + +#ifdef RANDR +static Bool +fbdevRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + RRScreenSizePtr pSize; + Rotation randr; + int n; + + *rotations = RR_Rotate_All|RR_Reflect_All; + + for (n = 0; n < pScreen->numDepths; n++) + if (pScreen->allowedDepths[n].numVids) + break; + if (n == pScreen->numDepths) + return FALSE; + + pSize = RRRegisterSize (pScreen, + screen->width, + screen->height, + screen->width_mm, + screen->height_mm); + + randr = KdSubRotation (scrpriv->randr, screen->randr); + + RRSetCurrentConfig (pScreen, randr, 0, pSize); + + return TRUE; +} + +static Bool +fbdevRandRSetConfig (ScreenPtr pScreen, + Rotation randr, + int rate, + RRScreenSizePtr pSize) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + Bool wasEnabled = pScreenPriv->enabled; + FbdevScrPriv oldscr; + int oldwidth; + int oldheight; + int oldmmwidth; + int oldmmheight; + int newwidth, newheight; + + if (screen->randr & (RR_Rotate_0|RR_Rotate_180)) + { + newwidth = pSize->width; + newheight = pSize->height; + } + else + { + newwidth = pSize->height; + newheight = pSize->width; + } + + if (wasEnabled) + KdDisableScreen (pScreen); + + oldscr = *scrpriv; + + oldwidth = screen->width; + oldheight = screen->height; + oldmmwidth = pScreen->mmWidth; + oldmmheight = pScreen->mmHeight; + + /* + * Set new configuration + */ + + scrpriv->randr = KdAddRotation (screen->randr, randr); + + fbdevUnmapFramebuffer (screen); + + if (!fbdevMapFramebuffer (screen)) + goto bail4; + + KdShadowUnset (screen->pScreen); + + if (!fbdevSetShadow (screen->pScreen)) + goto bail4; + + fbdevSetScreenSizes (screen->pScreen); + + /* + * Set frame buffer mapping + */ + (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen), + pScreen->width, + pScreen->height, + screen->fb.depth, + screen->fb.bitsPerPixel, + screen->fb.byteStride, + screen->fb.frameBuffer); + + /* set the subpixel order */ + + KdSetSubpixelOrder (pScreen, scrpriv->randr); + if (wasEnabled) + KdEnableScreen (pScreen); + + return TRUE; + +bail4: + fbdevUnmapFramebuffer (screen); + *scrpriv = oldscr; + (void) fbdevMapFramebuffer (screen); + pScreen->width = oldwidth; + pScreen->height = oldheight; + pScreen->mmWidth = oldmmwidth; + pScreen->mmHeight = oldmmheight; + + if (wasEnabled) + KdEnableScreen (pScreen); + return FALSE; +} + +static Bool +fbdevRandRInit (ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (!RRScreenInit (pScreen)) + return FALSE; + + pScrPriv = rrGetScrPriv(pScreen); + pScrPriv->rrGetInfo = fbdevRandRGetInfo; + pScrPriv->rrSetConfig = fbdevRandRSetConfig; + return TRUE; +} +#endif + +static Bool +fbdevCreateColormap (ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + VisualPtr pVisual; + int i; + int nent; + xColorItem *pdefs; + + switch (priv->fix.visual) { + case FB_VISUAL_STATIC_PSEUDOCOLOR: + pVisual = pmap->pVisual; + nent = pVisual->ColormapEntries; + pdefs = malloc(nent * sizeof (xColorItem)); + if (!pdefs) + return FALSE; + for (i = 0; i < nent; i++) + pdefs[i].pixel = i; + fbdevGetColors (pScreen, nent, pdefs); + for (i = 0; i < nent; i++) + { + pmap->red[i].co.local.red = pdefs[i].red; + pmap->red[i].co.local.green = pdefs[i].green; + pmap->red[i].co.local.blue = pdefs[i].blue; + } + free(pdefs); + return TRUE; + default: + return fbInitializeColormap (pmap); + } +} + +Bool +fbdevInitScreen (ScreenPtr pScreen) +{ +#ifdef TOUCHSCREEN + KdTsPhyScreen = pScreen->myNum; +#endif + + pScreen->CreateColormap = fbdevCreateColormap; + return TRUE; +} + +Bool +fbdevFinishInitScreen (ScreenPtr pScreen) +{ + if (!shadowSetup (pScreen)) + return FALSE; + +#ifdef RANDR + if (!fbdevRandRInit (pScreen)) + return FALSE; +#endif + + return TRUE; +} + + +Bool +fbdevCreateResources (ScreenPtr pScreen) +{ + return fbdevSetShadow (pScreen); +} + +void +fbdevPreserve (KdCardInfo *card) +{ +} + +static int +fbdevUpdateFbColormap(FbdevPriv *priv, int minidx, int maxidx) +{ + struct fb_cmap cmap; + + cmap.start = minidx; + cmap.len = maxidx - minidx + 1; + cmap.red = &priv->red[minidx]; + cmap.green = &priv->green[minidx]; + cmap.blue = &priv->blue[minidx]; + cmap.transp = 0; + + return ioctl(priv->fd, FBIOPUTCMAP, &cmap); +} + +Bool +fbdevEnable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + int k; + + priv->var.activate = FB_ACTIVATE_NOW|FB_CHANGE_CMAP_VBL; + + /* display it on the LCD */ + k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &priv->var); + if (k < 0) + { + perror ("FBIOPUT_VSCREENINFO"); + return FALSE; + } + + if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR) + { + int i; + + for (i = 0; + i < (1 << priv->var.red.length) || + i < (1 << priv->var.green.length) || + i < (1 << priv->var.blue.length); i++) + { + priv->red[i] = i * 65535 / ((1 << priv->var.red.length) - 1); + priv->green[i] = i * 65535 / ((1 << priv->var.green.length) - 1); + priv->blue[i] = i * 65535 / ((1 << priv->var.blue.length) - 1); + } + + fbdevUpdateFbColormap(priv, 0, i); + } + return TRUE; +} + +Bool +fbdevDPMS (ScreenPtr pScreen, int mode) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + static int oldmode = -1; + + if (mode == oldmode) + return TRUE; +#ifdef FBIOPUT_POWERMODE + if (ioctl (priv->fd, FBIOPUT_POWERMODE, &mode) >= 0) + { + oldmode = mode; + return TRUE; + } +#endif +#ifdef FBIOBLANK + if (ioctl (priv->fd, FBIOBLANK, mode ? mode + 1 : 0) >= 0) + { + oldmode = mode; + return TRUE; + } +#endif + return FALSE; +} + +void +fbdevDisable (ScreenPtr pScreen) +{ +} + +void +fbdevRestore (KdCardInfo *card) +{ +} + +void +fbdevScreenFini (KdScreenInfo *screen) +{ +} + +void +fbdevCardFini (KdCardInfo *card) +{ + FbdevPriv *priv = card->driver; + + munmap (priv->fb_base, priv->fix.smem_len); + close (priv->fd); + free(priv); +} + +/* + * Retrieve actual colormap and return selected n entries in pdefs. + */ +void +fbdevGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + struct fb_cmap cmap; + int p; + int k; + int min, max; + + min = 256; + max = 0; + for (k = 0; k < n; k++) + { + if (pdefs[k].pixel < min) + min = pdefs[k].pixel; + if (pdefs[k].pixel > max) + max = pdefs[k].pixel; + } + cmap.start = min; + cmap.len = max - min + 1; + cmap.red = &priv->red[min]; + cmap.green = &priv->green[min]; + cmap.blue = &priv->blue[min]; + cmap.transp = 0; + k = ioctl (priv->fd, FBIOGETCMAP, &cmap); + if (k < 0) + { + perror ("can't get colormap"); + return; + } + while (n--) + { + p = pdefs->pixel; + pdefs->red = priv->red[p]; + pdefs->green = priv->green[p]; + pdefs->blue = priv->blue[p]; + pdefs++; + } +} + +/* + * Change colormap by updating n entries described in pdefs. + */ +void +fbdevPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + int p; + int min, max; + + min = 256; + max = 0; + while (n--) + { + p = pdefs->pixel; + priv->red[p] = pdefs->red; + priv->green[p] = pdefs->green; + priv->blue[p] = pdefs->blue; + if (p < min) + min = p; + if (p > max) + max = p; + pdefs++; + } + + fbdevUpdateFbColormap(priv, min, max); +} diff --git a/xorg-server/hw/kdrive/fbdev/fbdev.h b/xorg-server/hw/kdrive/fbdev/fbdev.h index ebac6ad8b..ec53784af 100644 --- a/xorg-server/hw/kdrive/fbdev/fbdev.h +++ b/xorg-server/hw/kdrive/fbdev/fbdev.h @@ -1,5 +1,5 @@ /* - * Copyright © 1999 Keith Packard + * Copyright © 1999 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg-server/hw/kdrive/fbdev/fbinit.c b/xorg-server/hw/kdrive/fbdev/fbinit.c index 51e7e00d9..1d66fce32 100644 --- a/xorg-server/hw/kdrive/fbdev/fbinit.c +++ b/xorg-server/hw/kdrive/fbdev/fbinit.c @@ -1,5 +1,5 @@ /* - * Copyright © 1999 Keith Packard + * Copyright © 1999 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -47,6 +47,7 @@ InitInput (int argc, char **argv) void CloseInput (void) { + KdCloseInput (); } void diff --git a/xorg-server/hw/kdrive/linux/keyboard.c b/xorg-server/hw/kdrive/linux/keyboard.c index c888d14dc..f5f9d9b8a 100644 --- a/xorg-server/hw/kdrive/linux/keyboard.c +++ b/xorg-server/hw/kdrive/linux/keyboard.c @@ -1,765 +1,765 @@ -/*
- * Copyright © 1999 Keith Packard
- * XKB integration © 2006 Nokia Corporation, author: Tomas Frydrych <tf@o-hand.com>
- *
- * LinuxKeyboardRead() XKB code based on xf86KbdLnx.c:
- * Copyright © 1990,91 by Thomas Roell, Dinkelscherben, Germany.
- * Copyright © 1994-2001 by The XFree86 Project, Inc.
- *
- * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 copyright holder(s)
- * and author(s) 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 copyright holder(s) and author(s).
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include "kdrive.h"
-#include <linux/keyboard.h>
-#include <linux/kd.h>
-#define XK_PUBLISHING
-#include <X11/keysym.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-
-extern int LinuxConsoleFd;
-
-static const KeySym linux_to_x[256] = {
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, XK_Escape,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- XK_space, XK_exclam, XK_quotedbl, XK_numbersign,
- XK_dollar, XK_percent, XK_ampersand, XK_apostrophe,
- XK_parenleft, XK_parenright, XK_asterisk, XK_plus,
- XK_comma, XK_minus, XK_period, XK_slash,
- XK_0, XK_1, XK_2, XK_3,
- XK_4, XK_5, XK_6, XK_7,
- XK_8, XK_9, XK_colon, XK_semicolon,
- XK_less, XK_equal, XK_greater, XK_question,
- XK_at, XK_A, XK_B, XK_C,
- XK_D, XK_E, XK_F, XK_G,
- XK_H, XK_I, XK_J, XK_K,
- XK_L, XK_M, XK_N, XK_O,
- XK_P, XK_Q, XK_R, XK_S,
- XK_T, XK_U, XK_V, XK_W,
- XK_X, XK_Y, XK_Z, XK_bracketleft,
- XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore,
- XK_grave, XK_a, XK_b, XK_c,
- XK_d, XK_e, XK_f, XK_g,
- XK_h, XK_i, XK_j, XK_k,
- XK_l, XK_m, XK_n, XK_o,
- XK_p, XK_q, XK_r, XK_s,
- XK_t, XK_u, XK_v, XK_w,
- XK_x, XK_y, XK_z, XK_braceleft,
- XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling,
- XK_currency, XK_yen, XK_brokenbar, XK_section,
- XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft,
- XK_notsign, XK_hyphen, XK_registered, XK_macron,
- XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior,
- XK_acute, XK_mu, XK_paragraph, XK_periodcentered,
- XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright,
- XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown,
- XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde,
- XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla,
- XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis,
- XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis,
- XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute,
- XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply,
- XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex,
- XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp,
- XK_agrave, XK_aacute, XK_acircumflex, XK_atilde,
- XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla,
- XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis,
- XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis,
- XK_eth, XK_ntilde, XK_ograve, XK_oacute,
- XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division,
- XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex,
- XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis
-};
-
-/*
- * Getting a keycode from scancode
- *
- * With XKB
- * --------
- *
- * We have to enqueue keyboard events using standard X keycodes which correspond
- * to AT scancode + 8; this means that we need to translate the Linux scancode
- * provided by the kernel to an AT scancode -- this translation is not linear
- * and requires that we use a LUT.
- *
- *
- * Without XKB
- * -----------
- *
- * We can use custom keycodes, which makes things simpler; we define our custom
- * keycodes as Linux scancodes + KD_KEY_OFFSET
-*/
-
-/*
- This LUT translates AT scancodes into Linux ones -- the keymap we create
- for the core X keyboard protocol has to be AT-scancode based so that it
- corresponds to the Xkb keymap.
-*/
-#if 0
-static unsigned char at2lnx[] =
-{
- 0x0, /* no valid scancode */
- 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */
- 0x03, /* KEY_2 */ 0x04, /* KEY_3 */
- 0x05, /* KEY_4 */ 0x06, /* KEY_5 */
- 0x07, /* KEY_6 */ 0x08, /* KEY_7 */
- 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */
- 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */
- 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */
- 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */
- 0x11, /* KEY_W */ 0x12, /* KEY_E */
- 0x13, /* KEY_R */ 0x14, /* KEY_T */
- 0x15, /* KEY_Y */ 0x16, /* KEY_U */
- 0x17, /* KEY_I */ 0x18, /* KEY_O */
- 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */
- 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */
- 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */
- 0x1f, /* KEY_S */ 0x20, /* KEY_D */
- 0x21, /* KEY_F */ 0x22, /* KEY_G */
- 0x23, /* KEY_H */ 0x24, /* KEY_J */
- 0x25, /* KEY_K */ 0x26, /* KEY_L */
- 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */
- 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */
- 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */
- 0x2d, /* KEY_X */ 0x2e, /* KEY_C */
- 0x2f, /* KEY_V */ 0x30, /* KEY_B */
- 0x31, /* KEY_N */ 0x32, /* KEY_M */
- 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */
- 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */
- 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */
- 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */
- 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */
- 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */
- 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */
- 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */
- 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */
- 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */
- 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */
- 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */
- 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */
- 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */
- 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */
- 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */
- 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */
- 0x00, /* 0x55 */ 0x56, /* KEY_Less */
- 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */
- 0x66, /* KEY_Home */ 0x67, /* KEY_Up */
- 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */
- 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */
- 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */
- 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */
- 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */
- 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */
- 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */
- 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */
- 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */
- 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */
- 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */
- 0x00, /* 0x71 */ 0x00, /* 0x72 */
- 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */
- 0x00, /* 0x75 */ 0x00, /* 0x76 */
- 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */
- 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */
- 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */
- 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */
- 0x00, /* 0x7f */
-};
-
-#define NUM_AT_KEYS (sizeof(at2lnx)/sizeof(at2lnx[0]))
-#define LNX_KEY_INDEX(n) n < NUM_AT_KEYS ? at2lnx[n] : 0
-
-static unsigned char tbl[KD_MAX_WIDTH] =
-{
- 0,
- 1 << KG_SHIFT,
- (1 << KG_ALTGR),
- (1 << KG_ALTGR) | (1 << KG_SHIFT)
-};
-#endif
-
-static void
-readKernelMapping(KdKeyboardInfo *ki)
-{
-#if 0
- KeySym *k;
- int i, j;
- struct kbentry kbe;
- int minKeyCode, maxKeyCode;
- int row;
- int fd;
-
- if (!ki)
- return;
-
- fd = LinuxConsoleFd;
-
- minKeyCode = NR_KEYS;
- maxKeyCode = 0;
- row = 0;
- ki->keySyms.mapWidth = KD_MAX_WIDTH;
- for (i = 0; i < NR_KEYS && row < KD_MAX_LENGTH; ++i)
- {
- kbe.kb_index = LNX_KEY_INDEX(i);
-
- k = ki->keySyms.map + row * ki->keySyms.mapWidth;
-
- for (j = 0; j < ki->keySyms.mapWidth; ++j)
- {
- unsigned short kval;
-
- k[j] = NoSymbol;
-
- kbe.kb_table = tbl[j];
- kbe.kb_value = 0;
- if (ioctl(fd, KDGKBENT, &kbe))
- continue;
-
- kval = KVAL(kbe.kb_value);
- switch (KTYP(kbe.kb_value))
- {
- case KT_LATIN:
- case KT_LETTER:
- k[j] = linux_to_x[kval];
- break;
-
- case KT_FN:
- if (kval <= 19)
- k[j] = XK_F1 + kval;
- else switch (kbe.kb_value)
- {
- case K_FIND:
- k[j] = XK_Home; /* or XK_Find */
- break;
- case K_INSERT:
- k[j] = XK_Insert;
- break;
- case K_REMOVE:
- k[j] = XK_Delete;
- break;
- case K_SELECT:
- k[j] = XK_End; /* or XK_Select */
- break;
- case K_PGUP:
- k[j] = XK_Prior;
- break;
- case K_PGDN:
- k[j] = XK_Next;
- break;
- case K_HELP:
- k[j] = XK_Help;
- break;
- case K_DO:
- k[j] = XK_Execute;
- break;
- case K_PAUSE:
- k[j] = XK_Pause;
- break;
- case K_MACRO:
- k[j] = XK_Menu;
- break;
- default:
- break;
- }
- break;
-
- case KT_SPEC:
- switch (kbe.kb_value)
- {
- case K_ENTER:
- k[j] = XK_Return;
- break;
- case K_BREAK:
- k[j] = XK_Break;
- break;
- case K_CAPS:
- k[j] = XK_Caps_Lock;
- break;
- case K_NUM:
- k[j] = XK_Num_Lock;
- break;
- case K_HOLD:
- k[j] = XK_Scroll_Lock;
- break;
- case K_COMPOSE:
- k[j] = XK_Multi_key;
- break;
- default:
- break;
- }
- break;
-
- case KT_PAD:
- switch (kbe.kb_value)
- {
- case K_PPLUS:
- k[j] = XK_KP_Add;
- break;
- case K_PMINUS:
- k[j] = XK_KP_Subtract;
- break;
- case K_PSTAR:
- k[j] = XK_KP_Multiply;
- break;
- case K_PSLASH:
- k[j] = XK_KP_Divide;
- break;
- case K_PENTER:
- k[j] = XK_KP_Enter;
- break;
- case K_PCOMMA:
- k[j] = XK_KP_Separator;
- break;
- case K_PDOT:
- k[j] = XK_KP_Decimal;
- break;
- case K_PPLUSMINUS:
- k[j] = XK_KP_Subtract;
- break;
- default:
- if (kval <= 9)
- k[j] = XK_KP_0 + kval;
- break;
- }
- break;
-
- /*
- * KT_DEAD keys are for accelerated diacritical creation.
- */
- case KT_DEAD:
- switch (kbe.kb_value)
- {
- case K_DGRAVE:
- k[j] = XK_dead_grave;
- break;
- case K_DACUTE:
- k[j] = XK_dead_acute;
- break;
- case K_DCIRCM:
- k[j] = XK_dead_circumflex;
- break;
- case K_DTILDE:
- k[j] = XK_dead_tilde;
- break;
- case K_DDIERE:
- k[j] = XK_dead_diaeresis;
- break;
- }
- break;
-
- case KT_CUR:
- switch (kbe.kb_value)
- {
- case K_DOWN:
- k[j] = XK_Down;
- break;
- case K_LEFT:
- k[j] = XK_Left;
- break;
- case K_RIGHT:
- k[j] = XK_Right;
- break;
- case K_UP:
- k[j] = XK_Up;
- break;
- }
- break;
-
- case KT_SHIFT:
- switch (kbe.kb_value)
- {
- case K_ALTGR:
- k[j] = XK_Mode_switch;
- break;
- case K_ALT:
- k[j] = (kbe.kb_index == 0x64 ?
- XK_Alt_R : XK_Alt_L);
- break;
- case K_CTRL:
- k[j] = (kbe.kb_index == 0x61 ?
- XK_Control_R : XK_Control_L);
- break;
- case K_CTRLL:
- k[j] = XK_Control_L;
- break;
- case K_CTRLR:
- k[j] = XK_Control_R;
- break;
- case K_SHIFT:
- k[j] = (kbe.kb_index == 0x36 ?
- XK_Shift_R : XK_Shift_L);
- break;
- case K_SHIFTL:
- k[j] = XK_Shift_L;
- break;
- case K_SHIFTR:
- k[j] = XK_Shift_R;
- break;
- default:
- break;
- }
- break;
-
- /*
- * KT_ASCII keys accumulate a 3 digit decimal number that gets
- * emitted when the shift state changes. We can't emulate that.
- */
- case KT_ASCII:
- break;
-
- case KT_LOCK:
- if (kbe.kb_value == K_SHIFTLOCK)
- k[j] = XK_Shift_Lock;
- break;
-
-#ifdef KT_X
- case KT_X:
- /* depends on new keyboard symbols in file linux/keyboard.h */
- if(kbe.kb_value == K_XMENU) k[j] = XK_Menu;
- if(kbe.kb_value == K_XTELEPHONE) k[j] = XK_telephone;
- break;
-#endif
-#ifdef KT_XF
- case KT_XF:
- /* special linux keysyms which map directly to XF86 keysyms */
- k[j] = (kbe.kb_value & 0xFF) + 0x1008FF00;
- break;
-#endif
-
- default:
- break;
- }
- if (i < minKeyCode)
- minKeyCode = i;
- if (i > maxKeyCode)
- maxKeyCode = i;
- }
-
- if (minKeyCode == NR_KEYS)
- continue;
-
- if (k[3] == k[2]) k[3] = NoSymbol;
- if (k[2] == k[1]) k[2] = NoSymbol;
- if (k[1] == k[0]) k[1] = NoSymbol;
- if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
- if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] =NoSymbol;
- row++;
- }
- ki->minScanCode = minKeyCode;
- ki->maxScanCode = maxKeyCode;
-#endif
-}
-
-/*
- * We need these to handle extended scancodes correctly (I could just use the
- * numbers below, but this makes the code more readable
- */
-
-/* The prefix codes */
-#define KEY_Prefix0 /* special 0x60 */ 96
-#define KEY_Prefix1 /* special 0x61 */ 97
-
-/* The raw scancodes */
-#define KEY_Enter /* Enter 0x1c */ 28
-#define KEY_LCtrl /* Ctrl(left) 0x1d */ 29
-#define KEY_Slash /* / (Slash) ? 0x35 */ 53
-#define KEY_KP_Multiply /* * 0x37 */ 55
-#define KEY_Alt /* Alt(left) 0x38 */ 56
-#define KEY_F3 /* F3 0x3d */ 61
-#define KEY_F4 /* F4 0x3e */ 62
-#define KEY_F5 /* F5 0x3f */ 63
-#define KEY_F6 /* F6 0x40 */ 64
-#define KEY_F7 /* F7 0x41 */ 65
-#define KEY_ScrollLock /* ScrollLock 0x46 */ 70
-#define KEY_KP_7 /* 7 Home 0x47 */ 71
-#define KEY_KP_8 /* 8 Up 0x48 */ 72
-#define KEY_KP_9 /* 9 PgUp 0x49 */ 73
-#define KEY_KP_Minus /* - (Minus) 0x4a */ 74
-#define KEY_KP_4 /* 4 Left 0x4b */ 75
-#define KEY_KP_5 /* 5 0x4c */ 76
-#define KEY_KP_6 /* 6 Right 0x4d */ 77
-#define KEY_KP_Plus /* + (Plus) 0x4e */ 78
-#define KEY_KP_1 /* 1 End 0x4f */ 79
-#define KEY_KP_2 /* 2 Down 0x50 */ 80
-#define KEY_KP_3 /* 3 PgDown 0x51 */ 81
-#define KEY_KP_0 /* 0 Insert 0x52 */ 82
-#define KEY_KP_Decimal /* . (Decimal) Delete 0x53 */ 83
-#define KEY_Home /* Home 0x59 */ 89
-#define KEY_Up /* Up 0x5a */ 90
-#define KEY_PgUp /* PgUp 0x5b */ 91
-#define KEY_Left /* Left 0x5c */ 92
-#define KEY_Begin /* Begin 0x5d */ 93
-#define KEY_Right /* Right 0x5e */ 94
-#define KEY_End /* End 0x5f */ 95
-#define KEY_Down /* Down 0x60 */ 96
-#define KEY_PgDown /* PgDown 0x61 */ 97
-#define KEY_Insert /* Insert 0x62 */ 98
-#define KEY_Delete /* Delete 0x63 */ 99
-#define KEY_KP_Enter /* Enter 0x64 */ 100
-#define KEY_RCtrl /* Ctrl(right) 0x65 */ 101
-#define KEY_Pause /* Pause 0x66 */ 102
-#define KEY_Print /* Print 0x67 */ 103
-#define KEY_KP_Divide /* Divide 0x68 */ 104
-#define KEY_AltLang /* AtlLang(right) 0x69 */ 105
-#define KEY_Break /* Break 0x6a */ 106
-#define KEY_LMeta /* Left Meta 0x6b */ 107
-#define KEY_RMeta /* Right Meta 0x6c */ 108
-#define KEY_Menu /* Menu 0x6d */ 109
-#define KEY_F13 /* F13 0x6e */ 110
-#define KEY_F14 /* F14 0x6f */ 111
-#define KEY_F15 /* F15 0x70 */ 112
-#define KEY_F16 /* F16 0x71 */ 113
-#define KEY_F17 /* F17 0x72 */ 114
-#define KEY_KP_DEC /* KP_DEC 0x73 */ 115
-
-static void
-LinuxKeyboardRead (int fd, void *closure)
-{
- unsigned char buf[256], *b;
- int n;
- unsigned char prefix = 0, scancode = 0;
-
- while ((n = read (fd, buf, sizeof (buf))) > 0) {
- b = buf;
- while (n--) {
- /*
- * With xkb we use RAW mode for reading the console, which allows us
- * process extended scancodes.
- *
- * See if this is a prefix extending the following keycode
- */
- if (!prefix && ((b[0] & 0x7f) == KEY_Prefix0))
- {
- prefix = KEY_Prefix0;
- /* swallow this up */
- b++;
- continue;
- }
- else if (!prefix && ((b[0] & 0x7f) == KEY_Prefix1))
- {
- prefix = KEY_Prefix1;
- /* swallow this up */
- b++;
- continue;
- }
- scancode = b[0] & 0x7f;
-
- switch (prefix) {
- /* from xf86Events.c */
- case KEY_Prefix0:
- {
- switch (scancode) {
- case KEY_KP_7:
- scancode = KEY_Home; break; /* curs home */
- case KEY_KP_8:
- scancode = KEY_Up; break; /* curs up */
- case KEY_KP_9:
- scancode = KEY_PgUp; break; /* curs pgup */
- case KEY_KP_4:
- scancode = KEY_Left; break; /* curs left */
- case KEY_KP_5:
- scancode = KEY_Begin; break; /* curs begin */
- case KEY_KP_6:
- scancode = KEY_Right; break; /* curs right */
- case KEY_KP_1:
- scancode = KEY_End; break; /* curs end */
- case KEY_KP_2:
- scancode = KEY_Down; break; /* curs down */
- case KEY_KP_3:
- scancode = KEY_PgDown; break; /* curs pgdown */
- case KEY_KP_0:
- scancode = KEY_Insert; break; /* curs insert */
- case KEY_KP_Decimal:
- scancode = KEY_Delete; break; /* curs delete */
- case KEY_Enter:
- scancode = KEY_KP_Enter; break; /* keypad enter */
- case KEY_LCtrl:
- scancode = KEY_RCtrl; break; /* right ctrl */
- case KEY_KP_Multiply:
- scancode = KEY_Print; break; /* print */
- case KEY_Slash:
- scancode = KEY_KP_Divide; break; /* keyp divide */
- case KEY_Alt:
- scancode = KEY_AltLang; break; /* right alt */
- case KEY_ScrollLock:
- scancode = KEY_Break; break; /* curs break */
- case 0x5b:
- scancode = KEY_LMeta; break;
- case 0x5c:
- scancode = KEY_RMeta; break;
- case 0x5d:
- scancode = KEY_Menu; break;
- case KEY_F3:
- scancode = KEY_F13; break;
- case KEY_F4:
- scancode = KEY_F14; break;
- case KEY_F5:
- scancode = KEY_F15; break;
- case KEY_F6:
- scancode = KEY_F16; break;
- case KEY_F7:
- scancode = KEY_F17; break;
- case KEY_KP_Plus:
- scancode = KEY_KP_DEC; break;
- /* Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) */
- case 0x2A:
- case 0x36:
- b++;
- prefix = 0;
- continue;
- default:
- /*
- * "Internet" keyboards are generating lots of new
- * codes. Let them pass. There is little consistency
- * between them, so don't bother with symbolic names at
- * this level.
- */
- scancode += 0x78;
- }
- break;
- }
-
- case KEY_Prefix1:
- {
- /* we do no handle these */
- b++;
- prefix = 0;
- continue;
- }
-
- default: /* should not happen*/
- case 0: /* do nothing */
- ;
- }
-
- prefix = 0;
- KdEnqueueKeyboardEvent (closure, scancode, b[0] & 0x80);
- b++;
- }
- }
-}
-
-static int LinuxKbdTrans;
-static struct termios LinuxTermios;
-
-static Status
-LinuxKeyboardEnable (KdKeyboardInfo *ki)
-{
- struct termios nTty;
- unsigned char buf[256];
- int n;
- int fd;
-
- if (!ki)
- return !Success;
-
- fd = LinuxConsoleFd;
- ki->driverPrivate = (void *) fd;
-
- ioctl (fd, KDGKBMODE, &LinuxKbdTrans);
- tcgetattr (fd, &LinuxTermios);
- ioctl(fd, KDSKBMODE, K_RAW);
- nTty = LinuxTermios;
- nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
- nTty.c_oflag = 0;
- nTty.c_cflag = CREAD | CS8;
- nTty.c_lflag = 0;
- nTty.c_cc[VTIME]=0;
- nTty.c_cc[VMIN]=1;
- cfsetispeed(&nTty, 9600);
- cfsetospeed(&nTty, 9600);
- tcsetattr(fd, TCSANOW, &nTty);
- /*
- * Flush any pending keystrokes
- */
- while ((n = read (fd, buf, sizeof (buf))) > 0)
- ;
- KdRegisterFd (fd, LinuxKeyboardRead, ki);
- return Success;
-}
-
-static void
-LinuxKeyboardDisable (KdKeyboardInfo *ki)
-{
- int fd;
-
- if (!ki)
- return;
-
- fd = (int) ki->driverPrivate;
-
- KdUnregisterFd(ki, fd, FALSE);
- ioctl(fd, KDSKBMODE, LinuxKbdTrans);
- tcsetattr(fd, TCSANOW, &LinuxTermios);
-}
-
-static Status
-LinuxKeyboardInit (KdKeyboardInfo *ki)
-{
- if (!ki)
- return !Success;
-
- free(ki->path);
- ki->path = strdup("console");
- free(ki->name);
- ki->name = strdup("Linux console keyboard");
-
- readKernelMapping (ki);
-
- return Success;
-}
-
-static void
-LinuxKeyboardLeds (KdKeyboardInfo *ki, int leds)
-{
- if (!ki)
- return;
-
- ioctl ((int)ki->driverPrivate, KDSETLED, leds & 7);
-}
-
-KdKeyboardDriver LinuxKeyboardDriver = {
- "keyboard",
- .Init = LinuxKeyboardInit,
- .Enable = LinuxKeyboardEnable,
- .Leds = LinuxKeyboardLeds,
- .Disable = LinuxKeyboardDisable,
-};
+/* + * Copyright © 1999 Keith Packard + * XKB integration © 2006 Nokia Corporation, author: Tomas Frydrych <tf@o-hand.com> + * + * LinuxKeyboardRead() XKB code based on xf86KbdLnx.c: + * Copyright © 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * Copyright © 1994-2001 by The XFree86 Project, Inc. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "kdrive.h" +#include <linux/keyboard.h> +#include <linux/kd.h> +#define XK_PUBLISHING +#include <X11/keysym.h> +#include <termios.h> +#include <sys/ioctl.h> + +extern int LinuxConsoleFd; + +static const KeySym linux_to_x[256] = { + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling, + XK_currency, XK_yen, XK_brokenbar, XK_section, + XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, + XK_notsign, XK_hyphen, XK_registered, XK_macron, + XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, + XK_acute, XK_mu, XK_paragraph, XK_periodcentered, + XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, + XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown, + XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, + XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, + XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, + XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, + XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, + XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, + XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, + XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, + XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, + XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, + XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, + XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, + XK_eth, XK_ntilde, XK_ograve, XK_oacute, + XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, + XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, + XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis +}; + +/* + * Getting a keycode from scancode + * + * With XKB + * -------- + * + * We have to enqueue keyboard events using standard X keycodes which correspond + * to AT scancode + 8; this means that we need to translate the Linux scancode + * provided by the kernel to an AT scancode -- this translation is not linear + * and requires that we use a LUT. + * + * + * Without XKB + * ----------- + * + * We can use custom keycodes, which makes things simpler; we define our custom + * keycodes as Linux scancodes + KD_KEY_OFFSET +*/ + +/* + This LUT translates AT scancodes into Linux ones -- the keymap we create + for the core X keyboard protocol has to be AT-scancode based so that it + corresponds to the Xkb keymap. +*/ +#if 0 +static unsigned char at2lnx[] = +{ + 0x0, /* no valid scancode */ + 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */ + 0x03, /* KEY_2 */ 0x04, /* KEY_3 */ + 0x05, /* KEY_4 */ 0x06, /* KEY_5 */ + 0x07, /* KEY_6 */ 0x08, /* KEY_7 */ + 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */ + 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */ + 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */ + 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */ + 0x11, /* KEY_W */ 0x12, /* KEY_E */ + 0x13, /* KEY_R */ 0x14, /* KEY_T */ + 0x15, /* KEY_Y */ 0x16, /* KEY_U */ + 0x17, /* KEY_I */ 0x18, /* KEY_O */ + 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */ + 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */ + 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */ + 0x1f, /* KEY_S */ 0x20, /* KEY_D */ + 0x21, /* KEY_F */ 0x22, /* KEY_G */ + 0x23, /* KEY_H */ 0x24, /* KEY_J */ + 0x25, /* KEY_K */ 0x26, /* KEY_L */ + 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */ + 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */ + 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */ + 0x2d, /* KEY_X */ 0x2e, /* KEY_C */ + 0x2f, /* KEY_V */ 0x30, /* KEY_B */ + 0x31, /* KEY_N */ 0x32, /* KEY_M */ + 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */ + 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */ + 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */ + 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */ + 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */ + 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */ + 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */ + 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */ + 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */ + 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */ + 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */ + 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */ + 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */ + 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */ + 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */ + 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */ + 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */ + 0x00, /* 0x55 */ 0x56, /* KEY_Less */ + 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */ + 0x66, /* KEY_Home */ 0x67, /* KEY_Up */ + 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */ + 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */ + 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */ + 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */ + 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */ + 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */ + 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */ + 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */ + 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */ + 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */ + 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */ + 0x00, /* 0x71 */ 0x00, /* 0x72 */ + 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */ + 0x00, /* 0x75 */ 0x00, /* 0x76 */ + 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */ + 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */ + 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */ + 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */ + 0x00, /* 0x7f */ +}; + +#define NUM_AT_KEYS (sizeof(at2lnx)/sizeof(at2lnx[0])) +#define LNX_KEY_INDEX(n) n < NUM_AT_KEYS ? at2lnx[n] : 0 + +static unsigned char tbl[KD_MAX_WIDTH] = +{ + 0, + 1 << KG_SHIFT, + (1 << KG_ALTGR), + (1 << KG_ALTGR) | (1 << KG_SHIFT) +}; +#endif + +static void +readKernelMapping(KdKeyboardInfo *ki) +{ +#if 0 + KeySym *k; + int i, j; + struct kbentry kbe; + int minKeyCode, maxKeyCode; + int row; + int fd; + + if (!ki) + return; + + fd = LinuxConsoleFd; + + minKeyCode = NR_KEYS; + maxKeyCode = 0; + row = 0; + ki->keySyms.mapWidth = KD_MAX_WIDTH; + for (i = 0; i < NR_KEYS && row < KD_MAX_LENGTH; ++i) + { + kbe.kb_index = LNX_KEY_INDEX(i); + + k = ki->keySyms.map + row * ki->keySyms.mapWidth; + + for (j = 0; j < ki->keySyms.mapWidth; ++j) + { + unsigned short kval; + + k[j] = NoSymbol; + + kbe.kb_table = tbl[j]; + kbe.kb_value = 0; + if (ioctl(fd, KDGKBENT, &kbe)) + continue; + + kval = KVAL(kbe.kb_value); + switch (KTYP(kbe.kb_value)) + { + case KT_LATIN: + case KT_LETTER: + k[j] = linux_to_x[kval]; + break; + + case KT_FN: + if (kval <= 19) + k[j] = XK_F1 + kval; + else switch (kbe.kb_value) + { + case K_FIND: + k[j] = XK_Home; /* or XK_Find */ + break; + case K_INSERT: + k[j] = XK_Insert; + break; + case K_REMOVE: + k[j] = XK_Delete; + break; + case K_SELECT: + k[j] = XK_End; /* or XK_Select */ + break; + case K_PGUP: + k[j] = XK_Prior; + break; + case K_PGDN: + k[j] = XK_Next; + break; + case K_HELP: + k[j] = XK_Help; + break; + case K_DO: + k[j] = XK_Execute; + break; + case K_PAUSE: + k[j] = XK_Pause; + break; + case K_MACRO: + k[j] = XK_Menu; + break; + default: + break; + } + break; + + case KT_SPEC: + switch (kbe.kb_value) + { + case K_ENTER: + k[j] = XK_Return; + break; + case K_BREAK: + k[j] = XK_Break; + break; + case K_CAPS: + k[j] = XK_Caps_Lock; + break; + case K_NUM: + k[j] = XK_Num_Lock; + break; + case K_HOLD: + k[j] = XK_Scroll_Lock; + break; + case K_COMPOSE: + k[j] = XK_Multi_key; + break; + default: + break; + } + break; + + case KT_PAD: + switch (kbe.kb_value) + { + case K_PPLUS: + k[j] = XK_KP_Add; + break; + case K_PMINUS: + k[j] = XK_KP_Subtract; + break; + case K_PSTAR: + k[j] = XK_KP_Multiply; + break; + case K_PSLASH: + k[j] = XK_KP_Divide; + break; + case K_PENTER: + k[j] = XK_KP_Enter; + break; + case K_PCOMMA: + k[j] = XK_KP_Separator; + break; + case K_PDOT: + k[j] = XK_KP_Decimal; + break; + case K_PPLUSMINUS: + k[j] = XK_KP_Subtract; + break; + default: + if (kval <= 9) + k[j] = XK_KP_0 + kval; + break; + } + break; + + /* + * KT_DEAD keys are for accelerated diacritical creation. + */ + case KT_DEAD: + switch (kbe.kb_value) + { + case K_DGRAVE: + k[j] = XK_dead_grave; + break; + case K_DACUTE: + k[j] = XK_dead_acute; + break; + case K_DCIRCM: + k[j] = XK_dead_circumflex; + break; + case K_DTILDE: + k[j] = XK_dead_tilde; + break; + case K_DDIERE: + k[j] = XK_dead_diaeresis; + break; + } + break; + + case KT_CUR: + switch (kbe.kb_value) + { + case K_DOWN: + k[j] = XK_Down; + break; + case K_LEFT: + k[j] = XK_Left; + break; + case K_RIGHT: + k[j] = XK_Right; + break; + case K_UP: + k[j] = XK_Up; + break; + } + break; + + case KT_SHIFT: + switch (kbe.kb_value) + { + case K_ALTGR: + k[j] = XK_Mode_switch; + break; + case K_ALT: + k[j] = (kbe.kb_index == 0x64 ? + XK_Alt_R : XK_Alt_L); + break; + case K_CTRL: + k[j] = (kbe.kb_index == 0x61 ? + XK_Control_R : XK_Control_L); + break; + case K_CTRLL: + k[j] = XK_Control_L; + break; + case K_CTRLR: + k[j] = XK_Control_R; + break; + case K_SHIFT: + k[j] = (kbe.kb_index == 0x36 ? + XK_Shift_R : XK_Shift_L); + break; + case K_SHIFTL: + k[j] = XK_Shift_L; + break; + case K_SHIFTR: + k[j] = XK_Shift_R; + break; + default: + break; + } + break; + + /* + * KT_ASCII keys accumulate a 3 digit decimal number that gets + * emitted when the shift state changes. We can't emulate that. + */ + case KT_ASCII: + break; + + case KT_LOCK: + if (kbe.kb_value == K_SHIFTLOCK) + k[j] = XK_Shift_Lock; + break; + +#ifdef KT_X + case KT_X: + /* depends on new keyboard symbols in file linux/keyboard.h */ + if(kbe.kb_value == K_XMENU) k[j] = XK_Menu; + if(kbe.kb_value == K_XTELEPHONE) k[j] = XK_telephone; + break; +#endif +#ifdef KT_XF + case KT_XF: + /* special linux keysyms which map directly to XF86 keysyms */ + k[j] = (kbe.kb_value & 0xFF) + 0x1008FF00; + break; +#endif + + default: + break; + } + if (i < minKeyCode) + minKeyCode = i; + if (i > maxKeyCode) + maxKeyCode = i; + } + + if (minKeyCode == NR_KEYS) + continue; + + if (k[3] == k[2]) k[3] = NoSymbol; + if (k[2] == k[1]) k[2] = NoSymbol; + if (k[1] == k[0]) k[1] = NoSymbol; + if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; + if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] =NoSymbol; + row++; + } + ki->minScanCode = minKeyCode; + ki->maxScanCode = maxKeyCode; +#endif +} + +/* + * We need these to handle extended scancodes correctly (I could just use the + * numbers below, but this makes the code more readable + */ + +/* The prefix codes */ +#define KEY_Prefix0 /* special 0x60 */ 96 +#define KEY_Prefix1 /* special 0x61 */ 97 + +/* The raw scancodes */ +#define KEY_Enter /* Enter 0x1c */ 28 +#define KEY_LCtrl /* Ctrl(left) 0x1d */ 29 +#define KEY_Slash /* / (Slash) ? 0x35 */ 53 +#define KEY_KP_Multiply /* * 0x37 */ 55 +#define KEY_Alt /* Alt(left) 0x38 */ 56 +#define KEY_F3 /* F3 0x3d */ 61 +#define KEY_F4 /* F4 0x3e */ 62 +#define KEY_F5 /* F5 0x3f */ 63 +#define KEY_F6 /* F6 0x40 */ 64 +#define KEY_F7 /* F7 0x41 */ 65 +#define KEY_ScrollLock /* ScrollLock 0x46 */ 70 +#define KEY_KP_7 /* 7 Home 0x47 */ 71 +#define KEY_KP_8 /* 8 Up 0x48 */ 72 +#define KEY_KP_9 /* 9 PgUp 0x49 */ 73 +#define KEY_KP_Minus /* - (Minus) 0x4a */ 74 +#define KEY_KP_4 /* 4 Left 0x4b */ 75 +#define KEY_KP_5 /* 5 0x4c */ 76 +#define KEY_KP_6 /* 6 Right 0x4d */ 77 +#define KEY_KP_Plus /* + (Plus) 0x4e */ 78 +#define KEY_KP_1 /* 1 End 0x4f */ 79 +#define KEY_KP_2 /* 2 Down 0x50 */ 80 +#define KEY_KP_3 /* 3 PgDown 0x51 */ 81 +#define KEY_KP_0 /* 0 Insert 0x52 */ 82 +#define KEY_KP_Decimal /* . (Decimal) Delete 0x53 */ 83 +#define KEY_Home /* Home 0x59 */ 89 +#define KEY_Up /* Up 0x5a */ 90 +#define KEY_PgUp /* PgUp 0x5b */ 91 +#define KEY_Left /* Left 0x5c */ 92 +#define KEY_Begin /* Begin 0x5d */ 93 +#define KEY_Right /* Right 0x5e */ 94 +#define KEY_End /* End 0x5f */ 95 +#define KEY_Down /* Down 0x60 */ 96 +#define KEY_PgDown /* PgDown 0x61 */ 97 +#define KEY_Insert /* Insert 0x62 */ 98 +#define KEY_Delete /* Delete 0x63 */ 99 +#define KEY_KP_Enter /* Enter 0x64 */ 100 +#define KEY_RCtrl /* Ctrl(right) 0x65 */ 101 +#define KEY_Pause /* Pause 0x66 */ 102 +#define KEY_Print /* Print 0x67 */ 103 +#define KEY_KP_Divide /* Divide 0x68 */ 104 +#define KEY_AltLang /* AtlLang(right) 0x69 */ 105 +#define KEY_Break /* Break 0x6a */ 106 +#define KEY_LMeta /* Left Meta 0x6b */ 107 +#define KEY_RMeta /* Right Meta 0x6c */ 108 +#define KEY_Menu /* Menu 0x6d */ 109 +#define KEY_F13 /* F13 0x6e */ 110 +#define KEY_F14 /* F14 0x6f */ 111 +#define KEY_F15 /* F15 0x70 */ 112 +#define KEY_F16 /* F16 0x71 */ 113 +#define KEY_F17 /* F17 0x72 */ 114 +#define KEY_KP_DEC /* KP_DEC 0x73 */ 115 + +static void +LinuxKeyboardRead (int fd, void *closure) +{ + unsigned char buf[256], *b; + int n; + unsigned char prefix = 0, scancode = 0; + + while ((n = read (fd, buf, sizeof (buf))) > 0) { + b = buf; + while (n--) { + /* + * With xkb we use RAW mode for reading the console, which allows us + * process extended scancodes. + * + * See if this is a prefix extending the following keycode + */ + if (!prefix && ((b[0] & 0x7f) == KEY_Prefix0)) + { + prefix = KEY_Prefix0; + /* swallow this up */ + b++; + continue; + } + else if (!prefix && ((b[0] & 0x7f) == KEY_Prefix1)) + { + prefix = KEY_Prefix1; + /* swallow this up */ + b++; + continue; + } + scancode = b[0] & 0x7f; + + switch (prefix) { + /* from xf86Events.c */ + case KEY_Prefix0: + { + switch (scancode) { + case KEY_KP_7: + scancode = KEY_Home; break; /* curs home */ + case KEY_KP_8: + scancode = KEY_Up; break; /* curs up */ + case KEY_KP_9: + scancode = KEY_PgUp; break; /* curs pgup */ + case KEY_KP_4: + scancode = KEY_Left; break; /* curs left */ + case KEY_KP_5: + scancode = KEY_Begin; break; /* curs begin */ + case KEY_KP_6: + scancode = KEY_Right; break; /* curs right */ + case KEY_KP_1: + scancode = KEY_End; break; /* curs end */ + case KEY_KP_2: + scancode = KEY_Down; break; /* curs down */ + case KEY_KP_3: + scancode = KEY_PgDown; break; /* curs pgdown */ + case KEY_KP_0: + scancode = KEY_Insert; break; /* curs insert */ + case KEY_KP_Decimal: + scancode = KEY_Delete; break; /* curs delete */ + case KEY_Enter: + scancode = KEY_KP_Enter; break; /* keypad enter */ + case KEY_LCtrl: + scancode = KEY_RCtrl; break; /* right ctrl */ + case KEY_KP_Multiply: + scancode = KEY_Print; break; /* print */ + case KEY_Slash: + scancode = KEY_KP_Divide; break; /* keyp divide */ + case KEY_Alt: + scancode = KEY_AltLang; break; /* right alt */ + case KEY_ScrollLock: + scancode = KEY_Break; break; /* curs break */ + case 0x5b: + scancode = KEY_LMeta; break; + case 0x5c: + scancode = KEY_RMeta; break; + case 0x5d: + scancode = KEY_Menu; break; + case KEY_F3: + scancode = KEY_F13; break; + case KEY_F4: + scancode = KEY_F14; break; + case KEY_F5: + scancode = KEY_F15; break; + case KEY_F6: + scancode = KEY_F16; break; + case KEY_F7: + scancode = KEY_F17; break; + case KEY_KP_Plus: + scancode = KEY_KP_DEC; break; + /* Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) */ + case 0x2A: + case 0x36: + b++; + prefix = 0; + continue; + default: + /* + * "Internet" keyboards are generating lots of new + * codes. Let them pass. There is little consistency + * between them, so don't bother with symbolic names at + * this level. + */ + scancode += 0x78; + } + break; + } + + case KEY_Prefix1: + { + /* we do no handle these */ + b++; + prefix = 0; + continue; + } + + default: /* should not happen*/ + case 0: /* do nothing */ + ; + } + + prefix = 0; + KdEnqueueKeyboardEvent (closure, scancode, b[0] & 0x80); + b++; + } + } +} + +static int LinuxKbdTrans; +static struct termios LinuxTermios; + +static Status +LinuxKeyboardEnable (KdKeyboardInfo *ki) +{ + struct termios nTty; + unsigned char buf[256]; + int n; + int fd; + + if (!ki) + return !Success; + + fd = LinuxConsoleFd; + ki->driverPrivate = (void *) fd; + + ioctl (fd, KDGKBMODE, &LinuxKbdTrans); + tcgetattr (fd, &LinuxTermios); + ioctl(fd, KDSKBMODE, K_RAW); + nTty = LinuxTermios; + nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + nTty.c_oflag = 0; + nTty.c_cflag = CREAD | CS8; + nTty.c_lflag = 0; + nTty.c_cc[VTIME]=0; + nTty.c_cc[VMIN]=1; + cfsetispeed(&nTty, 9600); + cfsetospeed(&nTty, 9600); + tcsetattr(fd, TCSANOW, &nTty); + /* + * Flush any pending keystrokes + */ + while ((n = read (fd, buf, sizeof (buf))) > 0) + ; + KdRegisterFd (fd, LinuxKeyboardRead, ki); + return Success; +} + +static void +LinuxKeyboardDisable (KdKeyboardInfo *ki) +{ + int fd; + + if (!ki) + return; + + fd = (int) ki->driverPrivate; + + KdUnregisterFd(ki, fd, FALSE); + ioctl(fd, KDSKBMODE, LinuxKbdTrans); + tcsetattr(fd, TCSANOW, &LinuxTermios); +} + +static Status +LinuxKeyboardInit (KdKeyboardInfo *ki) +{ + if (!ki) + return !Success; + + free(ki->path); + ki->path = strdup("console"); + free(ki->name); + ki->name = strdup("Linux console keyboard"); + + readKernelMapping (ki); + + return Success; +} + +static void +LinuxKeyboardLeds (KdKeyboardInfo *ki, int leds) +{ + if (!ki) + return; + + ioctl ((int)ki->driverPrivate, KDSETLED, leds & 7); +} + +KdKeyboardDriver LinuxKeyboardDriver = { + "keyboard", + .Init = LinuxKeyboardInit, + .Enable = LinuxKeyboardEnable, + .Leds = LinuxKeyboardLeds, + .Disable = LinuxKeyboardDisable, +}; diff --git a/xorg-server/hw/kdrive/linux/linux.c b/xorg-server/hw/kdrive/linux/linux.c index 9863c1424..a53db4965 100644 --- a/xorg-server/hw/kdrive/linux/linux.c +++ b/xorg-server/hw/kdrive/linux/linux.c @@ -1,5 +1,5 @@ /* - * Copyright © 1999 Keith Packard + * Copyright © 1999 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg-server/hw/kdrive/linux/mouse.c b/xorg-server/hw/kdrive/linux/mouse.c index 2e39d240e..93c207817 100644 --- a/xorg-server/hw/kdrive/linux/mouse.c +++ b/xorg-server/hw/kdrive/linux/mouse.c @@ -1,1030 +1,1030 @@ -/*
- * Copyright © 2001 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include <errno.h>
-#include <termios.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/Xpoll.h>
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "kdrive.h"
-
-#undef DEBUG
-#undef DEBUG_BYTES
-#define KBUFIO_SIZE 256
-#define MOUSE_TIMEOUT 100
-
-typedef struct _kbufio {
- int fd;
- unsigned char buf[KBUFIO_SIZE];
- int avail;
- int used;
-} Kbufio;
-
-static Bool
-MouseWaitForReadable (int fd, int timeout)
-{
- fd_set set;
- struct timeval tv, *tp;
- int n;
- CARD32 done;
-
- done = GetTimeInMillis () + timeout;
- for (;;)
- {
- FD_ZERO (&set);
- FD_SET (fd, &set);
- if (timeout == -1)
- tp = 0;
- else
- {
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- tp = &tv;
- }
- n = select (fd + 1, &set, 0, 0, tp);
- if (n > 0)
- return TRUE;
- if (n < 0 && (errno == EAGAIN || errno == EINTR))
- {
- timeout = (int) (done - GetTimeInMillis ());
- if (timeout > 0)
- continue;
- }
- break;
- }
- return FALSE;
-}
-
-static int
-MouseReadByte (Kbufio *b, int timeout)
-{
- int n;
- if (b->avail <= b->used)
- {
- if (timeout && !MouseWaitForReadable (b->fd, timeout))
- {
-#ifdef DEBUG_BYTES
- ErrorF ("\tTimeout %d\n", timeout);
-#endif
- return -1;
- }
- n = read (b->fd, b->buf, KBUFIO_SIZE);
- if (n <= 0)
- return -1;
- b->avail = n;
- b->used = 0;
- }
-#ifdef DEBUG_BYTES
- ErrorF ("\tget %02x\n", b->buf[b->used]);
-#endif
- return b->buf[b->used++];
-}
-
-#if NOTUSED
-static int
-MouseFlush (Kbufio *b, char *buf, int size)
-{
- CARD32 now = GetTimeInMillis ();
- CARD32 done = now + 100;
- int c;
- int n = 0;
-
- while ((c = MouseReadByte (b, done - now)) != -1)
- {
- if (buf)
- {
- if (n == size)
- {
- memmove (buf, buf + 1, size - 1);
- n--;
- }
- buf[n++] = c;
- }
- now = GetTimeInMillis ();
- if ((INT32) (now - done) >= 0)
- break;
- }
- return n;
-}
-
-static int
-MousePeekByte (Kbufio *b, int timeout)
-{
- int c;
-
- c = MouseReadByte (b, timeout);
- if (c != -1)
- --b->used;
- return c;
-}
-#endif /* NOTUSED */
-
-static Bool
-MouseWaitForWritable (int fd, int timeout)
-{
- fd_set set;
- struct timeval tv, *tp;
- int n;
-
- FD_ZERO (&set);
- FD_SET (fd, &set);
- if (timeout == -1)
- tp = 0;
- else
- {
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- tp = &tv;
- }
- n = select (fd + 1, 0, &set, 0, tp);
- if (n > 0)
- return TRUE;
- return FALSE;
-}
-
-static Bool
-MouseWriteByte (int fd, unsigned char c, int timeout)
-{
- int ret;
-
-#ifdef DEBUG_BYTES
- ErrorF ("\tput %02x\n", c);
-#endif
- for (;;)
- {
- ret = write (fd, &c, 1);
- if (ret == 1)
- return TRUE;
- if (ret == 0)
- return FALSE;
- if (errno != EWOULDBLOCK)
- return FALSE;
- if (!MouseWaitForWritable (fd, timeout))
- return FALSE;
- }
-}
-
-static Bool
-MouseWriteBytes (int fd, unsigned char *c, int n, int timeout)
-{
- while (n--)
- if (!MouseWriteByte (fd, *c++, timeout))
- return FALSE;
- return TRUE;
-}
-
-#define MAX_MOUSE 10 /* maximum length of mouse protocol */
-#define MAX_SKIP 16 /* number of error bytes before switching */
-#define MAX_VALID 4 /* number of valid packets before accepting */
-
-typedef struct _kmouseProt {
- char *name;
- Bool (*Complete) (KdPointerInfo *pi, unsigned char *ev, int ne);
- int (*Valid) (KdPointerInfo *pi, unsigned char *ev, int ne);
- Bool (*Parse) (KdPointerInfo *pi, unsigned char *ev, int ne);
- Bool (*Init) (KdPointerInfo *pi);
- unsigned char headerMask, headerValid;
- unsigned char dataMask, dataValid;
- Bool tty;
- unsigned int c_iflag;
- unsigned int c_oflag;
- unsigned int c_lflag;
- unsigned int c_cflag;
- unsigned int speed;
- unsigned char *init;
- unsigned long state;
-} KmouseProt;
-
-typedef enum _kmouseStage {
- MouseBroken, MouseTesting, MouseWorking
-} KmouseStage;
-
-typedef struct _kmouse {
- Kbufio iob;
- const KmouseProt *prot;
- int i_prot;
- KmouseStage stage; /* protocol verification stage */
- Bool tty; /* mouse device is a tty */
- int valid; /* sequential valid events */
- int tested; /* bytes scanned during Testing phase */
- int invalid;/* total invalid bytes for this protocol */
- unsigned long state; /* private per protocol, init to prot->state */
-} Kmouse;
-
-static int mouseValid (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- const KmouseProt *prot = km->prot;
- int i;
-
- for (i = 0; i < ne; i++)
- if ((ev[i] & prot->headerMask) == prot->headerValid)
- break;
- if (i != 0)
- return i;
- for (i = 1; i < ne; i++)
- if ((ev[i] & prot->dataMask) != prot->dataValid)
- return -1;
- return 0;
-}
-
-static Bool threeComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- return ne == 3;
-}
-
-static Bool fourComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- return ne == 4;
-}
-
-static Bool fiveComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- return ne == 5;
-}
-
-static Bool MouseReasonable (KdPointerInfo *pi, unsigned long flags, int dx, int dy)
-{
- Kmouse *km = pi->driverPrivate;
-
- if (km->stage == MouseWorking)
- return TRUE;
- if (dx < -50 || dx > 50)
- {
-#ifdef DEBUG
- ErrorF ("Large X %d\n", dx);
-#endif
- return FALSE;
- }
- if (dy < -50 || dy > 50)
- {
-#ifdef DEBUG
- ErrorF ("Large Y %d\n", dy);
-#endif
- return FALSE;
- }
- return TRUE;
-}
-
-/*
- * Standard PS/2 mouse protocol
- */
-static Bool ps2Parse (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- int dx, dy, dz;
- unsigned long flags;
- unsigned long flagsrelease = 0;
-
- flags = KD_MOUSE_DELTA;
- if (ev[0] & 4)
- flags |= KD_BUTTON_2;
- if (ev[0] & 2)
- flags |= KD_BUTTON_3;
- if (ev[0] & 1)
- flags |= KD_BUTTON_1;
-
- if (ne > 3)
- {
- dz = (int) (signed char) ev[3];
- if (dz < 0)
- {
- flags |= KD_BUTTON_4;
- flagsrelease = KD_BUTTON_4;
- }
- else if (dz > 0)
- {
- flags |= KD_BUTTON_5;
- flagsrelease = KD_BUTTON_5;
- }
- }
-
- dx = ev[1];
- if (ev[0] & 0x10)
- dx -= 256;
- dy = ev[2];
- if (ev[0] & 0x20)
- dy -= 256;
- dy = -dy;
- if (!MouseReasonable (pi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- {
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- if (flagsrelease)
- {
- flags &= ~flagsrelease;
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- }
- }
- return TRUE;
-}
-
-static Bool ps2Init (KdPointerInfo *pi);
-
-static const KmouseProt ps2Prot = {
- "ps/2",
- threeComplete, mouseValid, ps2Parse, ps2Init,
- 0x08, 0x08, 0x00, 0x00,
- FALSE
-};
-
-static const KmouseProt imps2Prot = {
- "imps/2",
- fourComplete, mouseValid, ps2Parse, ps2Init,
- 0x08, 0x08, 0x00, 0x00,
- FALSE
-};
-
-static const KmouseProt exps2Prot = {
- "exps/2",
- fourComplete, mouseValid, ps2Parse, ps2Init,
- 0x08, 0x08, 0x00, 0x00,
- FALSE
-};
-
-/*
- * Once the mouse is known to speak ps/2 protocol, go and find out
- * what advanced capabilities it has and turn them on
- */
-
-/* these extracted from FreeBSD 4.3 sys/dev/kbd/atkbdcreg.h */
-
-/* aux device commands (sent to KBD_DATA_PORT) */
-#define PSMC_SET_SCALING11 0x00e6
-#define PSMC_SET_SCALING21 0x00e7
-#define PSMC_SET_RESOLUTION 0x00e8
-#define PSMC_SEND_DEV_STATUS 0x00e9
-#define PSMC_SET_STREAM_MODE 0x00ea
-#define PSMC_SEND_DEV_DATA 0x00eb
-#define PSMC_SET_REMOTE_MODE 0x00f0
-#define PSMC_SEND_DEV_ID 0x00f2
-#define PSMC_SET_SAMPLING_RATE 0x00f3
-#define PSMC_ENABLE_DEV 0x00f4
-#define PSMC_DISABLE_DEV 0x00f5
-#define PSMC_SET_DEFAULTS 0x00f6
-#define PSMC_RESET_DEV 0x00ff
-
-/* PSMC_SET_RESOLUTION argument */
-#define PSMD_RES_LOW 0 /* typically 25ppi */
-#define PSMD_RES_MEDIUM_LOW 1 /* typically 50ppi */
-#define PSMD_RES_MEDIUM_HIGH 2 /* typically 100ppi (default) */
-#define PSMD_RES_HIGH 3 /* typically 200ppi */
-#define PSMD_MAX_RESOLUTION PSMD_RES_HIGH
-
-/* PSMC_SET_SAMPLING_RATE */
-#define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */
-
-/* aux device ID */
-#define PSM_MOUSE_ID 0
-#define PSM_BALLPOINT_ID 2
-#define PSM_INTELLI_ID 3
-#define PSM_EXPLORER_ID 4
-#define PSM_4DMOUSE_ID 6
-#define PSM_4DPLUS_ID 8
-
-static unsigned char ps2_init[] = {
- PSMC_ENABLE_DEV,
- 0,
-};
-
-#define NINIT_PS2 1
-
-static unsigned char wheel_3button_init[] = {
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 100,
- PSMC_SET_SAMPLING_RATE, 80,
- PSMC_SEND_DEV_ID,
- 0,
-};
-
-#define NINIT_IMPS2 4
-
-static unsigned char wheel_5button_init[] = {
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 100,
- PSMC_SET_SAMPLING_RATE, 80,
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 80,
- PSMC_SEND_DEV_ID,
- 0
-};
-
-#define NINIT_EXPS2 7
-
-static unsigned char intelli_init[] = {
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 100,
- PSMC_SET_SAMPLING_RATE, 80,
- 0
-};
-
-#define NINIT_INTELLI 3
-
-static int
-ps2SkipInit (KdPointerInfo *pi, int ninit, Bool ret_next)
-{
- Kmouse *km = pi->driverPrivate;
- int c = -1;
- int skipping;
- Bool waiting;
-
- skipping = 0;
- waiting = FALSE;
- while (ninit || ret_next)
- {
- c = MouseReadByte (&km->iob, MOUSE_TIMEOUT);
- if (c == -1)
- break;
- /* look for ACK */
- if (c == 0xfa)
- {
- ninit--;
- if (ret_next)
- waiting = TRUE;
- }
- /* look for packet start -- not the response */
- else if ((c & 0x08) == 0x08)
- waiting = FALSE;
- else if (waiting)
- break;
- }
- return c;
-}
-
-static Bool
-ps2Init (KdPointerInfo *pi)
-{
- Kmouse *km = pi->driverPrivate;
- int skipping;
- Bool waiting;
- int id;
- unsigned char *init;
- int ninit;
-
- /* Send Intellimouse initialization sequence */
- MouseWriteBytes (km->iob.fd, intelli_init, strlen ((char *) intelli_init), 100);
- /*
- * Send ID command
- */
- if (!MouseWriteByte (km->iob.fd, PSMC_SEND_DEV_ID, 100))
- return FALSE;
- skipping = 0;
- waiting = FALSE;
- id = ps2SkipInit (pi, 0, TRUE);
- switch (id) {
- case 3:
- init = wheel_3button_init;
- ninit = NINIT_IMPS2;
- km->prot = &imps2Prot;
- break;
- case 4:
- init = wheel_5button_init;
- ninit = NINIT_EXPS2;
- km->prot = &exps2Prot;
- break;
- default:
- init = ps2_init;
- ninit = NINIT_PS2;
- km->prot = &ps2Prot;
- break;
- }
- if (init)
- MouseWriteBytes (km->iob.fd, init, strlen ((char *) init), 100);
- /*
- * Flush out the available data to eliminate responses to the
- * initialization string. Make sure any partial event is
- * skipped
- */
- (void) ps2SkipInit (pi, ninit, FALSE);
- return TRUE;
-}
-
-static Bool busParse (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- int dx, dy;
- unsigned long flags;
-
- flags = KD_MOUSE_DELTA;
- dx = (signed char) ev[1];
- dy = -(signed char) ev[2];
- if ((ev[0] & 4) == 0)
- flags |= KD_BUTTON_1;
- if ((ev[0] & 2) == 0)
- flags |= KD_BUTTON_2;
- if ((ev[0] & 1) == 0)
- flags |= KD_BUTTON_3;
- if (!MouseReasonable (pi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- return TRUE;
-}
-
-static const KmouseProt busProt = {
- "bus",
- threeComplete, mouseValid, busParse, 0,
- 0xf8, 0x00, 0x00, 0x00,
- FALSE
-};
-
-/*
- * Standard MS serial protocol, three bytes
- */
-
-static Bool msParse (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- int dx, dy;
- unsigned long flags;
-
- flags = KD_MOUSE_DELTA;
-
- if (ev[0] & 0x20)
- flags |= KD_BUTTON_1;
- if (ev[0] & 0x10)
- flags |= KD_BUTTON_3;
-
- dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
- dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
- if (!MouseReasonable (pi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- return TRUE;
-}
-
-static const KmouseProt msProt = {
- "ms",
- threeComplete, mouseValid, msParse, 0,
- 0xc0, 0x40, 0xc0, 0x00,
- TRUE,
- IGNPAR,
- 0,
- 0,
- CS7 | CSTOPB | CREAD | CLOCAL,
- B1200,
-};
-
-/*
- * Logitech mice send 3 or 4 bytes, the only way to tell is to look at the
- * first byte of a synchronized protocol stream and see if it's got
- * any bits turned on that can't occur in that fourth byte
- */
-static Bool logiComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
-
- if ((ev[0] & 0x40) == 0x40)
- return ne == 3;
- if (km->stage != MouseBroken && (ev[0] & ~0x23) == 0)
- return ne == 1;
- return FALSE;
-}
-
-static int logiValid (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- const KmouseProt *prot = km->prot;
- int i;
-
- for (i = 0; i < ne; i++)
- {
- if ((ev[i] & 0x40) == 0x40)
- break;
- if (km->stage != MouseBroken && (ev[i] & ~0x23) == 0)
- break;
- }
- if (i != 0)
- return i;
- for (i = 1; i < ne; i++)
- if ((ev[i] & prot->dataMask) != prot->dataValid)
- return -1;
- return 0;
-}
-
-static Bool logiParse (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- int dx, dy;
- unsigned long flags;
-
- flags = KD_MOUSE_DELTA;
-
- if (ne == 3)
- {
- if (ev[0] & 0x20)
- flags |= KD_BUTTON_1;
- if (ev[0] & 0x10)
- flags |= KD_BUTTON_3;
-
- dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
- dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
- flags |= km->state & KD_BUTTON_2;
- }
- else
- {
- if (ev[0] & 0x20)
- flags |= KD_BUTTON_2;
- dx = 0;
- dy = 0;
- flags |= km->state & (KD_BUTTON_1|KD_BUTTON_3);
- }
-
- if (!MouseReasonable (pi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- return TRUE;
-}
-
-static const KmouseProt logiProt = {
- "logitech",
- logiComplete, logiValid, logiParse, 0,
- 0xc0, 0x40, 0xc0, 0x00,
- TRUE,
- IGNPAR,
- 0,
- 0,
- CS7 | CSTOPB | CREAD | CLOCAL,
- B1200,
-};
-
-/*
- * Mouse systems protocol, 5 bytes
- */
-static Bool mscParse (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- int dx, dy;
- unsigned long flags;
-
- flags = KD_MOUSE_DELTA;
-
- if (!(ev[0] & 0x4))
- flags |= KD_BUTTON_1;
- if (!(ev[0] & 0x2))
- flags |= KD_BUTTON_2;
- if (!(ev[0] & 0x1))
- flags |= KD_BUTTON_3;
- dx = (signed char)(ev[1]) + (signed char)(ev[3]);
- dy = - ((signed char)(ev[2]) + (signed char)(ev[4]));
-
- if (!MouseReasonable (pi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- return TRUE;
-}
-
-static const KmouseProt mscProt = {
- "msc",
- fiveComplete, mouseValid, mscParse, 0,
- 0xf8, 0x80, 0x00, 0x00,
- TRUE,
- IGNPAR,
- 0,
- 0,
- CS8 | CSTOPB | CREAD | CLOCAL,
- B1200,
-};
-
-/*
- * Use logitech before ms -- they're the same except that
- * logitech sometimes has a fourth byte
- */
-static const KmouseProt *kmouseProts[] = {
- &ps2Prot, &imps2Prot, &exps2Prot, &busProt, &logiProt, &msProt, &mscProt,
-};
-
-#define NUM_PROT (sizeof (kmouseProts) / sizeof (kmouseProts[0]))
-
-static void
-MouseInitProtocol (Kmouse *km)
-{
- int ret;
- struct termios t;
-
- if (km->prot->tty)
- {
- ret = tcgetattr (km->iob.fd, &t);
-
- if (ret >= 0)
- {
- t.c_iflag = km->prot->c_iflag;
- t.c_oflag = km->prot->c_oflag;
- t.c_lflag = km->prot->c_lflag;
- t.c_cflag = km->prot->c_cflag;
- cfsetispeed (&t, km->prot->speed);
- cfsetospeed (&t, km->prot->speed);
- ret = tcsetattr (km->iob.fd, TCSANOW, &t);
- }
- }
- km->stage = MouseBroken;
- km->valid = 0;
- km->tested = 0;
- km->invalid = 0;
- km->state = km->prot->state;
-}
-
-static void
-MouseFirstProtocol (Kmouse *km, char *prot)
-{
- if (prot)
- {
- for (km->i_prot = 0; km->i_prot < NUM_PROT; km->i_prot++)
- if (!strcmp (prot, kmouseProts[km->i_prot]->name))
- break;
- if (km->i_prot == NUM_PROT)
- {
- int i;
- ErrorF ("Unknown mouse protocol \"%s\". Pick one of:", prot);
- for (i = 0; i < NUM_PROT; i++)
- ErrorF (" %s", kmouseProts[i]->name);
- ErrorF ("\n");
- }
- else
- {
- km->prot = kmouseProts[km->i_prot];
- if (km->tty && !km->prot->tty)
- ErrorF ("Mouse device is serial port, protocol %s is not serial protocol\n",
- prot);
- else if (!km->tty && km->prot->tty)
- ErrorF ("Mouse device is not serial port, protocol %s is serial protocol\n",
- prot);
- }
- }
- if (!km->prot)
- {
- for (km->i_prot = 0; kmouseProts[km->i_prot]->tty != km->tty; km->i_prot++)
- ;
- km->prot = kmouseProts[km->i_prot];
- }
- MouseInitProtocol (km);
-}
-
-static void
-MouseNextProtocol (Kmouse *km)
-{
- do
- {
- if (!km->prot)
- km->i_prot = 0;
- else
- if (++km->i_prot == NUM_PROT) km->i_prot = 0;
- km->prot = kmouseProts[km->i_prot];
- } while (km->prot->tty != km->tty);
- MouseInitProtocol (km);
- ErrorF ("Switching to mouse protocol \"%s\"\n", km->prot->name);
-}
-
-static void
-MouseRead (int mousePort, void *closure)
-{
- KdPointerInfo *pi = closure;
- Kmouse *km = pi->driverPrivate;
- unsigned char event[MAX_MOUSE];
- int ne;
- int c;
- int i;
- int timeout;
-
- timeout = 0;
- ne = 0;
- for(;;)
- {
- c = MouseReadByte (&km->iob, timeout);
- if (c == -1)
- {
- if (ne)
- {
- km->invalid += ne + km->tested;
- km->valid = 0;
- km->tested = 0;
- km->stage = MouseBroken;
- }
- break;
- }
- event[ne++] = c;
- i = (*km->prot->Valid) (pi, event, ne);
- if (i != 0)
- {
-#ifdef DEBUG
- ErrorF ("Mouse protocol %s broken %d of %d bytes bad\n",
- km->prot->name, i > 0 ? i : ne, ne);
-#endif
- if (i > 0 && i < ne)
- {
- ne -= i;
- memmove (event, event + i, ne);
- }
- else
- {
- i = ne;
- ne = 0;
- }
- km->invalid += i + km->tested;
- km->valid = 0;
- km->tested = 0;
- if (km->stage == MouseWorking)
- km->i_prot--;
- km->stage = MouseBroken;
- if (km->invalid > MAX_SKIP)
- {
- MouseNextProtocol (km);
- ne = 0;
- }
- timeout = 0;
- }
- else
- {
- if ((*km->prot->Complete) (pi, event, ne))
- {
- if ((*km->prot->Parse) (pi, event, ne))
- {
- switch (km->stage)
- {
- case MouseBroken:
-#ifdef DEBUG
- ErrorF ("Mouse protocol %s seems OK\n",
- km->prot->name);
-#endif
- /* do not zero invalid to accumulate invalid bytes */
- km->valid = 0;
- km->tested = 0;
- km->stage = MouseTesting;
- /* fall through ... */
- case MouseTesting:
- km->valid++;
- km->tested += ne;
- if (km->valid > MAX_VALID)
- {
-#ifdef DEBUG
- ErrorF ("Mouse protocol %s working\n",
- km->prot->name);
-#endif
- km->stage = MouseWorking;
- km->invalid = 0;
- km->tested = 0;
- km->valid = 0;
- if (km->prot->Init && !(*km->prot->Init) (pi))
- km->stage = MouseBroken;
- }
- break;
- case MouseWorking:
- break;
- }
- }
- else
- {
- km->invalid += ne + km->tested;
- km->valid = 0;
- km->tested = 0;
- km->stage = MouseBroken;
- }
- ne = 0;
- timeout = 0;
- }
- else
- timeout = MOUSE_TIMEOUT;
- }
- }
-}
-
-int MouseInputType;
-
-char *kdefaultMouse[] = {
- "/dev/input/mice",
- "/dev/mouse",
- "/dev/psaux",
- "/dev/adbmouse",
- "/dev/ttyS0",
- "/dev/ttyS1",
-};
-
-#define NUM_DEFAULT_MOUSE (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0]))
-
-static Status
-MouseInit (KdPointerInfo *pi)
-{
- int i;
- int fd;
- Kmouse *km;
-
- if (!pi)
- return BadImplementation;
-
- if (!pi->path || strcmp(pi->path, "auto") == 0) {
- for (i = 0; i < NUM_DEFAULT_MOUSE; i++) {
- fd = open (kdefaultMouse[i], 2);
- if (fd >= 0) {
- pi->path = strdup (kdefaultMouse[i]);
- break;
- }
- }
- }
- else {
- fd = open (pi->path, 2);
- }
-
- if (fd < 0)
- return BadMatch;
-
- close(fd);
-
- km = (Kmouse *) malloc(sizeof (Kmouse));
- if (km) {
- km->iob.avail = km->iob.used = 0;
- MouseFirstProtocol(km, pi->protocol ? pi->protocol : "exps/2");
- /* MouseFirstProtocol sets state to MouseBroken for later protocol
- * checks. Skip these checks if a protocol was supplied */
- if (pi->protocol)
- km->state = MouseWorking;
- km->i_prot = 0;
- km->tty = isatty (fd);
- km->iob.fd = -1;
- pi->driverPrivate = km;
- }
- else {
- close (fd);
- return BadAlloc;
- }
-
- return Success;
-}
-
-static Status
-MouseEnable (KdPointerInfo *pi)
-{
- Kmouse *km;
-
- if (!pi || !pi->driverPrivate || !pi->path)
- return BadImplementation;
-
- km = pi->driverPrivate;
-
- km->iob.fd = open(pi->path, 2);
- if (km->iob.fd < 0)
- return BadMatch;
-
- if (!KdRegisterFd (km->iob.fd, MouseRead, pi))
- {
- close(km->iob.fd);
- return BadAlloc;
- }
-
- return Success;
-}
-
-static void
-MouseDisable (KdPointerInfo *pi)
-{
- Kmouse *km;
- if (!pi || !pi->driverPrivate)
- return;
-
- km = pi->driverPrivate;
- KdUnregisterFd (pi, km->iob.fd, TRUE);
-}
-
-static void
-MouseFini (KdPointerInfo *pi)
-{
- free(pi->driverPrivate);
- pi->driverPrivate = NULL;
-}
-
-KdPointerDriver LinuxMouseDriver = {
- "mouse",
- MouseInit,
- MouseEnable,
- MouseDisable,
- MouseFini,
- NULL,
-};
+/* + * Copyright © 2001 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include <errno.h> +#include <termios.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/Xpoll.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "kdrive.h" + +#undef DEBUG +#undef DEBUG_BYTES +#define KBUFIO_SIZE 256 +#define MOUSE_TIMEOUT 100 + +typedef struct _kbufio { + int fd; + unsigned char buf[KBUFIO_SIZE]; + int avail; + int used; +} Kbufio; + +static Bool +MouseWaitForReadable (int fd, int timeout) +{ + fd_set set; + struct timeval tv, *tp; + int n; + CARD32 done; + + done = GetTimeInMillis () + timeout; + for (;;) + { + FD_ZERO (&set); + FD_SET (fd, &set); + if (timeout == -1) + tp = 0; + else + { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + tp = &tv; + } + n = select (fd + 1, &set, 0, 0, tp); + if (n > 0) + return TRUE; + if (n < 0 && (errno == EAGAIN || errno == EINTR)) + { + timeout = (int) (done - GetTimeInMillis ()); + if (timeout > 0) + continue; + } + break; + } + return FALSE; +} + +static int +MouseReadByte (Kbufio *b, int timeout) +{ + int n; + if (b->avail <= b->used) + { + if (timeout && !MouseWaitForReadable (b->fd, timeout)) + { +#ifdef DEBUG_BYTES + ErrorF ("\tTimeout %d\n", timeout); +#endif + return -1; + } + n = read (b->fd, b->buf, KBUFIO_SIZE); + if (n <= 0) + return -1; + b->avail = n; + b->used = 0; + } +#ifdef DEBUG_BYTES + ErrorF ("\tget %02x\n", b->buf[b->used]); +#endif + return b->buf[b->used++]; +} + +#if NOTUSED +static int +MouseFlush (Kbufio *b, char *buf, int size) +{ + CARD32 now = GetTimeInMillis (); + CARD32 done = now + 100; + int c; + int n = 0; + + while ((c = MouseReadByte (b, done - now)) != -1) + { + if (buf) + { + if (n == size) + { + memmove (buf, buf + 1, size - 1); + n--; + } + buf[n++] = c; + } + now = GetTimeInMillis (); + if ((INT32) (now - done) >= 0) + break; + } + return n; +} + +static int +MousePeekByte (Kbufio *b, int timeout) +{ + int c; + + c = MouseReadByte (b, timeout); + if (c != -1) + --b->used; + return c; +} +#endif /* NOTUSED */ + +static Bool +MouseWaitForWritable (int fd, int timeout) +{ + fd_set set; + struct timeval tv, *tp; + int n; + + FD_ZERO (&set); + FD_SET (fd, &set); + if (timeout == -1) + tp = 0; + else + { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + tp = &tv; + } + n = select (fd + 1, 0, &set, 0, tp); + if (n > 0) + return TRUE; + return FALSE; +} + +static Bool +MouseWriteByte (int fd, unsigned char c, int timeout) +{ + int ret; + +#ifdef DEBUG_BYTES + ErrorF ("\tput %02x\n", c); +#endif + for (;;) + { + ret = write (fd, &c, 1); + if (ret == 1) + return TRUE; + if (ret == 0) + return FALSE; + if (errno != EWOULDBLOCK) + return FALSE; + if (!MouseWaitForWritable (fd, timeout)) + return FALSE; + } +} + +static Bool +MouseWriteBytes (int fd, unsigned char *c, int n, int timeout) +{ + while (n--) + if (!MouseWriteByte (fd, *c++, timeout)) + return FALSE; + return TRUE; +} + +#define MAX_MOUSE 10 /* maximum length of mouse protocol */ +#define MAX_SKIP 16 /* number of error bytes before switching */ +#define MAX_VALID 4 /* number of valid packets before accepting */ + +typedef struct _kmouseProt { + char *name; + Bool (*Complete) (KdPointerInfo *pi, unsigned char *ev, int ne); + int (*Valid) (KdPointerInfo *pi, unsigned char *ev, int ne); + Bool (*Parse) (KdPointerInfo *pi, unsigned char *ev, int ne); + Bool (*Init) (KdPointerInfo *pi); + unsigned char headerMask, headerValid; + unsigned char dataMask, dataValid; + Bool tty; + unsigned int c_iflag; + unsigned int c_oflag; + unsigned int c_lflag; + unsigned int c_cflag; + unsigned int speed; + unsigned char *init; + unsigned long state; +} KmouseProt; + +typedef enum _kmouseStage { + MouseBroken, MouseTesting, MouseWorking +} KmouseStage; + +typedef struct _kmouse { + Kbufio iob; + const KmouseProt *prot; + int i_prot; + KmouseStage stage; /* protocol verification stage */ + Bool tty; /* mouse device is a tty */ + int valid; /* sequential valid events */ + int tested; /* bytes scanned during Testing phase */ + int invalid;/* total invalid bytes for this protocol */ + unsigned long state; /* private per protocol, init to prot->state */ +} Kmouse; + +static int mouseValid (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + const KmouseProt *prot = km->prot; + int i; + + for (i = 0; i < ne; i++) + if ((ev[i] & prot->headerMask) == prot->headerValid) + break; + if (i != 0) + return i; + for (i = 1; i < ne; i++) + if ((ev[i] & prot->dataMask) != prot->dataValid) + return -1; + return 0; +} + +static Bool threeComplete (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + return ne == 3; +} + +static Bool fourComplete (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + return ne == 4; +} + +static Bool fiveComplete (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + return ne == 5; +} + +static Bool MouseReasonable (KdPointerInfo *pi, unsigned long flags, int dx, int dy) +{ + Kmouse *km = pi->driverPrivate; + + if (km->stage == MouseWorking) + return TRUE; + if (dx < -50 || dx > 50) + { +#ifdef DEBUG + ErrorF ("Large X %d\n", dx); +#endif + return FALSE; + } + if (dy < -50 || dy > 50) + { +#ifdef DEBUG + ErrorF ("Large Y %d\n", dy); +#endif + return FALSE; + } + return TRUE; +} + +/* + * Standard PS/2 mouse protocol + */ +static Bool ps2Parse (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + int dx, dy, dz; + unsigned long flags; + unsigned long flagsrelease = 0; + + flags = KD_MOUSE_DELTA; + if (ev[0] & 4) + flags |= KD_BUTTON_2; + if (ev[0] & 2) + flags |= KD_BUTTON_3; + if (ev[0] & 1) + flags |= KD_BUTTON_1; + + if (ne > 3) + { + dz = (int) (signed char) ev[3]; + if (dz < 0) + { + flags |= KD_BUTTON_4; + flagsrelease = KD_BUTTON_4; + } + else if (dz > 0) + { + flags |= KD_BUTTON_5; + flagsrelease = KD_BUTTON_5; + } + } + + dx = ev[1]; + if (ev[0] & 0x10) + dx -= 256; + dy = ev[2]; + if (ev[0] & 0x20) + dy -= 256; + dy = -dy; + if (!MouseReasonable (pi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + { + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + if (flagsrelease) + { + flags &= ~flagsrelease; + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + } + } + return TRUE; +} + +static Bool ps2Init (KdPointerInfo *pi); + +static const KmouseProt ps2Prot = { + "ps/2", + threeComplete, mouseValid, ps2Parse, ps2Init, + 0x08, 0x08, 0x00, 0x00, + FALSE +}; + +static const KmouseProt imps2Prot = { + "imps/2", + fourComplete, mouseValid, ps2Parse, ps2Init, + 0x08, 0x08, 0x00, 0x00, + FALSE +}; + +static const KmouseProt exps2Prot = { + "exps/2", + fourComplete, mouseValid, ps2Parse, ps2Init, + 0x08, 0x08, 0x00, 0x00, + FALSE +}; + +/* + * Once the mouse is known to speak ps/2 protocol, go and find out + * what advanced capabilities it has and turn them on + */ + +/* these extracted from FreeBSD 4.3 sys/dev/kbd/atkbdcreg.h */ + +/* aux device commands (sent to KBD_DATA_PORT) */ +#define PSMC_SET_SCALING11 0x00e6 +#define PSMC_SET_SCALING21 0x00e7 +#define PSMC_SET_RESOLUTION 0x00e8 +#define PSMC_SEND_DEV_STATUS 0x00e9 +#define PSMC_SET_STREAM_MODE 0x00ea +#define PSMC_SEND_DEV_DATA 0x00eb +#define PSMC_SET_REMOTE_MODE 0x00f0 +#define PSMC_SEND_DEV_ID 0x00f2 +#define PSMC_SET_SAMPLING_RATE 0x00f3 +#define PSMC_ENABLE_DEV 0x00f4 +#define PSMC_DISABLE_DEV 0x00f5 +#define PSMC_SET_DEFAULTS 0x00f6 +#define PSMC_RESET_DEV 0x00ff + +/* PSMC_SET_RESOLUTION argument */ +#define PSMD_RES_LOW 0 /* typically 25ppi */ +#define PSMD_RES_MEDIUM_LOW 1 /* typically 50ppi */ +#define PSMD_RES_MEDIUM_HIGH 2 /* typically 100ppi (default) */ +#define PSMD_RES_HIGH 3 /* typically 200ppi */ +#define PSMD_MAX_RESOLUTION PSMD_RES_HIGH + +/* PSMC_SET_SAMPLING_RATE */ +#define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */ + +/* aux device ID */ +#define PSM_MOUSE_ID 0 +#define PSM_BALLPOINT_ID 2 +#define PSM_INTELLI_ID 3 +#define PSM_EXPLORER_ID 4 +#define PSM_4DMOUSE_ID 6 +#define PSM_4DPLUS_ID 8 + +static unsigned char ps2_init[] = { + PSMC_ENABLE_DEV, + 0, +}; + +#define NINIT_PS2 1 + +static unsigned char wheel_3button_init[] = { + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 100, + PSMC_SET_SAMPLING_RATE, 80, + PSMC_SEND_DEV_ID, + 0, +}; + +#define NINIT_IMPS2 4 + +static unsigned char wheel_5button_init[] = { + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 100, + PSMC_SET_SAMPLING_RATE, 80, + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 80, + PSMC_SEND_DEV_ID, + 0 +}; + +#define NINIT_EXPS2 7 + +static unsigned char intelli_init[] = { + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 100, + PSMC_SET_SAMPLING_RATE, 80, + 0 +}; + +#define NINIT_INTELLI 3 + +static int +ps2SkipInit (KdPointerInfo *pi, int ninit, Bool ret_next) +{ + Kmouse *km = pi->driverPrivate; + int c = -1; + int skipping; + Bool waiting; + + skipping = 0; + waiting = FALSE; + while (ninit || ret_next) + { + c = MouseReadByte (&km->iob, MOUSE_TIMEOUT); + if (c == -1) + break; + /* look for ACK */ + if (c == 0xfa) + { + ninit--; + if (ret_next) + waiting = TRUE; + } + /* look for packet start -- not the response */ + else if ((c & 0x08) == 0x08) + waiting = FALSE; + else if (waiting) + break; + } + return c; +} + +static Bool +ps2Init (KdPointerInfo *pi) +{ + Kmouse *km = pi->driverPrivate; + int skipping; + Bool waiting; + int id; + unsigned char *init; + int ninit; + + /* Send Intellimouse initialization sequence */ + MouseWriteBytes (km->iob.fd, intelli_init, strlen ((char *) intelli_init), 100); + /* + * Send ID command + */ + if (!MouseWriteByte (km->iob.fd, PSMC_SEND_DEV_ID, 100)) + return FALSE; + skipping = 0; + waiting = FALSE; + id = ps2SkipInit (pi, 0, TRUE); + switch (id) { + case 3: + init = wheel_3button_init; + ninit = NINIT_IMPS2; + km->prot = &imps2Prot; + break; + case 4: + init = wheel_5button_init; + ninit = NINIT_EXPS2; + km->prot = &exps2Prot; + break; + default: + init = ps2_init; + ninit = NINIT_PS2; + km->prot = &ps2Prot; + break; + } + if (init) + MouseWriteBytes (km->iob.fd, init, strlen ((char *) init), 100); + /* + * Flush out the available data to eliminate responses to the + * initialization string. Make sure any partial event is + * skipped + */ + (void) ps2SkipInit (pi, ninit, FALSE); + return TRUE; +} + +static Bool busParse (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + dx = (signed char) ev[1]; + dy = -(signed char) ev[2]; + if ((ev[0] & 4) == 0) + flags |= KD_BUTTON_1; + if ((ev[0] & 2) == 0) + flags |= KD_BUTTON_2; + if ((ev[0] & 1) == 0) + flags |= KD_BUTTON_3; + if (!MouseReasonable (pi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + return TRUE; +} + +static const KmouseProt busProt = { + "bus", + threeComplete, mouseValid, busParse, 0, + 0xf8, 0x00, 0x00, 0x00, + FALSE +}; + +/* + * Standard MS serial protocol, three bytes + */ + +static Bool msParse (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + + if (ev[0] & 0x20) + flags |= KD_BUTTON_1; + if (ev[0] & 0x10) + flags |= KD_BUTTON_3; + + dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F)); + dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F)); + if (!MouseReasonable (pi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + return TRUE; +} + +static const KmouseProt msProt = { + "ms", + threeComplete, mouseValid, msParse, 0, + 0xc0, 0x40, 0xc0, 0x00, + TRUE, + IGNPAR, + 0, + 0, + CS7 | CSTOPB | CREAD | CLOCAL, + B1200, +}; + +/* + * Logitech mice send 3 or 4 bytes, the only way to tell is to look at the + * first byte of a synchronized protocol stream and see if it's got + * any bits turned on that can't occur in that fourth byte + */ +static Bool logiComplete (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + + if ((ev[0] & 0x40) == 0x40) + return ne == 3; + if (km->stage != MouseBroken && (ev[0] & ~0x23) == 0) + return ne == 1; + return FALSE; +} + +static int logiValid (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + const KmouseProt *prot = km->prot; + int i; + + for (i = 0; i < ne; i++) + { + if ((ev[i] & 0x40) == 0x40) + break; + if (km->stage != MouseBroken && (ev[i] & ~0x23) == 0) + break; + } + if (i != 0) + return i; + for (i = 1; i < ne; i++) + if ((ev[i] & prot->dataMask) != prot->dataValid) + return -1; + return 0; +} + +static Bool logiParse (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + + if (ne == 3) + { + if (ev[0] & 0x20) + flags |= KD_BUTTON_1; + if (ev[0] & 0x10) + flags |= KD_BUTTON_3; + + dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F)); + dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F)); + flags |= km->state & KD_BUTTON_2; + } + else + { + if (ev[0] & 0x20) + flags |= KD_BUTTON_2; + dx = 0; + dy = 0; + flags |= km->state & (KD_BUTTON_1|KD_BUTTON_3); + } + + if (!MouseReasonable (pi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + return TRUE; +} + +static const KmouseProt logiProt = { + "logitech", + logiComplete, logiValid, logiParse, 0, + 0xc0, 0x40, 0xc0, 0x00, + TRUE, + IGNPAR, + 0, + 0, + CS7 | CSTOPB | CREAD | CLOCAL, + B1200, +}; + +/* + * Mouse systems protocol, 5 bytes + */ +static Bool mscParse (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + + if (!(ev[0] & 0x4)) + flags |= KD_BUTTON_1; + if (!(ev[0] & 0x2)) + flags |= KD_BUTTON_2; + if (!(ev[0] & 0x1)) + flags |= KD_BUTTON_3; + dx = (signed char)(ev[1]) + (signed char)(ev[3]); + dy = - ((signed char)(ev[2]) + (signed char)(ev[4])); + + if (!MouseReasonable (pi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + return TRUE; +} + +static const KmouseProt mscProt = { + "msc", + fiveComplete, mouseValid, mscParse, 0, + 0xf8, 0x80, 0x00, 0x00, + TRUE, + IGNPAR, + 0, + 0, + CS8 | CSTOPB | CREAD | CLOCAL, + B1200, +}; + +/* + * Use logitech before ms -- they're the same except that + * logitech sometimes has a fourth byte + */ +static const KmouseProt *kmouseProts[] = { + &ps2Prot, &imps2Prot, &exps2Prot, &busProt, &logiProt, &msProt, &mscProt, +}; + +#define NUM_PROT (sizeof (kmouseProts) / sizeof (kmouseProts[0])) + +static void +MouseInitProtocol (Kmouse *km) +{ + int ret; + struct termios t; + + if (km->prot->tty) + { + ret = tcgetattr (km->iob.fd, &t); + + if (ret >= 0) + { + t.c_iflag = km->prot->c_iflag; + t.c_oflag = km->prot->c_oflag; + t.c_lflag = km->prot->c_lflag; + t.c_cflag = km->prot->c_cflag; + cfsetispeed (&t, km->prot->speed); + cfsetospeed (&t, km->prot->speed); + ret = tcsetattr (km->iob.fd, TCSANOW, &t); + } + } + km->stage = MouseBroken; + km->valid = 0; + km->tested = 0; + km->invalid = 0; + km->state = km->prot->state; +} + +static void +MouseFirstProtocol (Kmouse *km, char *prot) +{ + if (prot) + { + for (km->i_prot = 0; km->i_prot < NUM_PROT; km->i_prot++) + if (!strcmp (prot, kmouseProts[km->i_prot]->name)) + break; + if (km->i_prot == NUM_PROT) + { + int i; + ErrorF ("Unknown mouse protocol \"%s\". Pick one of:", prot); + for (i = 0; i < NUM_PROT; i++) + ErrorF (" %s", kmouseProts[i]->name); + ErrorF ("\n"); + } + else + { + km->prot = kmouseProts[km->i_prot]; + if (km->tty && !km->prot->tty) + ErrorF ("Mouse device is serial port, protocol %s is not serial protocol\n", + prot); + else if (!km->tty && km->prot->tty) + ErrorF ("Mouse device is not serial port, protocol %s is serial protocol\n", + prot); + } + } + if (!km->prot) + { + for (km->i_prot = 0; kmouseProts[km->i_prot]->tty != km->tty; km->i_prot++) + ; + km->prot = kmouseProts[km->i_prot]; + } + MouseInitProtocol (km); +} + +static void +MouseNextProtocol (Kmouse *km) +{ + do + { + if (!km->prot) + km->i_prot = 0; + else + if (++km->i_prot == NUM_PROT) km->i_prot = 0; + km->prot = kmouseProts[km->i_prot]; + } while (km->prot->tty != km->tty); + MouseInitProtocol (km); + ErrorF ("Switching to mouse protocol \"%s\"\n", km->prot->name); +} + +static void +MouseRead (int mousePort, void *closure) +{ + KdPointerInfo *pi = closure; + Kmouse *km = pi->driverPrivate; + unsigned char event[MAX_MOUSE]; + int ne; + int c; + int i; + int timeout; + + timeout = 0; + ne = 0; + for(;;) + { + c = MouseReadByte (&km->iob, timeout); + if (c == -1) + { + if (ne) + { + km->invalid += ne + km->tested; + km->valid = 0; + km->tested = 0; + km->stage = MouseBroken; + } + break; + } + event[ne++] = c; + i = (*km->prot->Valid) (pi, event, ne); + if (i != 0) + { +#ifdef DEBUG + ErrorF ("Mouse protocol %s broken %d of %d bytes bad\n", + km->prot->name, i > 0 ? i : ne, ne); +#endif + if (i > 0 && i < ne) + { + ne -= i; + memmove (event, event + i, ne); + } + else + { + i = ne; + ne = 0; + } + km->invalid += i + km->tested; + km->valid = 0; + km->tested = 0; + if (km->stage == MouseWorking) + km->i_prot--; + km->stage = MouseBroken; + if (km->invalid > MAX_SKIP) + { + MouseNextProtocol (km); + ne = 0; + } + timeout = 0; + } + else + { + if ((*km->prot->Complete) (pi, event, ne)) + { + if ((*km->prot->Parse) (pi, event, ne)) + { + switch (km->stage) + { + case MouseBroken: +#ifdef DEBUG + ErrorF ("Mouse protocol %s seems OK\n", + km->prot->name); +#endif + /* do not zero invalid to accumulate invalid bytes */ + km->valid = 0; + km->tested = 0; + km->stage = MouseTesting; + /* fall through ... */ + case MouseTesting: + km->valid++; + km->tested += ne; + if (km->valid > MAX_VALID) + { +#ifdef DEBUG + ErrorF ("Mouse protocol %s working\n", + km->prot->name); +#endif + km->stage = MouseWorking; + km->invalid = 0; + km->tested = 0; + km->valid = 0; + if (km->prot->Init && !(*km->prot->Init) (pi)) + km->stage = MouseBroken; + } + break; + case MouseWorking: + break; + } + } + else + { + km->invalid += ne + km->tested; + km->valid = 0; + km->tested = 0; + km->stage = MouseBroken; + } + ne = 0; + timeout = 0; + } + else + timeout = MOUSE_TIMEOUT; + } + } +} + +int MouseInputType; + +char *kdefaultMouse[] = { + "/dev/input/mice", + "/dev/mouse", + "/dev/psaux", + "/dev/adbmouse", + "/dev/ttyS0", + "/dev/ttyS1", +}; + +#define NUM_DEFAULT_MOUSE (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0])) + +static Status +MouseInit (KdPointerInfo *pi) +{ + int i; + int fd; + Kmouse *km; + + if (!pi) + return BadImplementation; + + if (!pi->path || strcmp(pi->path, "auto") == 0) { + for (i = 0; i < NUM_DEFAULT_MOUSE; i++) { + fd = open (kdefaultMouse[i], 2); + if (fd >= 0) { + pi->path = strdup (kdefaultMouse[i]); + break; + } + } + } + else { + fd = open (pi->path, 2); + } + + if (fd < 0) + return BadMatch; + + close(fd); + + km = (Kmouse *) malloc(sizeof (Kmouse)); + if (km) { + km->iob.avail = km->iob.used = 0; + MouseFirstProtocol(km, pi->protocol ? pi->protocol : "exps/2"); + /* MouseFirstProtocol sets state to MouseBroken for later protocol + * checks. Skip these checks if a protocol was supplied */ + if (pi->protocol) + km->state = MouseWorking; + km->i_prot = 0; + km->tty = isatty (fd); + km->iob.fd = -1; + pi->driverPrivate = km; + } + else { + close (fd); + return BadAlloc; + } + + return Success; +} + +static Status +MouseEnable (KdPointerInfo *pi) +{ + Kmouse *km; + + if (!pi || !pi->driverPrivate || !pi->path) + return BadImplementation; + + km = pi->driverPrivate; + + km->iob.fd = open(pi->path, 2); + if (km->iob.fd < 0) + return BadMatch; + + if (!KdRegisterFd (km->iob.fd, MouseRead, pi)) + { + close(km->iob.fd); + return BadAlloc; + } + + return Success; +} + +static void +MouseDisable (KdPointerInfo *pi) +{ + Kmouse *km; + if (!pi || !pi->driverPrivate) + return; + + km = pi->driverPrivate; + KdUnregisterFd (pi, km->iob.fd, TRUE); +} + +static void +MouseFini (KdPointerInfo *pi) +{ + free(pi->driverPrivate); + pi->driverPrivate = NULL; +} + +KdPointerDriver LinuxMouseDriver = { + "mouse", + MouseInit, + MouseEnable, + MouseDisable, + MouseFini, + NULL, +}; diff --git a/xorg-server/hw/kdrive/linux/ps2.c b/xorg-server/hw/kdrive/linux/ps2.c index 552a3c7cb..465b963f2 100644 --- a/xorg-server/hw/kdrive/linux/ps2.c +++ b/xorg-server/hw/kdrive/linux/ps2.c @@ -1,5 +1,5 @@ /* - * Copyright © 1999 Keith Packard + * Copyright © 1999 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg-server/hw/kdrive/linux/tslib.c b/xorg-server/hw/kdrive/linux/tslib.c index 8d6007390..1f30ccae7 100644 --- a/xorg-server/hw/kdrive/linux/tslib.c +++ b/xorg-server/hw/kdrive/linux/tslib.c @@ -1,197 +1,197 @@ -/*
- * TSLIB based touchscreen driver for KDrive
- * Porting to new input API and event queueing by Daniel Stone.
- * Derived from ts.c by Keith Packard
- * Derived from ps2.c by Jim Gettys
- *
- * Copyright © 1999 Keith Packard
- * Copyright © 2000 Compaq Computer Corporation
- * Copyright © 2002 MontaVista Software Inc.
- * Copyright © 2005 OpenedHand Ltd.
- * Copyright © 2006 Nokia Corporation
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of the authors and/or copyright holders
- * not be used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission. The authors and/or
- * copyright holders make no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *
- * THE AUTHORS AND/OR COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
- * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS AND/OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-
-#ifdef HAVE_KDRIVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/Xpoll.h>
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "kdrive.h"
-#include <sys/ioctl.h>
-#include <tslib.h>
-#include <dirent.h>
-#include <linux/input.h>
-
-struct TslibPrivate {
- int fd;
- int lastx, lasty;
- struct tsdev *tsDev;
- void (*raw_event_hook)(int x, int y, int pressure, void *closure);
- void *raw_event_closure;
- int phys_screen;
-};
-
-
-static void
-TsRead (int fd, void *closure)
-{
- KdPointerInfo *pi = closure;
- struct TslibPrivate *private = pi->driverPrivate;
- struct ts_sample event;
- long x = 0, y = 0;
- unsigned long flags;
-
- if (private->raw_event_hook) {
- while (ts_read_raw(private->tsDev, &event, 1) == 1)
- private->raw_event_hook (event.x, event.y, event.pressure,
- private->raw_event_closure);
- return;
- }
-
- while (ts_read(private->tsDev, &event, 1) == 1) {
- if (event.pressure) {
- flags = KD_BUTTON_1;
-
- /*
- * Here we test for the touch screen driver actually being on the
- * touch screen, if it is we send absolute coordinates. If not,
- * then we send delta's so that we can track the entire vga screen.
- */
- if (KdCurScreen == private->phys_screen) {
- x = event.x;
- y = event.y;
- } else {
- flags |= KD_MOUSE_DELTA;
- if ((private->lastx == 0) || (private->lasty == 0)) {
- x = event.x;
- y = event.y;
- } else {
- x = event.x - private->lastx;
- y = event.y - private->lasty;
- }
- }
- private->lastx = event.x;
- private->lasty = event.y;
- } else {
- flags = 0;
- x = private->lastx;
- y = private->lasty;
- }
-
- KdEnqueuePointerEvent (pi, flags, x, y, event.pressure);
- }
-}
-
-static Status
-TslibEnable (KdPointerInfo *pi)
-{
- struct TslibPrivate *private = pi->driverPrivate;
-
- private->raw_event_hook = NULL;
- private->raw_event_closure = NULL;
- if (!pi->path) {
- pi->path = strdup("/dev/input/touchscreen0");
- ErrorF("[tslib/TslibEnable] no device path given, trying %s\n", pi->path);
- }
-
- private->tsDev = ts_open(pi->path, 0);
- if (!private->tsDev) {
- ErrorF("[tslib/TslibEnable] failed to open %s\n", pi->path);
- return BadAlloc;
- }
-
- if (ts_config(private->tsDev)) {
- ErrorF("[tslib/TslibEnable] failed to load configuration\n");
- ts_close(private->tsDev);
- private->tsDev = NULL;
- return BadValue;
- }
-
- private->fd = ts_fd(private->tsDev);
-
- KdRegisterFd(private->fd, TsRead, pi);
-
- return Success;
-}
-
-
-static void
-TslibDisable (KdPointerInfo *pi)
-{
- struct TslibPrivate *private = pi->driverPrivate;
-
- if (private->fd)
- KdUnregisterFd(pi, private->fd, TRUE);
-
- if (private->tsDev)
- ts_close(private->tsDev);
-
- private->fd = 0;
- private->tsDev = NULL;
-}
-
-
-static Status
-TslibInit (KdPointerInfo *pi)
-{
- struct TslibPrivate *private = NULL;
-
- if (!pi || !pi->dixdev)
- return !Success;
-
- pi->driverPrivate = (struct TslibPrivate *)
- calloc(sizeof(struct TslibPrivate), 1);
- if (!pi->driverPrivate)
- return !Success;
-
- private = pi->driverPrivate;
- /* hacktastic */
- private->phys_screen = 0;
- pi->nAxes = 3;
- pi->name = strdup("Touchscreen");
- pi->inputClass = KD_TOUCHSCREEN;
-
- return Success;
-}
-
-
-static void
-TslibFini (KdPointerInfo *pi)
-{
- free(pi->driverPrivate);
- pi->driverPrivate = NULL;
-}
-
-
-KdPointerDriver TsDriver = {
- "tslib",
- TslibInit,
- TslibEnable,
- TslibDisable,
- TslibFini,
- NULL,
-};
+/* + * TSLIB based touchscreen driver for KDrive + * Porting to new input API and event queueing by Daniel Stone. + * Derived from ts.c by Keith Packard + * Derived from ps2.c by Jim Gettys + * + * Copyright © 1999 Keith Packard + * Copyright © 2000 Compaq Computer Corporation + * Copyright © 2002 MontaVista Software Inc. + * Copyright © 2005 OpenedHand Ltd. + * Copyright © 2006 Nokia Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the authors and/or copyright holders + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. The authors and/or + * copyright holders make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THE AUTHORS AND/OR COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS AND/OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#ifdef HAVE_KDRIVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/Xpoll.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "kdrive.h" +#include <sys/ioctl.h> +#include <tslib.h> +#include <dirent.h> +#include <linux/input.h> + +struct TslibPrivate { + int fd; + int lastx, lasty; + struct tsdev *tsDev; + void (*raw_event_hook)(int x, int y, int pressure, void *closure); + void *raw_event_closure; + int phys_screen; +}; + + +static void +TsRead (int fd, void *closure) +{ + KdPointerInfo *pi = closure; + struct TslibPrivate *private = pi->driverPrivate; + struct ts_sample event; + long x = 0, y = 0; + unsigned long flags; + + if (private->raw_event_hook) { + while (ts_read_raw(private->tsDev, &event, 1) == 1) + private->raw_event_hook (event.x, event.y, event.pressure, + private->raw_event_closure); + return; + } + + while (ts_read(private->tsDev, &event, 1) == 1) { + if (event.pressure) { + flags = KD_BUTTON_1; + + /* + * Here we test for the touch screen driver actually being on the + * touch screen, if it is we send absolute coordinates. If not, + * then we send delta's so that we can track the entire vga screen. + */ + if (KdCurScreen == private->phys_screen) { + x = event.x; + y = event.y; + } else { + flags |= KD_MOUSE_DELTA; + if ((private->lastx == 0) || (private->lasty == 0)) { + x = event.x; + y = event.y; + } else { + x = event.x - private->lastx; + y = event.y - private->lasty; + } + } + private->lastx = event.x; + private->lasty = event.y; + } else { + flags = 0; + x = private->lastx; + y = private->lasty; + } + + KdEnqueuePointerEvent (pi, flags, x, y, event.pressure); + } +} + +static Status +TslibEnable (KdPointerInfo *pi) +{ + struct TslibPrivate *private = pi->driverPrivate; + + private->raw_event_hook = NULL; + private->raw_event_closure = NULL; + if (!pi->path) { + pi->path = strdup("/dev/input/touchscreen0"); + ErrorF("[tslib/TslibEnable] no device path given, trying %s\n", pi->path); + } + + private->tsDev = ts_open(pi->path, 0); + if (!private->tsDev) { + ErrorF("[tslib/TslibEnable] failed to open %s\n", pi->path); + return BadAlloc; + } + + if (ts_config(private->tsDev)) { + ErrorF("[tslib/TslibEnable] failed to load configuration\n"); + ts_close(private->tsDev); + private->tsDev = NULL; + return BadValue; + } + + private->fd = ts_fd(private->tsDev); + + KdRegisterFd(private->fd, TsRead, pi); + + return Success; +} + + +static void +TslibDisable (KdPointerInfo *pi) +{ + struct TslibPrivate *private = pi->driverPrivate; + + if (private->fd) + KdUnregisterFd(pi, private->fd, TRUE); + + if (private->tsDev) + ts_close(private->tsDev); + + private->fd = 0; + private->tsDev = NULL; +} + + +static Status +TslibInit (KdPointerInfo *pi) +{ + struct TslibPrivate *private = NULL; + + if (!pi || !pi->dixdev) + return !Success; + + pi->driverPrivate = (struct TslibPrivate *) + calloc(sizeof(struct TslibPrivate), 1); + if (!pi->driverPrivate) + return !Success; + + private = pi->driverPrivate; + /* hacktastic */ + private->phys_screen = 0; + pi->nAxes = 3; + pi->name = strdup("Touchscreen"); + pi->inputClass = KD_TOUCHSCREEN; + + return Success; +} + + +static void +TslibFini (KdPointerInfo *pi) +{ + free(pi->driverPrivate); + pi->driverPrivate = NULL; +} + + +KdPointerDriver TsDriver = { + "tslib", + TslibInit, + TslibEnable, + TslibDisable, + TslibFini, + NULL, +}; diff --git a/xorg-server/hw/kdrive/src/kcmap.c b/xorg-server/hw/kdrive/src/kcmap.c index 127c7a078..6e0fc1417 100644 --- a/xorg-server/hw/kdrive/src/kcmap.c +++ b/xorg-server/hw/kdrive/src/kcmap.c @@ -1,246 +1,246 @@ -/*
- * Copyright © 1999 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include "kdrive.h"
-
-/*
- * Put the entire colormap into the DAC
- */
-
-void
-KdSetColormap (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- ColormapPtr pCmap = pScreenPriv->pInstalledmap;
- Pixel pixels[KD_MAX_PSEUDO_SIZE];
- xrgb colors[KD_MAX_PSEUDO_SIZE];
- xColorItem defs[KD_MAX_PSEUDO_SIZE];
- int i;
-
- if (!pScreenPriv->card->cfuncs->putColors)
- return;
- if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH)
- return;
-
- if (!pScreenPriv->enabled)
- return;
-
- if (!pCmap)
- return;
-
- /*
- * Make DIX convert pixels into RGB values -- this handles
- * true/direct as well as pseudo/static visuals
- */
-
- for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
- pixels[i] = i;
-
- QueryColors (pCmap, (1 << pScreenPriv->screen->fb.depth), pixels, colors, serverClient);
-
- for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
- {
- defs[i].pixel = i;
- defs[i].red = colors[i].red;
- defs[i].green = colors[i].green;
- defs[i].blue = colors[i].blue;
- defs[i].flags = DoRed|DoGreen|DoBlue;
- }
-
- (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen,
- (1 << pScreenPriv->screen->fb.depth),
- defs);
-
- /* recolor hardware cursor */
- if (pScreenPriv->card->cfuncs->recolorCursor)
- (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, 0, 0);
-}
-
-/*
- * When the hardware is enabled, save the hardware colors and store
- * the current colormap
- */
-void
-KdEnableColormap (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- int i;
-
- if (!pScreenPriv->card->cfuncs->putColors)
- return;
-
- if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH)
- {
- for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
- pScreenPriv->systemPalette[i].pixel = i;
- (*pScreenPriv->card->cfuncs->getColors) (pScreen,
- (1 << pScreenPriv->screen->fb.depth),
- pScreenPriv->systemPalette);
- }
- KdSetColormap (pScreen);
-}
-
-void
-KdDisableColormap (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
-
- if (!pScreenPriv->card->cfuncs->putColors)
- return;
-
- if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH)
- {
- (*pScreenPriv->card->cfuncs->putColors) (pScreen,
- (1 << pScreenPriv->screen->fb.depth),
- pScreenPriv->systemPalette);
- }
-}
-
-/*
- * KdInstallColormap
- *
- * This function is called when the server receives a request to install a
- * colormap or when the server needs to install one on its own, like when
- * there's no window manager running and the user has moved the pointer over
- * an X client window. It needs to build an identity Windows palette for the
- * colormap and realize it into the Windows system palette.
- */
-void
-KdInstallColormap (ColormapPtr pCmap)
-{
- KdScreenPriv(pCmap->pScreen);
-
- if (pCmap == pScreenPriv->pInstalledmap)
- return;
-
- /* Tell X clients that the installed colormap is going away. */
- if (pScreenPriv->pInstalledmap)
- WalkTree(pScreenPriv->pInstalledmap->pScreen, TellLostMap,
- (pointer) &(pScreenPriv->pInstalledmap->mid));
-
- /* Take note of the new installed colorscreen-> */
- pScreenPriv->pInstalledmap = pCmap;
-
- KdSetColormap (pCmap->pScreen);
-
- /* Tell X clients of the new colormap */
- WalkTree(pCmap->pScreen, TellGainedMap, (pointer) &(pCmap->mid));
-}
-
-/*
- * KdUninstallColormap
- *
- * This function uninstalls a colormap by either installing
- * the default X colormap or erasing the installed colormap pointer.
- * The default X colormap itself cannot be uninstalled.
- */
-void
-KdUninstallColormap (ColormapPtr pCmap)
-{
- KdScreenPriv(pCmap->pScreen);
- Colormap defMapID;
- ColormapPtr defMap;
-
- /* ignore if not installed */
- if (pCmap != pScreenPriv->pInstalledmap)
- return;
-
- /* ignore attempts to uninstall default colormap */
- defMapID = pCmap->pScreen->defColormap;
- if ((Colormap) pCmap->mid == defMapID)
- return;
-
- /* install default */
- dixLookupResourceByType((pointer *)&defMap, defMapID, RT_COLORMAP,
- serverClient, DixInstallAccess);
- if (defMap)
- (*pCmap->pScreen->InstallColormap)(defMap);
- else
- {
- /* uninstall and clear colormap pointer */
- WalkTree(pCmap->pScreen, TellLostMap,
- (pointer) &(pCmap->mid));
- pScreenPriv->pInstalledmap = 0;
- }
-}
-
-int
-KdListInstalledColormaps (ScreenPtr pScreen, Colormap *pCmaps)
-{
- KdScreenPriv(pScreen);
- int n = 0;
-
- if (pScreenPriv->pInstalledmap)
- {
- *pCmaps++ = pScreenPriv->pInstalledmap->mid;
- n++;
- }
- return n;
-}
-
-/*
- * KdStoreColors
- *
- * This function is called whenever the server receives a request to store
- * color values into one or more entries in the currently installed X
- * colormap; it can be either the default colormap or a private colorscreen->
- */
-void
-KdStoreColors (ColormapPtr pCmap, int ndef, xColorItem *pdefs)
-{
- KdScreenPriv(pCmap->pScreen);
- VisualPtr pVisual;
- xColorItem expanddefs[KD_MAX_PSEUDO_SIZE];
-
- if (pCmap != pScreenPriv->pInstalledmap)
- return;
-
- if (!pScreenPriv->card->cfuncs->putColors)
- return;
-
- if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH)
- return;
-
- if (!pScreenPriv->enabled)
- return;
-
- /* Check for DirectColor or TrueColor being simulated on a PseudoColor device. */
- pVisual = pCmap->pVisual;
- if ((pVisual->class | DynamicClass) == DirectColor)
- {
- /*
- * Expand DirectColor or TrueColor color values into a PseudoColor
- * format. Defer to the Color Framebuffer (CFB) code to do that.
- */
- ndef = fbExpandDirectColors(pCmap, ndef, pdefs, expanddefs);
- pdefs = expanddefs;
- }
-
- (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, ndef, pdefs);
-
- /* recolor hardware cursor */
- if (pScreenPriv->card->cfuncs->recolorCursor)
- (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, ndef, pdefs);
-}
+/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "kdrive.h" + +/* + * Put the entire colormap into the DAC + */ + +void +KdSetColormap (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ColormapPtr pCmap = pScreenPriv->pInstalledmap; + Pixel pixels[KD_MAX_PSEUDO_SIZE]; + xrgb colors[KD_MAX_PSEUDO_SIZE]; + xColorItem defs[KD_MAX_PSEUDO_SIZE]; + int i; + + if (!pScreenPriv->card->cfuncs->putColors) + return; + if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH) + return; + + if (!pScreenPriv->enabled) + return; + + if (!pCmap) + return; + + /* + * Make DIX convert pixels into RGB values -- this handles + * true/direct as well as pseudo/static visuals + */ + + for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) + pixels[i] = i; + + QueryColors (pCmap, (1 << pScreenPriv->screen->fb.depth), pixels, colors, serverClient); + + for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) + { + defs[i].pixel = i; + defs[i].red = colors[i].red; + defs[i].green = colors[i].green; + defs[i].blue = colors[i].blue; + defs[i].flags = DoRed|DoGreen|DoBlue; + } + + (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, + (1 << pScreenPriv->screen->fb.depth), + defs); + + /* recolor hardware cursor */ + if (pScreenPriv->card->cfuncs->recolorCursor) + (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, 0, 0); +} + +/* + * When the hardware is enabled, save the hardware colors and store + * the current colormap + */ +void +KdEnableColormap (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + int i; + + if (!pScreenPriv->card->cfuncs->putColors) + return; + + if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) + { + for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) + pScreenPriv->systemPalette[i].pixel = i; + (*pScreenPriv->card->cfuncs->getColors) (pScreen, + (1 << pScreenPriv->screen->fb.depth), + pScreenPriv->systemPalette); + } + KdSetColormap (pScreen); +} + +void +KdDisableColormap (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + + if (!pScreenPriv->card->cfuncs->putColors) + return; + + if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) + { + (*pScreenPriv->card->cfuncs->putColors) (pScreen, + (1 << pScreenPriv->screen->fb.depth), + pScreenPriv->systemPalette); + } +} + +/* + * KdInstallColormap + * + * This function is called when the server receives a request to install a + * colormap or when the server needs to install one on its own, like when + * there's no window manager running and the user has moved the pointer over + * an X client window. It needs to build an identity Windows palette for the + * colormap and realize it into the Windows system palette. + */ +void +KdInstallColormap (ColormapPtr pCmap) +{ + KdScreenPriv(pCmap->pScreen); + + if (pCmap == pScreenPriv->pInstalledmap) + return; + + /* Tell X clients that the installed colormap is going away. */ + if (pScreenPriv->pInstalledmap) + WalkTree(pScreenPriv->pInstalledmap->pScreen, TellLostMap, + (pointer) &(pScreenPriv->pInstalledmap->mid)); + + /* Take note of the new installed colorscreen-> */ + pScreenPriv->pInstalledmap = pCmap; + + KdSetColormap (pCmap->pScreen); + + /* Tell X clients of the new colormap */ + WalkTree(pCmap->pScreen, TellGainedMap, (pointer) &(pCmap->mid)); +} + +/* + * KdUninstallColormap + * + * This function uninstalls a colormap by either installing + * the default X colormap or erasing the installed colormap pointer. + * The default X colormap itself cannot be uninstalled. + */ +void +KdUninstallColormap (ColormapPtr pCmap) +{ + KdScreenPriv(pCmap->pScreen); + Colormap defMapID; + ColormapPtr defMap; + + /* ignore if not installed */ + if (pCmap != pScreenPriv->pInstalledmap) + return; + + /* ignore attempts to uninstall default colormap */ + defMapID = pCmap->pScreen->defColormap; + if ((Colormap) pCmap->mid == defMapID) + return; + + /* install default */ + dixLookupResourceByType((pointer *)&defMap, defMapID, RT_COLORMAP, + serverClient, DixInstallAccess); + if (defMap) + (*pCmap->pScreen->InstallColormap)(defMap); + else + { + /* uninstall and clear colormap pointer */ + WalkTree(pCmap->pScreen, TellLostMap, + (pointer) &(pCmap->mid)); + pScreenPriv->pInstalledmap = 0; + } +} + +int +KdListInstalledColormaps (ScreenPtr pScreen, Colormap *pCmaps) +{ + KdScreenPriv(pScreen); + int n = 0; + + if (pScreenPriv->pInstalledmap) + { + *pCmaps++ = pScreenPriv->pInstalledmap->mid; + n++; + } + return n; +} + +/* + * KdStoreColors + * + * This function is called whenever the server receives a request to store + * color values into one or more entries in the currently installed X + * colormap; it can be either the default colormap or a private colorscreen-> + */ +void +KdStoreColors (ColormapPtr pCmap, int ndef, xColorItem *pdefs) +{ + KdScreenPriv(pCmap->pScreen); + VisualPtr pVisual; + xColorItem expanddefs[KD_MAX_PSEUDO_SIZE]; + + if (pCmap != pScreenPriv->pInstalledmap) + return; + + if (!pScreenPriv->card->cfuncs->putColors) + return; + + if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH) + return; + + if (!pScreenPriv->enabled) + return; + + /* Check for DirectColor or TrueColor being simulated on a PseudoColor device. */ + pVisual = pCmap->pVisual; + if ((pVisual->class | DynamicClass) == DirectColor) + { + /* + * Expand DirectColor or TrueColor color values into a PseudoColor + * format. Defer to the Color Framebuffer (CFB) code to do that. + */ + ndef = fbExpandDirectColors(pCmap, ndef, pdefs, expanddefs); + pdefs = expanddefs; + } + + (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, ndef, pdefs); + + /* recolor hardware cursor */ + if (pScreenPriv->card->cfuncs->recolorCursor) + (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, ndef, pdefs); +} diff --git a/xorg-server/hw/kdrive/src/kdrive.h b/xorg-server/hw/kdrive/src/kdrive.h index 2ab535aef..9ac5a19d7 100644 --- a/xorg-server/hw/kdrive/src/kdrive.h +++ b/xorg-server/hw/kdrive/src/kdrive.h @@ -1,5 +1,5 @@ /* - * Copyright © 1999 Keith Packard + * Copyright © 1999 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -500,6 +500,8 @@ KdScreenInfoDispose (KdScreenInfo *si); /* kinput.c */ void KdInitInput(void); +void +KdCloseInput(void); void KdAddPointerDriver(KdPointerDriver *); diff --git a/xorg-server/hw/kdrive/src/kinfo.c b/xorg-server/hw/kdrive/src/kinfo.c index 90fe37ae9..7055fbf4a 100644 --- a/xorg-server/hw/kdrive/src/kinfo.c +++ b/xorg-server/hw/kdrive/src/kinfo.c @@ -1,163 +1,163 @@ -/*
- * Copyright © 1999 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include "kdrive.h"
-
-KdCardInfo *kdCardInfo;
-
-KdCardInfo *
-KdCardInfoAdd (KdCardFuncs *funcs,
- void *closure)
-{
- KdCardInfo *ci, **prev;
-
- ci = calloc(1, sizeof (KdCardInfo));
- if (!ci)
- return 0;
- for (prev = &kdCardInfo; *prev; prev = &(*prev)->next);
- *prev = ci;
- ci->cfuncs = funcs;
- ci->closure = closure;
- ci->screenList = 0;
- ci->selected = 0;
- ci->next = 0;
- return ci;
-}
-
-KdCardInfo *
-KdCardInfoLast (void)
-{
- KdCardInfo *ci;
-
- if (!kdCardInfo)
- return 0;
- for (ci = kdCardInfo; ci->next; ci = ci->next);
- return ci;
-}
-
-void
-KdCardInfoDispose (KdCardInfo *ci)
-{
- KdCardInfo **prev;
-
- for (prev = &kdCardInfo; *prev; prev = &(*prev)->next)
- if (*prev == ci)
- {
- *prev = ci->next;
- free(ci);
- break;
- }
-}
-
-KdScreenInfo *
-KdScreenInfoAdd (KdCardInfo *ci)
-{
- KdScreenInfo *si, **prev;
- int n;
-
- si = calloc(1, sizeof (KdScreenInfo));
- if (!si)
- return 0;
- for (prev = &ci->screenList, n = 0; *prev; prev = &(*prev)->next, n++);
- *prev = si;
- si->next = 0;
- si->card = ci;
- si->mynum = n;
- return si;
-}
-
-void
-KdScreenInfoDispose (KdScreenInfo *si)
-{
- KdCardInfo *ci = si->card;
- KdScreenInfo **prev;
-
- for (prev = &ci->screenList; *prev; prev = &(*prev)->next) {
- if (*prev == si)
- {
- *prev = si->next;
- free(si);
- if (!ci->screenList)
- KdCardInfoDispose (ci);
- break;
- }
- }
-}
-
-KdPointerInfo *
-KdNewPointer (void)
-{
- KdPointerInfo *pi;
- int i;
-
- pi = (KdPointerInfo *)calloc(1, sizeof(KdPointerInfo));
- if (!pi)
- return NULL;
-
- pi->name = strdup("Generic Pointer");
- pi->path = NULL;
- pi->inputClass = KD_MOUSE;
- pi->driver = NULL;
- pi->driverPrivate = NULL;
- pi->next = NULL;
- pi->options = NULL;
- pi->nAxes = 3;
- pi->nButtons = KD_MAX_BUTTON;
- for (i = 1; i < KD_MAX_BUTTON; i++)
- pi->map[i] = i;
-
- return pi;
-}
-
-void
-KdFreePointer(KdPointerInfo *pi)
-{
- InputOption *option, *prev = NULL;
-
- free(pi->name);
- free(pi->path);
-
- for (option = pi->options; option; option = option->next) {
- free(prev);
- free(option->key);
- free(option->value);
- prev = option;
- }
-
- free(prev);
- free(pi);
-}
-
-void
-KdFreeKeyboard(KdKeyboardInfo *ki)
-{
- free(ki->name);
- free(ki->path);
- free(ki->xkbRules);
- free(ki->xkbModel);
- free(ki->xkbLayout);
- ki->next = NULL;
- free(ki);
-}
+/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "kdrive.h" + +KdCardInfo *kdCardInfo; + +KdCardInfo * +KdCardInfoAdd (KdCardFuncs *funcs, + void *closure) +{ + KdCardInfo *ci, **prev; + + ci = calloc(1, sizeof (KdCardInfo)); + if (!ci) + return 0; + for (prev = &kdCardInfo; *prev; prev = &(*prev)->next); + *prev = ci; + ci->cfuncs = funcs; + ci->closure = closure; + ci->screenList = 0; + ci->selected = 0; + ci->next = 0; + return ci; +} + +KdCardInfo * +KdCardInfoLast (void) +{ + KdCardInfo *ci; + + if (!kdCardInfo) + return 0; + for (ci = kdCardInfo; ci->next; ci = ci->next); + return ci; +} + +void +KdCardInfoDispose (KdCardInfo *ci) +{ + KdCardInfo **prev; + + for (prev = &kdCardInfo; *prev; prev = &(*prev)->next) + if (*prev == ci) + { + *prev = ci->next; + free(ci); + break; + } +} + +KdScreenInfo * +KdScreenInfoAdd (KdCardInfo *ci) +{ + KdScreenInfo *si, **prev; + int n; + + si = calloc(1, sizeof (KdScreenInfo)); + if (!si) + return 0; + for (prev = &ci->screenList, n = 0; *prev; prev = &(*prev)->next, n++); + *prev = si; + si->next = 0; + si->card = ci; + si->mynum = n; + return si; +} + +void +KdScreenInfoDispose (KdScreenInfo *si) +{ + KdCardInfo *ci = si->card; + KdScreenInfo **prev; + + for (prev = &ci->screenList; *prev; prev = &(*prev)->next) { + if (*prev == si) + { + *prev = si->next; + free(si); + if (!ci->screenList) + KdCardInfoDispose (ci); + break; + } + } +} + +KdPointerInfo * +KdNewPointer (void) +{ + KdPointerInfo *pi; + int i; + + pi = (KdPointerInfo *)calloc(1, sizeof(KdPointerInfo)); + if (!pi) + return NULL; + + pi->name = strdup("Generic Pointer"); + pi->path = NULL; + pi->inputClass = KD_MOUSE; + pi->driver = NULL; + pi->driverPrivate = NULL; + pi->next = NULL; + pi->options = NULL; + pi->nAxes = 3; + pi->nButtons = KD_MAX_BUTTON; + for (i = 1; i < KD_MAX_BUTTON; i++) + pi->map[i] = i; + + return pi; +} + +void +KdFreePointer(KdPointerInfo *pi) +{ + InputOption *option, *prev = NULL; + + free(pi->name); + free(pi->path); + + for (option = pi->options; option; option = option->next) { + free(prev); + free(option->key); + free(option->value); + prev = option; + } + + free(prev); + free(pi); +} + +void +KdFreeKeyboard(KdKeyboardInfo *ki) +{ + free(ki->name); + free(ki->path); + free(ki->xkbRules); + free(ki->xkbModel); + free(ki->xkbLayout); + ki->next = NULL; + free(ki); +} diff --git a/xorg-server/hw/kdrive/src/kinput.c b/xorg-server/hw/kdrive/src/kinput.c index cdf55d7f9..c14dd8241 100644 --- a/xorg-server/hw/kdrive/src/kinput.c +++ b/xorg-server/hw/kdrive/src/kinput.c @@ -1,6 +1,6 @@ /* - * Copyright © 1999 Keith Packard - * Copyright © 2006 Nokia Corporation + * Copyright © 1999 Keith Packard + * Copyright © 2006 Nokia Corporation * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -1305,6 +1305,12 @@ KdInitInput (void) mieqInit(); } +void +KdCloseInput (void) +{ + mieqFini(); +} + /* * Middle button emulation state machine * @@ -2159,7 +2165,6 @@ void ProcessInputEvents (void) { mieqProcessInputEvents(); - miPointerUpdateSprite(inputInfo.pointer); if (kdSwitchPending) KdProcessSwitch (); KdCheckLock (); diff --git a/xorg-server/hw/kdrive/src/kshadow.c b/xorg-server/hw/kdrive/src/kshadow.c index 4454020f0..63bb87bc6 100644 --- a/xorg-server/hw/kdrive/src/kshadow.c +++ b/xorg-server/hw/kdrive/src/kshadow.c @@ -1,81 +1,81 @@ -/*
- * Copyright © 1999 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include "kdrive.h"
-
-Bool
-KdShadowFbAlloc (KdScreenInfo *screen, Bool rotate)
-{
- int paddedWidth;
- void *buf;
- int width = rotate ? screen->height : screen->width;
- int height = rotate ? screen->width : screen->height;
- int bpp = screen->fb.bitsPerPixel;
-
- /* use fb computation for width */
- paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits);
- buf = malloc(paddedWidth * height);
- if (!buf)
- return FALSE;
- if (screen->fb.shadow)
- free(screen->fb.frameBuffer);
- screen->fb.shadow = TRUE;
- screen->fb.frameBuffer = buf;
- screen->fb.byteStride = paddedWidth;
- screen->fb.pixelStride = paddedWidth * 8 / bpp;
- return TRUE;
-}
-
-void
-KdShadowFbFree (KdScreenInfo *screen)
-{
- if (screen->fb.shadow)
- {
- free(screen->fb.frameBuffer);
- screen->fb.frameBuffer = 0;
- screen->fb.shadow = FALSE;
- }
-}
-
-Bool
-KdShadowSet (ScreenPtr pScreen, int randr, ShadowUpdateProc update, ShadowWindowProc window)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
-
- shadowRemove (pScreen, pScreen->GetScreenPixmap(pScreen));
- if(screen->fb.shadow)
- {
- return shadowAdd (pScreen, pScreen->GetScreenPixmap(pScreen),
- update, window, randr, 0);
- }
- return TRUE;
-}
-
-void
-KdShadowUnset (ScreenPtr pScreen)
-{
- shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
-}
+/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "kdrive.h" + +Bool +KdShadowFbAlloc (KdScreenInfo *screen, Bool rotate) +{ + int paddedWidth; + void *buf; + int width = rotate ? screen->height : screen->width; + int height = rotate ? screen->width : screen->height; + int bpp = screen->fb.bitsPerPixel; + + /* use fb computation for width */ + paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits); + buf = malloc(paddedWidth * height); + if (!buf) + return FALSE; + if (screen->fb.shadow) + free(screen->fb.frameBuffer); + screen->fb.shadow = TRUE; + screen->fb.frameBuffer = buf; + screen->fb.byteStride = paddedWidth; + screen->fb.pixelStride = paddedWidth * 8 / bpp; + return TRUE; +} + +void +KdShadowFbFree (KdScreenInfo *screen) +{ + if (screen->fb.shadow) + { + free(screen->fb.frameBuffer); + screen->fb.frameBuffer = 0; + screen->fb.shadow = FALSE; + } +} + +Bool +KdShadowSet (ScreenPtr pScreen, int randr, ShadowUpdateProc update, ShadowWindowProc window) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + + shadowRemove (pScreen, pScreen->GetScreenPixmap(pScreen)); + if(screen->fb.shadow) + { + return shadowAdd (pScreen, pScreen->GetScreenPixmap(pScreen), + update, window, randr, 0); + } + return TRUE; +} + +void +KdShadowUnset (ScreenPtr pScreen) +{ + shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen)); +} |