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 query 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 <X11/extensions/XI.h> 41706f2543Smrg#include <X11/extensions/XI2proto.h> 42706f2543Smrg#include "extnsionst.h" 43706f2543Smrg#include "exevents.h" 44706f2543Smrg#include "exglobals.h" 45706f2543Smrg#include "eventconvert.h" 46706f2543Smrg#include "scrnintstr.h" 47706f2543Smrg#include "xkbsrv.h" 48706f2543Smrg 49706f2543Smrg#ifdef PANORAMIX 50706f2543Smrg#include "panoramiXsrv.h" 51706f2543Smrg#endif 52706f2543Smrg 53706f2543Smrg#include "xiquerypointer.h" 54706f2543Smrg 55706f2543Smrg/*********************************************************************** 56706f2543Smrg * 57706f2543Smrg * This procedure allows a client to query the pointer of a device. 58706f2543Smrg * 59706f2543Smrg */ 60706f2543Smrg 61706f2543Smrgint 62706f2543SmrgSProcXIQueryPointer(ClientPtr client) 63706f2543Smrg{ 64706f2543Smrg char n; 65706f2543Smrg 66706f2543Smrg REQUEST(xXIQueryPointerReq); 67706f2543Smrg REQUEST_SIZE_MATCH(xXIQueryPointerReq); 68706f2543Smrg 69706f2543Smrg swaps(&stuff->length, n); 70706f2543Smrg swaps(&stuff->deviceid, n); 71706f2543Smrg swapl(&stuff->win, n); 72706f2543Smrg return (ProcXIQueryPointer(client)); 73706f2543Smrg} 74706f2543Smrg 75706f2543Smrgint 76706f2543SmrgProcXIQueryPointer(ClientPtr client) 77706f2543Smrg{ 78706f2543Smrg int rc; 79706f2543Smrg xXIQueryPointerReply rep; 80706f2543Smrg DeviceIntPtr pDev, kbd; 81706f2543Smrg WindowPtr pWin, t; 82706f2543Smrg SpritePtr pSprite; 83706f2543Smrg XkbStatePtr state; 84706f2543Smrg char *buttons = NULL; 85706f2543Smrg int buttons_size = 0; /* size of buttons array */ 86706f2543Smrg 87706f2543Smrg REQUEST(xXIQueryPointerReq); 88706f2543Smrg REQUEST_SIZE_MATCH(xXIQueryPointerReq); 89706f2543Smrg 90706f2543Smrg rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess); 91706f2543Smrg if (rc != Success) 92706f2543Smrg { 93706f2543Smrg client->errorValue = stuff->deviceid; 94706f2543Smrg return rc; 95706f2543Smrg } 96706f2543Smrg 97706f2543Smrg if (pDev->valuator == NULL || IsKeyboardDevice(pDev) || 98706f2543Smrg (!IsMaster(pDev) && pDev->u.master)) /* no attached devices */ 99706f2543Smrg { 100706f2543Smrg client->errorValue = stuff->deviceid; 101706f2543Smrg return BadDevice; 102706f2543Smrg } 103706f2543Smrg 104706f2543Smrg rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess); 105706f2543Smrg if (rc != Success) 106706f2543Smrg { 107706f2543Smrg SendErrorToClient(client, IReqCode, X_XIQueryPointer, 108706f2543Smrg stuff->win, rc); 109706f2543Smrg return Success; 110706f2543Smrg } 111706f2543Smrg 112706f2543Smrg if (pDev->valuator->motionHintWindow) 113706f2543Smrg MaybeStopHint(pDev, client); 114706f2543Smrg 115706f2543Smrg if (IsMaster(pDev)) 116706f2543Smrg kbd = GetPairedDevice(pDev); 117706f2543Smrg else 118706f2543Smrg kbd = (pDev->key) ? pDev : NULL; 119706f2543Smrg 120706f2543Smrg pSprite = pDev->spriteInfo->sprite; 121706f2543Smrg 122706f2543Smrg memset(&rep, 0, sizeof(rep)); 123706f2543Smrg rep.repType = X_Reply; 124706f2543Smrg rep.RepType = X_XIQueryPointer; 125706f2543Smrg rep.length = 6; 126706f2543Smrg rep.sequenceNumber = client->sequence; 127706f2543Smrg rep.root = (GetCurrentRootWindow(pDev))->drawable.id; 128706f2543Smrg rep.root_x = FP1616(pSprite->hot.x, 0); 129706f2543Smrg rep.root_y = FP1616(pSprite->hot.y, 0); 130706f2543Smrg rep.child = None; 131706f2543Smrg 132706f2543Smrg if (kbd) 133706f2543Smrg { 134706f2543Smrg state = &kbd->key->xkbInfo->state; 135706f2543Smrg rep.mods.base_mods = state->base_mods; 136706f2543Smrg rep.mods.latched_mods = state->latched_mods; 137706f2543Smrg rep.mods.locked_mods = state->locked_mods; 138706f2543Smrg 139706f2543Smrg rep.group.base_group = state->base_group; 140706f2543Smrg rep.group.latched_group = state->latched_group; 141706f2543Smrg rep.group.locked_group = state->locked_group; 142706f2543Smrg } 143706f2543Smrg 144706f2543Smrg if (pDev->button) 145706f2543Smrg { 146706f2543Smrg int i, down; 147bde01a6bSmrg rep.buttons_len = bytes_to_int32(bits_to_bytes(256)); /* button map up to 255 */ 148706f2543Smrg rep.length += rep.buttons_len; 149706f2543Smrg buttons_size = rep.buttons_len * 4; 150706f2543Smrg buttons = calloc(1, buttons_size); 151706f2543Smrg if (!buttons) 152706f2543Smrg return BadAlloc; 153706f2543Smrg 154706f2543Smrg down = pDev->button->buttonsDown; 155706f2543Smrg 156706f2543Smrg for (i = 0; i < pDev->button->numButtons && down; i++) 157706f2543Smrg { 158706f2543Smrg if (BitIsOn(pDev->button->down, i)) 159706f2543Smrg { 160706f2543Smrg SetBit(buttons, i); 161706f2543Smrg down--; 162706f2543Smrg } 163706f2543Smrg } 164706f2543Smrg } else 165706f2543Smrg rep.buttons_len = 0; 166706f2543Smrg 167706f2543Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) 168706f2543Smrg { 169706f2543Smrg rep.same_screen = xTrue; 170706f2543Smrg rep.win_x = FP1616(pSprite->hot.x - pWin->drawable.x, 0); 171706f2543Smrg rep.win_y = FP1616(pSprite->hot.y - pWin->drawable.y, 0); 172706f2543Smrg for (t = pSprite->win; t; t = t->parent) 173706f2543Smrg if (t->parent == pWin) 174706f2543Smrg { 175706f2543Smrg rep.child = t->drawable.id; 176706f2543Smrg break; 177706f2543Smrg } 178706f2543Smrg } else 179706f2543Smrg { 180706f2543Smrg rep.same_screen = xFalse; 181706f2543Smrg rep.win_x = 0; 182706f2543Smrg rep.win_y = 0; 183706f2543Smrg } 184706f2543Smrg 185706f2543Smrg#ifdef PANORAMIX 186706f2543Smrg if(!noPanoramiXExtension) { 187706f2543Smrg rep.root_x += FP1616(screenInfo.screens[0]->x, 0); 188706f2543Smrg rep.root_y += FP1616(screenInfo.screens[0]->y, 0); 189706f2543Smrg if (stuff->win == rep.root) 190706f2543Smrg { 191706f2543Smrg rep.win_x += FP1616(screenInfo.screens[0]->x, 0); 192706f2543Smrg rep.win_y += FP1616(screenInfo.screens[0]->y, 0); 193706f2543Smrg } 194706f2543Smrg } 195706f2543Smrg#endif 196706f2543Smrg 197706f2543Smrg WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep); 198706f2543Smrg if (buttons) 199706f2543Smrg WriteToClient(client, buttons_size, buttons); 200706f2543Smrg 201706f2543Smrg free(buttons); 202706f2543Smrg 203706f2543Smrg return Success; 204706f2543Smrg} 205706f2543Smrg 206706f2543Smrg/*********************************************************************** 207706f2543Smrg * 208706f2543Smrg * This procedure writes the reply for the XIQueryPointer function, 209706f2543Smrg * if the client and server have a different byte ordering. 210706f2543Smrg * 211706f2543Smrg */ 212706f2543Smrg 213706f2543Smrgvoid 214706f2543SmrgSRepXIQueryPointer(ClientPtr client, int size, 215706f2543Smrg xXIQueryPointerReply * rep) 216706f2543Smrg{ 217706f2543Smrg char n; 218706f2543Smrg 219706f2543Smrg swaps(&rep->sequenceNumber, n); 220706f2543Smrg swapl(&rep->length, n); 221706f2543Smrg swapl(&rep->root, n); 222706f2543Smrg swapl(&rep->child, n); 223706f2543Smrg swapl(&rep->root_x, n); 224706f2543Smrg swapl(&rep->root_y, n); 225706f2543Smrg swapl(&rep->win_x, n); 226706f2543Smrg swapl(&rep->win_y, n); 227706f2543Smrg swaps(&rep->buttons_len, n); 228706f2543Smrg 229706f2543Smrg WriteToClient(client, size, (char *)rep); 230706f2543Smrg} 231706f2543Smrg 232