xiwarppointer.c revision 6747b715
16747b715Smrg/*
26747b715Smrg * Copyright 2007-2008 Peter Hutterer
36747b715Smrg *
46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
56747b715Smrg * copy of this software and associated documentation files (the "Software"),
66747b715Smrg * to deal in the Software without restriction, including without limitation
76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
96747b715Smrg * Software is furnished to do so, subject to the following conditions:
106747b715Smrg *
116747b715Smrg * The above copyright notice and this permission notice (including the next
126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
136747b715Smrg * Software.
146747b715Smrg *
156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
216747b715Smrg * DEALINGS IN THE SOFTWARE.
226747b715Smrg *
236747b715Smrg * Author: Peter Hutterer, University of South Australia, NICTA
246747b715Smrg */
256747b715Smrg
266747b715Smrg/***********************************************************************
276747b715Smrg *
286747b715Smrg * Request to Warp the pointer location of an extension input device.
296747b715Smrg *
306747b715Smrg */
316747b715Smrg
326747b715Smrg#ifdef HAVE_DIX_CONFIG_H
336747b715Smrg#include <dix-config.h>
346747b715Smrg#endif
356747b715Smrg
366747b715Smrg#include <X11/X.h>	/* for inputstr.h    */
376747b715Smrg#include <X11/Xproto.h>	/* Request macro     */
386747b715Smrg#include "inputstr.h"	/* DeviceIntPtr      */
396747b715Smrg#include "windowstr.h"	/* window structure  */
406747b715Smrg#include "scrnintstr.h"	/* screen structure  */
416747b715Smrg#include <X11/extensions/XI.h>
426747b715Smrg#include <X11/extensions/XI2proto.h>
436747b715Smrg#include "extnsionst.h"
446747b715Smrg#include "exevents.h"
456747b715Smrg#include "exglobals.h"
466747b715Smrg#include "mipointer.h" /* for miPointerUpdateSprite */
476747b715Smrg
486747b715Smrg
496747b715Smrg#include "xiwarppointer.h"
506747b715Smrg/***********************************************************************
516747b715Smrg *
526747b715Smrg * This procedure allows a client to warp the pointer of a device.
536747b715Smrg *
546747b715Smrg */
556747b715Smrg
566747b715Smrgint
576747b715SmrgSProcXIWarpPointer(ClientPtr client)
586747b715Smrg{
596747b715Smrg    char n;
606747b715Smrg
616747b715Smrg    REQUEST(xXIWarpPointerReq);
626747b715Smrg    swaps(&stuff->length, n);
636747b715Smrg    swapl(&stuff->src_win, n);
646747b715Smrg    swapl(&stuff->dst_win, n);
656747b715Smrg    swapl(&stuff->src_x, n);
666747b715Smrg    swapl(&stuff->src_y, n);
676747b715Smrg    swaps(&stuff->src_width, n);
686747b715Smrg    swaps(&stuff->src_height, n);
696747b715Smrg    swapl(&stuff->dst_x, n);
706747b715Smrg    swapl(&stuff->dst_y, n);
716747b715Smrg    swaps(&stuff->deviceid, n);
726747b715Smrg    return (ProcXIWarpPointer(client));
736747b715Smrg}
746747b715Smrg
756747b715Smrgint
766747b715SmrgProcXIWarpPointer(ClientPtr client)
776747b715Smrg{
786747b715Smrg    int rc;
796747b715Smrg    int x, y;
806747b715Smrg    WindowPtr dest = NULL;
816747b715Smrg    DeviceIntPtr pDev;
826747b715Smrg    SpritePtr pSprite;
836747b715Smrg    ScreenPtr newScreen;
846747b715Smrg    int src_x, src_y;
856747b715Smrg    int dst_x, dst_y;
866747b715Smrg
876747b715Smrg    REQUEST(xXIWarpPointerReq);
886747b715Smrg    REQUEST_SIZE_MATCH(xXIWarpPointerReq);
896747b715Smrg
906747b715Smrg    /* FIXME: panoramix stuff is missing, look at ProcWarpPointer */
916747b715Smrg
926747b715Smrg    rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess);
936747b715Smrg
946747b715Smrg    if (rc != Success)
956747b715Smrg    {
966747b715Smrg        client->errorValue = stuff->deviceid;
976747b715Smrg        return rc;
986747b715Smrg    }
996747b715Smrg
1006747b715Smrg    if ((!IsMaster(pDev) && pDev->u.master) ||
1016747b715Smrg        (IsMaster(pDev) && !IsPointerDevice(pDev)))
1026747b715Smrg    {
1036747b715Smrg        client->errorValue = stuff->deviceid;
1046747b715Smrg        return BadDevice;
1056747b715Smrg    }
1066747b715Smrg
1076747b715Smrg    if (stuff->dst_win != None)
1086747b715Smrg    {
1096747b715Smrg        rc = dixLookupWindow(&dest, stuff->dst_win, client, DixGetAttrAccess);
1106747b715Smrg        if (rc != Success)
1116747b715Smrg        {
1126747b715Smrg            client->errorValue = stuff->dst_win;
1136747b715Smrg            return rc;
1146747b715Smrg        }
1156747b715Smrg    }
1166747b715Smrg
1176747b715Smrg    pSprite = pDev->spriteInfo->sprite;
1186747b715Smrg    x = pSprite->hotPhys.x;
1196747b715Smrg    y = pSprite->hotPhys.y;
1206747b715Smrg
1216747b715Smrg    src_x = stuff->src_x / (double)(1 << 16);
1226747b715Smrg    src_y = stuff->src_y / (double)(1 << 16);
1236747b715Smrg    dst_x = stuff->dst_x / (double)(1 << 16);
1246747b715Smrg    dst_y = stuff->dst_y / (double)(1 << 16);
1256747b715Smrg
1266747b715Smrg    if (stuff->src_win != None)
1276747b715Smrg    {
1286747b715Smrg        int winX, winY;
1296747b715Smrg        WindowPtr src;
1306747b715Smrg
1316747b715Smrg        rc = dixLookupWindow(&src, stuff->src_win, client, DixGetAttrAccess);
1326747b715Smrg        if (rc != Success)
1336747b715Smrg        {
1346747b715Smrg            client->errorValue = stuff->src_win;
1356747b715Smrg            return rc;
1366747b715Smrg        }
1376747b715Smrg
1386747b715Smrg        winX = src->drawable.x;
1396747b715Smrg        winY = src->drawable.y;
1406747b715Smrg        if (src->drawable.pScreen != pSprite->hotPhys.pScreen ||
1416747b715Smrg                x < winX + src_x ||
1426747b715Smrg                y < winY + src_y ||
1436747b715Smrg                (stuff->src_width != 0 &&
1446747b715Smrg                 winX + src_x + (int)stuff->src_width < 0) ||
1456747b715Smrg                (stuff->src_height != 0 &&
1466747b715Smrg                 winY + src_y + (int)stuff->src_height < y) ||
1476747b715Smrg                !PointInWindowIsVisible(src, x, y))
1486747b715Smrg            return Success;
1496747b715Smrg    }
1506747b715Smrg
1516747b715Smrg    if (dest)
1526747b715Smrg    {
1536747b715Smrg        x = dest->drawable.x;
1546747b715Smrg        y = dest->drawable.y;
1556747b715Smrg        newScreen = dest->drawable.pScreen;
1566747b715Smrg    } else
1576747b715Smrg        newScreen = pSprite->hotPhys.pScreen;
1586747b715Smrg
1596747b715Smrg    x += dst_x;
1606747b715Smrg    y += dst_y;
1616747b715Smrg
1626747b715Smrg    if (x < 0)
1636747b715Smrg        x = 0;
1646747b715Smrg    else if (x > newScreen->width)
1656747b715Smrg        x = newScreen->width - 1;
1666747b715Smrg
1676747b715Smrg    if (y < 0)
1686747b715Smrg        y = 0;
1696747b715Smrg    else if (y > newScreen->height)
1706747b715Smrg        y = newScreen->height - 1;
1716747b715Smrg
1726747b715Smrg    if (newScreen == pSprite->hotPhys.pScreen)
1736747b715Smrg    {
1746747b715Smrg        if (x < pSprite->physLimits.x1)
1756747b715Smrg            x = pSprite->physLimits.x1;
1766747b715Smrg        else if (x >= pSprite->physLimits.x2)
1776747b715Smrg            x = pSprite->physLimits.x2 - 1;
1786747b715Smrg
1796747b715Smrg        if (y < pSprite->physLimits.y1)
1806747b715Smrg            y = pSprite->physLimits.y1;
1816747b715Smrg        else if (y >= pSprite->physLimits.y2)
1826747b715Smrg            y = pSprite->physLimits.y2 - 1;
1836747b715Smrg
1846747b715Smrg        if (pSprite->hotShape)
1856747b715Smrg            ConfineToShape(pDev, pSprite->hotShape, &x, &y);
1866747b715Smrg        (*newScreen->SetCursorPosition)(pDev, newScreen, x, y, TRUE);
1876747b715Smrg    } else if (!PointerConfinedToScreen(pDev))
1886747b715Smrg    {
1896747b715Smrg        NewCurrentScreen(pDev, newScreen, x, y);
1906747b715Smrg    }
1916747b715Smrg
1926747b715Smrg    /* if we don't update the device, we get a jump next time it moves */
1936747b715Smrg    pDev->last.valuators[0] = x;
1946747b715Smrg    pDev->last.valuators[1] = y;
1956747b715Smrg    miPointerUpdateSprite(pDev);
1966747b715Smrg
1976747b715Smrg    /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it
1986747b715Smrg       here though. */
1996747b715Smrg    return Success;
2006747b715Smrg}
2016747b715Smrg
202