1706f2543Smrg/* 2706f2543Smrg * Copyright 2007-2008 Peter Hutterer 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice (including the next 12706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the 13706f2543Smrg * Software. 14706f2543Smrg * 15706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20706f2543Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21706f2543Smrg * DEALINGS IN THE SOFTWARE. 22706f2543Smrg * 23706f2543Smrg * Author: Peter Hutterer, University of South Australia, NICTA 24706f2543Smrg */ 25706f2543Smrg 26706f2543Smrg/*********************************************************************** 27706f2543Smrg * 28706f2543Smrg * Request to Warp the pointer location of an extension input device. 29706f2543Smrg * 30706f2543Smrg */ 31706f2543Smrg 32706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 33706f2543Smrg#include <dix-config.h> 34706f2543Smrg#endif 35706f2543Smrg 36706f2543Smrg#include <X11/X.h> /* for inputstr.h */ 37706f2543Smrg#include <X11/Xproto.h> /* Request macro */ 38706f2543Smrg#include "inputstr.h" /* DeviceIntPtr */ 39706f2543Smrg#include "windowstr.h" /* window structure */ 40706f2543Smrg#include "scrnintstr.h" /* screen structure */ 41706f2543Smrg#include <X11/extensions/XI.h> 42706f2543Smrg#include <X11/extensions/XI2proto.h> 43706f2543Smrg#include "extnsionst.h" 44706f2543Smrg#include "exevents.h" 45706f2543Smrg#include "exglobals.h" 46706f2543Smrg#include "mipointer.h" /* for miPointerUpdateSprite */ 47706f2543Smrg 48706f2543Smrg 49706f2543Smrg#include "xiwarppointer.h" 50706f2543Smrg/*********************************************************************** 51706f2543Smrg * 52706f2543Smrg * This procedure allows a client to warp the pointer of a device. 53706f2543Smrg * 54706f2543Smrg */ 55706f2543Smrg 56706f2543Smrgint 57706f2543SmrgSProcXIWarpPointer(ClientPtr client) 58706f2543Smrg{ 59706f2543Smrg char n; 60706f2543Smrg 61706f2543Smrg REQUEST(xXIWarpPointerReq); 62706f2543Smrg REQUEST_SIZE_MATCH(xXIWarpPointerReq); 63706f2543Smrg 64706f2543Smrg swaps(&stuff->length, n); 65706f2543Smrg swapl(&stuff->src_win, n); 66706f2543Smrg swapl(&stuff->dst_win, n); 67706f2543Smrg swapl(&stuff->src_x, n); 68706f2543Smrg swapl(&stuff->src_y, n); 69706f2543Smrg swaps(&stuff->src_width, n); 70706f2543Smrg swaps(&stuff->src_height, n); 71706f2543Smrg swapl(&stuff->dst_x, n); 72706f2543Smrg swapl(&stuff->dst_y, n); 73706f2543Smrg swaps(&stuff->deviceid, n); 74706f2543Smrg return (ProcXIWarpPointer(client)); 75706f2543Smrg} 76706f2543Smrg 77706f2543Smrgint 78706f2543SmrgProcXIWarpPointer(ClientPtr client) 79706f2543Smrg{ 80706f2543Smrg int rc; 81706f2543Smrg int x, y; 82706f2543Smrg WindowPtr dest = NULL; 83706f2543Smrg DeviceIntPtr pDev; 84706f2543Smrg SpritePtr pSprite; 85706f2543Smrg ScreenPtr newScreen; 86706f2543Smrg int src_x, src_y; 87706f2543Smrg int dst_x, dst_y; 88706f2543Smrg 89706f2543Smrg REQUEST(xXIWarpPointerReq); 90706f2543Smrg REQUEST_SIZE_MATCH(xXIWarpPointerReq); 91706f2543Smrg 92706f2543Smrg /* FIXME: panoramix stuff is missing, look at ProcWarpPointer */ 93706f2543Smrg 94706f2543Smrg rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess); 95706f2543Smrg 96706f2543Smrg if (rc != Success) 97706f2543Smrg { 98706f2543Smrg client->errorValue = stuff->deviceid; 99706f2543Smrg return rc; 100706f2543Smrg } 101706f2543Smrg 102706f2543Smrg if ((!IsMaster(pDev) && pDev->u.master) || 103706f2543Smrg (IsMaster(pDev) && !IsPointerDevice(pDev))) 104706f2543Smrg { 105706f2543Smrg client->errorValue = stuff->deviceid; 106706f2543Smrg return BadDevice; 107706f2543Smrg } 108706f2543Smrg 109706f2543Smrg if (stuff->dst_win != None) 110706f2543Smrg { 111706f2543Smrg rc = dixLookupWindow(&dest, stuff->dst_win, client, DixGetAttrAccess); 112706f2543Smrg if (rc != Success) 113706f2543Smrg { 114706f2543Smrg client->errorValue = stuff->dst_win; 115706f2543Smrg return rc; 116706f2543Smrg } 117706f2543Smrg } 118706f2543Smrg 119706f2543Smrg pSprite = pDev->spriteInfo->sprite; 120706f2543Smrg x = pSprite->hotPhys.x; 121706f2543Smrg y = pSprite->hotPhys.y; 122706f2543Smrg 123706f2543Smrg src_x = stuff->src_x / (double)(1 << 16); 124706f2543Smrg src_y = stuff->src_y / (double)(1 << 16); 125706f2543Smrg dst_x = stuff->dst_x / (double)(1 << 16); 126706f2543Smrg dst_y = stuff->dst_y / (double)(1 << 16); 127706f2543Smrg 128706f2543Smrg if (stuff->src_win != None) 129706f2543Smrg { 130706f2543Smrg int winX, winY; 131706f2543Smrg WindowPtr src; 132706f2543Smrg 133706f2543Smrg rc = dixLookupWindow(&src, stuff->src_win, client, DixGetAttrAccess); 134706f2543Smrg if (rc != Success) 135706f2543Smrg { 136706f2543Smrg client->errorValue = stuff->src_win; 137706f2543Smrg return rc; 138706f2543Smrg } 139706f2543Smrg 140706f2543Smrg winX = src->drawable.x; 141706f2543Smrg winY = src->drawable.y; 142706f2543Smrg if (src->drawable.pScreen != pSprite->hotPhys.pScreen || 143706f2543Smrg x < winX + src_x || 144706f2543Smrg y < winY + src_y || 145706f2543Smrg (stuff->src_width != 0 && 146706f2543Smrg winX + src_x + (int)stuff->src_width < 0) || 147706f2543Smrg (stuff->src_height != 0 && 148706f2543Smrg winY + src_y + (int)stuff->src_height < y) || 149706f2543Smrg !PointInWindowIsVisible(src, x, y)) 150706f2543Smrg return Success; 151706f2543Smrg } 152706f2543Smrg 153706f2543Smrg if (dest) 154706f2543Smrg { 155706f2543Smrg x = dest->drawable.x; 156706f2543Smrg y = dest->drawable.y; 157706f2543Smrg newScreen = dest->drawable.pScreen; 158706f2543Smrg } else 159706f2543Smrg newScreen = pSprite->hotPhys.pScreen; 160706f2543Smrg 161706f2543Smrg x += dst_x; 162706f2543Smrg y += dst_y; 163706f2543Smrg 164706f2543Smrg if (x < 0) 165706f2543Smrg x = 0; 166706f2543Smrg else if (x > newScreen->width) 167706f2543Smrg x = newScreen->width - 1; 168706f2543Smrg 169706f2543Smrg if (y < 0) 170706f2543Smrg y = 0; 171706f2543Smrg else if (y > newScreen->height) 172706f2543Smrg y = newScreen->height - 1; 173706f2543Smrg 174706f2543Smrg if (newScreen == pSprite->hotPhys.pScreen) 175706f2543Smrg { 176706f2543Smrg if (x < pSprite->physLimits.x1) 177706f2543Smrg x = pSprite->physLimits.x1; 178706f2543Smrg else if (x >= pSprite->physLimits.x2) 179706f2543Smrg x = pSprite->physLimits.x2 - 1; 180706f2543Smrg 181706f2543Smrg if (y < pSprite->physLimits.y1) 182706f2543Smrg y = pSprite->physLimits.y1; 183706f2543Smrg else if (y >= pSprite->physLimits.y2) 184706f2543Smrg y = pSprite->physLimits.y2 - 1; 185706f2543Smrg 186706f2543Smrg if (pSprite->hotShape) 187706f2543Smrg ConfineToShape(pDev, pSprite->hotShape, &x, &y); 188706f2543Smrg (*newScreen->SetCursorPosition)(pDev, newScreen, x, y, TRUE); 189706f2543Smrg } else if (!PointerConfinedToScreen(pDev)) 190706f2543Smrg { 191706f2543Smrg NewCurrentScreen(pDev, newScreen, x, y); 192706f2543Smrg } 193706f2543Smrg 194706f2543Smrg /* if we don't update the device, we get a jump next time it moves */ 195706f2543Smrg pDev->last.valuators[0] = x; 196706f2543Smrg pDev->last.valuators[1] = y; 197706f2543Smrg pDev->last.remainder[0] = 0; 198706f2543Smrg pDev->last.remainder[1] = 0; 199706f2543Smrg miPointerUpdateSprite(pDev); 200706f2543Smrg 201706f2543Smrg /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it 202706f2543Smrg here though. */ 203706f2543Smrg return Success; 204706f2543Smrg} 205706f2543Smrg 206