xiquerypointer.c revision f7df2e56
1/* 2 * Copyright 2007-2008 Peter Hutterer 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Author: Peter Hutterer, University of South Australia, NICTA 24 */ 25 26/*********************************************************************** 27 * 28 * Request to query the pointer location of an extension input device. 29 * 30 */ 31 32#ifdef HAVE_DIX_CONFIG_H 33#include <dix-config.h> 34#endif 35 36#include <X11/X.h> /* for inputstr.h */ 37#include <X11/Xproto.h> /* Request macro */ 38#include "inputstr.h" /* DeviceIntPtr */ 39#include "windowstr.h" /* window structure */ 40#include <X11/extensions/XI.h> 41#include <X11/extensions/XI2proto.h> 42#include "extnsionst.h" 43#include "exevents.h" 44#include "exglobals.h" 45#include "eventconvert.h" 46#include "scrnintstr.h" 47#include "xkbsrv.h" 48 49#ifdef PANORAMIX 50#include "panoramiXsrv.h" 51#endif 52 53#include "inpututils.h" 54#include "xiquerypointer.h" 55 56/*********************************************************************** 57 * 58 * This procedure allows a client to query the pointer of a device. 59 * 60 */ 61 62int 63SProcXIQueryPointer(ClientPtr client) 64{ 65 REQUEST(xXIQueryPointerReq); 66 REQUEST_SIZE_MATCH(xXIQueryPointerReq); 67 68 swaps(&stuff->length); 69 swaps(&stuff->deviceid); 70 swapl(&stuff->win); 71 return (ProcXIQueryPointer(client)); 72} 73 74int 75ProcXIQueryPointer(ClientPtr client) 76{ 77 int rc; 78 xXIQueryPointerReply rep; 79 DeviceIntPtr pDev, kbd; 80 WindowPtr pWin, t; 81 SpritePtr pSprite; 82 XkbStatePtr state; 83 char *buttons = NULL; 84 int buttons_size = 0; /* size of buttons array */ 85 XIClientPtr xi_client; 86 Bool have_xi22 = FALSE; 87 88 REQUEST(xXIQueryPointerReq); 89 REQUEST_SIZE_MATCH(xXIQueryPointerReq); 90 91 /* Check if client is compliant with XInput 2.2 or later. Earlier clients 92 * do not know about touches, so we must report emulated button presses. 2.2 93 * and later clients are aware of touches, so we don't include emulated 94 * button presses in the reply. */ 95 xi_client = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); 96 if (version_compare(xi_client->major_version, 97 xi_client->minor_version, 2, 2) >= 0) 98 have_xi22 = TRUE; 99 100 rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess); 101 if (rc != Success) { 102 client->errorValue = stuff->deviceid; 103 return rc; 104 } 105 106 if (pDev->valuator == NULL || IsKeyboardDevice(pDev) || (!IsMaster(pDev) && !IsFloating(pDev))) { /* no attached devices */ 107 client->errorValue = stuff->deviceid; 108 return BadDevice; 109 } 110 111 rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess); 112 if (rc != Success) { 113 SendErrorToClient(client, IReqCode, X_XIQueryPointer, stuff->win, rc); 114 return Success; 115 } 116 117 if (pDev->valuator->motionHintWindow) 118 MaybeStopHint(pDev, client); 119 120 if (IsMaster(pDev)) 121 kbd = GetMaster(pDev, MASTER_KEYBOARD); 122 else 123 kbd = (pDev->key) ? pDev : NULL; 124 125 pSprite = pDev->spriteInfo->sprite; 126 127 rep = (xXIQueryPointerReply) { 128 .repType = X_Reply, 129 .RepType = X_XIQueryPointer, 130 .sequenceNumber = client->sequence, 131 .length = 6, 132 .root = (GetCurrentRootWindow(pDev))->drawable.id, 133 .root_x = double_to_fp1616(pSprite->hot.x), 134 .root_y = double_to_fp1616(pSprite->hot.y), 135 .child = None 136 }; 137 138 if (kbd) { 139 state = &kbd->key->xkbInfo->state; 140 rep.mods.base_mods = state->base_mods; 141 rep.mods.latched_mods = state->latched_mods; 142 rep.mods.locked_mods = state->locked_mods; 143 144 rep.group.base_group = state->base_group; 145 rep.group.latched_group = state->latched_group; 146 rep.group.locked_group = state->locked_group; 147 } 148 149 if (pDev->button) { 150 int i; 151 152 rep.buttons_len = 153 bytes_to_int32(bits_to_bytes(pDev->button->numButtons)); 154 rep.length += rep.buttons_len; 155 buttons = calloc(rep.buttons_len, 4); 156 if (!buttons) 157 return BadAlloc; 158 buttons_size = rep.buttons_len * 4; 159 160 for (i = 1; i < pDev->button->numButtons; i++) 161 if (BitIsOn(pDev->button->down, i)) 162 SetBit(buttons, pDev->button->map[i]); 163 164 if (!have_xi22 && pDev->touch && pDev->touch->buttonsDown > 0) 165 SetBit(buttons, pDev->button->map[1]); 166 } 167 else 168 rep.buttons_len = 0; 169 170 if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 171 rep.same_screen = xTrue; 172 rep.win_x = double_to_fp1616(pSprite->hot.x - pWin->drawable.x); 173 rep.win_y = double_to_fp1616(pSprite->hot.y - pWin->drawable.y); 174 for (t = pSprite->win; t; t = t->parent) 175 if (t->parent == pWin) { 176 rep.child = t->drawable.id; 177 break; 178 } 179 } 180 else { 181 rep.same_screen = xFalse; 182 rep.win_x = 0; 183 rep.win_y = 0; 184 } 185 186#ifdef PANORAMIX 187 if (!noPanoramiXExtension) { 188 rep.root_x += double_to_fp1616(screenInfo.screens[0]->x); 189 rep.root_y += double_to_fp1616(screenInfo.screens[0]->y); 190 if (stuff->win == rep.root) { 191 rep.win_x += double_to_fp1616(screenInfo.screens[0]->x); 192 rep.win_y += double_to_fp1616(screenInfo.screens[0]->y); 193 } 194 } 195#endif 196 197 WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep); 198 if (buttons) 199 WriteToClient(client, buttons_size, buttons); 200 201 free(buttons); 202 203 return Success; 204} 205 206/*********************************************************************** 207 * 208 * This procedure writes the reply for the XIQueryPointer function, 209 * if the client and server have a different byte ordering. 210 * 211 */ 212 213void 214SRepXIQueryPointer(ClientPtr client, int size, xXIQueryPointerReply * rep) 215{ 216 swaps(&rep->sequenceNumber); 217 swapl(&rep->length); 218 swapl(&rep->root); 219 swapl(&rep->child); 220 swapl(&rep->root_x); 221 swapl(&rep->root_y); 222 swapl(&rep->win_x); 223 swapl(&rep->win_y); 224 swaps(&rep->buttons_len); 225 226 WriteToClient(client, size, rep); 227} 228