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 query 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 36f7df2e56Smrg#include <X11/X.h> /* for inputstr.h */ 37f7df2e56Smrg#include <X11/Xproto.h> /* Request macro */ 38f7df2e56Smrg#include "inputstr.h" /* DeviceIntPtr */ 39f7df2e56Smrg#include "windowstr.h" /* window structure */ 406747b715Smrg#include <X11/extensions/XI.h> 416747b715Smrg#include <X11/extensions/XI2proto.h> 426747b715Smrg#include "extnsionst.h" 436747b715Smrg#include "exevents.h" 446747b715Smrg#include "exglobals.h" 456747b715Smrg#include "eventconvert.h" 466747b715Smrg#include "scrnintstr.h" 476747b715Smrg#include "xkbsrv.h" 486747b715Smrg 496747b715Smrg#ifdef PANORAMIX 506747b715Smrg#include "panoramiXsrv.h" 516747b715Smrg#endif 526747b715Smrg 53f7df2e56Smrg#include "inpututils.h" 546747b715Smrg#include "xiquerypointer.h" 556747b715Smrg 566747b715Smrg/*********************************************************************** 576747b715Smrg * 586747b715Smrg * This procedure allows a client to query the pointer of a device. 596747b715Smrg * 606747b715Smrg */ 616747b715Smrg 627e31ba66Smrgint _X_COLD 636747b715SmrgSProcXIQueryPointer(ClientPtr client) 646747b715Smrg{ 656747b715Smrg REQUEST(xXIQueryPointerReq); 660b0d8713Smrg REQUEST_SIZE_MATCH(xXIQueryPointerReq); 670b0d8713Smrg 68f7df2e56Smrg swaps(&stuff->length); 69f7df2e56Smrg swaps(&stuff->deviceid); 70f7df2e56Smrg swapl(&stuff->win); 716747b715Smrg return (ProcXIQueryPointer(client)); 726747b715Smrg} 736747b715Smrg 746747b715Smrgint 756747b715SmrgProcXIQueryPointer(ClientPtr client) 766747b715Smrg{ 776747b715Smrg int rc; 786747b715Smrg xXIQueryPointerReply rep; 796747b715Smrg DeviceIntPtr pDev, kbd; 806747b715Smrg WindowPtr pWin, t; 816747b715Smrg SpritePtr pSprite; 826747b715Smrg XkbStatePtr state; 836747b715Smrg char *buttons = NULL; 84f7df2e56Smrg int buttons_size = 0; /* size of buttons array */ 85f7df2e56Smrg XIClientPtr xi_client; 86f7df2e56Smrg Bool have_xi22 = FALSE; 876747b715Smrg 886747b715Smrg REQUEST(xXIQueryPointerReq); 896747b715Smrg REQUEST_SIZE_MATCH(xXIQueryPointerReq); 906747b715Smrg 91f7df2e56Smrg /* Check if client is compliant with XInput 2.2 or later. Earlier clients 92f7df2e56Smrg * do not know about touches, so we must report emulated button presses. 2.2 93f7df2e56Smrg * and later clients are aware of touches, so we don't include emulated 94f7df2e56Smrg * button presses in the reply. */ 95f7df2e56Smrg xi_client = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); 96f7df2e56Smrg if (version_compare(xi_client->major_version, 97f7df2e56Smrg xi_client->minor_version, 2, 2) >= 0) 98f7df2e56Smrg have_xi22 = TRUE; 99f7df2e56Smrg 1006747b715Smrg rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess); 101f7df2e56Smrg if (rc != Success) { 1026747b715Smrg client->errorValue = stuff->deviceid; 1036747b715Smrg return rc; 1046747b715Smrg } 1056747b715Smrg 106f7df2e56Smrg if (pDev->valuator == NULL || IsKeyboardDevice(pDev) || (!IsMaster(pDev) && !IsFloating(pDev))) { /* no attached devices */ 1076747b715Smrg client->errorValue = stuff->deviceid; 1086747b715Smrg return BadDevice; 1096747b715Smrg } 1106747b715Smrg 1116747b715Smrg rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess); 112f7df2e56Smrg if (rc != Success) { 1137e31ba66Smrg client->errorValue = stuff->win; 1147e31ba66Smrg return rc; 1156747b715Smrg } 1166747b715Smrg 1176747b715Smrg if (pDev->valuator->motionHintWindow) 1186747b715Smrg MaybeStopHint(pDev, client); 1196747b715Smrg 1206747b715Smrg if (IsMaster(pDev)) 121f7df2e56Smrg kbd = GetMaster(pDev, MASTER_KEYBOARD); 1226747b715Smrg else 1236747b715Smrg kbd = (pDev->key) ? pDev : NULL; 1246747b715Smrg 1256747b715Smrg pSprite = pDev->spriteInfo->sprite; 1266747b715Smrg 127f7df2e56Smrg rep = (xXIQueryPointerReply) { 128f7df2e56Smrg .repType = X_Reply, 129f7df2e56Smrg .RepType = X_XIQueryPointer, 130f7df2e56Smrg .sequenceNumber = client->sequence, 131f7df2e56Smrg .length = 6, 132f7df2e56Smrg .root = (GetCurrentRootWindow(pDev))->drawable.id, 133f7df2e56Smrg .root_x = double_to_fp1616(pSprite->hot.x), 134f7df2e56Smrg .root_y = double_to_fp1616(pSprite->hot.y), 135f7df2e56Smrg .child = None 136f7df2e56Smrg }; 137f7df2e56Smrg 138f7df2e56Smrg if (kbd) { 1399ace9065Smrg state = &kbd->key->xkbInfo->state; 1406747b715Smrg rep.mods.base_mods = state->base_mods; 1416747b715Smrg rep.mods.latched_mods = state->latched_mods; 1426747b715Smrg rep.mods.locked_mods = state->locked_mods; 1436747b715Smrg 1446747b715Smrg rep.group.base_group = state->base_group; 1456747b715Smrg rep.group.latched_group = state->latched_group; 1466747b715Smrg rep.group.locked_group = state->locked_group; 1476747b715Smrg } 1486747b715Smrg 149f7df2e56Smrg if (pDev->button) { 150f7df2e56Smrg int i; 151f7df2e56Smrg 152875c6e4fSmrg rep.buttons_len = bytes_to_int32(bits_to_bytes(256)); /* button map up to 255 */ 1536747b715Smrg rep.length += rep.buttons_len; 154f7df2e56Smrg buttons = calloc(rep.buttons_len, 4); 1556747b715Smrg if (!buttons) 1566747b715Smrg return BadAlloc; 157f7df2e56Smrg buttons_size = rep.buttons_len * 4; 1586747b715Smrg 159f7df2e56Smrg for (i = 1; i < pDev->button->numButtons; i++) 1606747b715Smrg if (BitIsOn(pDev->button->down, i)) 161f7df2e56Smrg SetBit(buttons, pDev->button->map[i]); 162f7df2e56Smrg 163f7df2e56Smrg if (!have_xi22 && pDev->touch && pDev->touch->buttonsDown > 0) 164f7df2e56Smrg SetBit(buttons, pDev->button->map[1]); 165f7df2e56Smrg } 166f7df2e56Smrg else 1676747b715Smrg rep.buttons_len = 0; 1686747b715Smrg 169f7df2e56Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 1706747b715Smrg rep.same_screen = xTrue; 171f7df2e56Smrg rep.win_x = double_to_fp1616(pSprite->hot.x - pWin->drawable.x); 172f7df2e56Smrg rep.win_y = double_to_fp1616(pSprite->hot.y - pWin->drawable.y); 1736747b715Smrg for (t = pSprite->win; t; t = t->parent) 174f7df2e56Smrg if (t->parent == pWin) { 1756747b715Smrg rep.child = t->drawable.id; 1766747b715Smrg break; 1776747b715Smrg } 178f7df2e56Smrg } 179f7df2e56Smrg else { 1806747b715Smrg rep.same_screen = xFalse; 1816747b715Smrg rep.win_x = 0; 1826747b715Smrg rep.win_y = 0; 1836747b715Smrg } 1846747b715Smrg 1856747b715Smrg#ifdef PANORAMIX 186f7df2e56Smrg if (!noPanoramiXExtension) { 187f7df2e56Smrg rep.root_x += double_to_fp1616(screenInfo.screens[0]->x); 188f7df2e56Smrg rep.root_y += double_to_fp1616(screenInfo.screens[0]->y); 189f7df2e56Smrg if (stuff->win == rep.root) { 190f7df2e56Smrg rep.win_x += double_to_fp1616(screenInfo.screens[0]->x); 191f7df2e56Smrg rep.win_y += double_to_fp1616(screenInfo.screens[0]->y); 1926747b715Smrg } 1936747b715Smrg } 1946747b715Smrg#endif 1956747b715Smrg 1966747b715Smrg WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep); 1976747b715Smrg if (buttons) 1986747b715Smrg WriteToClient(client, buttons_size, buttons); 1996747b715Smrg 2006747b715Smrg free(buttons); 2016747b715Smrg 2026747b715Smrg return Success; 2036747b715Smrg} 2046747b715Smrg 2056747b715Smrg/*********************************************************************** 2066747b715Smrg * 2076747b715Smrg * This procedure writes the reply for the XIQueryPointer function, 2086747b715Smrg * if the client and server have a different byte ordering. 2096747b715Smrg * 2106747b715Smrg */ 2116747b715Smrg 2126747b715Smrgvoid 213f7df2e56SmrgSRepXIQueryPointer(ClientPtr client, int size, xXIQueryPointerReply * rep) 2146747b715Smrg{ 215f7df2e56Smrg swaps(&rep->sequenceNumber); 216f7df2e56Smrg swapl(&rep->length); 217f7df2e56Smrg swapl(&rep->root); 218f7df2e56Smrg swapl(&rep->child); 219f7df2e56Smrg swapl(&rep->root_x); 220f7df2e56Smrg swapl(&rep->root_y); 221f7df2e56Smrg swapl(&rep->win_x); 222f7df2e56Smrg swapl(&rep->win_y); 223f7df2e56Smrg swaps(&rep->buttons_len); 224f7df2e56Smrg 225f7df2e56Smrg WriteToClient(client, size, rep); 2266747b715Smrg} 227