xiquerypointer.c revision 6747b715
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 "xiquerypointer.h" 54 55/*********************************************************************** 56 * 57 * This procedure allows a client to query the pointer of a device. 58 * 59 */ 60 61int 62SProcXIQueryPointer(ClientPtr client) 63{ 64 char n; 65 66 REQUEST(xXIQueryPointerReq); 67 swaps(&stuff->length, n); 68 swaps(&stuff->deviceid, n); 69 swapl(&stuff->win, n); 70 return (ProcXIQueryPointer(client)); 71} 72 73int 74ProcXIQueryPointer(ClientPtr client) 75{ 76 int rc; 77 xXIQueryPointerReply rep; 78 DeviceIntPtr pDev, kbd; 79 WindowPtr pWin, t; 80 SpritePtr pSprite; 81 XkbStatePtr state; 82 char *buttons = NULL; 83 int buttons_size = 0; /* size of buttons array */ 84 85 REQUEST(xXIQueryPointerReq); 86 REQUEST_SIZE_MATCH(xXIQueryPointerReq); 87 88 rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess); 89 if (rc != Success) 90 { 91 client->errorValue = stuff->deviceid; 92 return rc; 93 } 94 95 if (pDev->valuator == NULL || IsKeyboardDevice(pDev) || 96 (!IsMaster(pDev) && pDev->u.master)) /* no attached devices */ 97 { 98 client->errorValue = stuff->deviceid; 99 return BadDevice; 100 } 101 102 rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess); 103 if (rc != Success) 104 { 105 SendErrorToClient(client, IReqCode, X_XIQueryPointer, 106 stuff->win, rc); 107 return Success; 108 } 109 110 if (pDev->valuator->motionHintWindow) 111 MaybeStopHint(pDev, client); 112 113 if (IsMaster(pDev)) 114 kbd = GetPairedDevice(pDev); 115 else 116 kbd = (pDev->key) ? pDev : NULL; 117 118 pSprite = pDev->spriteInfo->sprite; 119 120 memset(&rep, 0, sizeof(rep)); 121 rep.repType = X_Reply; 122 rep.RepType = X_XIQueryPointer; 123 rep.length = 6; 124 rep.sequenceNumber = client->sequence; 125 rep.root = (GetCurrentRootWindow(pDev))->drawable.id; 126 rep.root_x = FP1616(pSprite->hot.x, 0); 127 rep.root_y = FP1616(pSprite->hot.y, 0); 128 rep.child = None; 129 130 if (kbd) 131 { 132 state = &kbd->key->xkbInfo->prev_state; 133 rep.mods.base_mods = state->base_mods; 134 rep.mods.latched_mods = state->latched_mods; 135 rep.mods.locked_mods = state->locked_mods; 136 137 rep.group.base_group = state->base_group; 138 rep.group.latched_group = state->latched_group; 139 rep.group.locked_group = state->locked_group; 140 } 141 142 if (pDev->button) 143 { 144 int i, down; 145 rep.buttons_len = bytes_to_int32(bits_to_bytes(pDev->button->numButtons)); 146 rep.length += rep.buttons_len; 147 buttons_size = rep.buttons_len * 4; 148 buttons = calloc(1, buttons_size); 149 if (!buttons) 150 return BadAlloc; 151 152 down = pDev->button->buttonsDown; 153 154 for (i = 0; i < pDev->button->numButtons && down; i++) 155 { 156 if (BitIsOn(pDev->button->down, i)) 157 { 158 SetBit(buttons, i); 159 down--; 160 } 161 } 162 } else 163 rep.buttons_len = 0; 164 165 if (pSprite->hot.pScreen == pWin->drawable.pScreen) 166 { 167 rep.same_screen = xTrue; 168 rep.win_x = FP1616(pSprite->hot.x - pWin->drawable.x, 0); 169 rep.win_y = FP1616(pSprite->hot.y - pWin->drawable.y, 0); 170 for (t = pSprite->win; t; t = t->parent) 171 if (t->parent == pWin) 172 { 173 rep.child = t->drawable.id; 174 break; 175 } 176 } else 177 { 178 rep.same_screen = xFalse; 179 rep.win_x = 0; 180 rep.win_y = 0; 181 } 182 183#ifdef PANORAMIX 184 if(!noPanoramiXExtension) { 185 rep.root_x += FP1616(screenInfo.screens[0]->x, 0); 186 rep.root_y += FP1616(screenInfo.screens[0]->y, 0); 187 if (stuff->win == rep.root) 188 { 189 rep.win_x += FP1616(screenInfo.screens[0]->x, 0); 190 rep.win_y += FP1616(screenInfo.screens[0]->y, 0); 191 } 192 } 193#endif 194 195 WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep); 196 if (buttons) 197 WriteToClient(client, buttons_size, buttons); 198 199 free(buttons); 200 201 return Success; 202} 203 204/*********************************************************************** 205 * 206 * This procedure writes the reply for the XIQueryPointer function, 207 * if the client and server have a different byte ordering. 208 * 209 */ 210 211void 212SRepXIQueryPointer(ClientPtr client, int size, 213 xXIQueryPointerReply * rep) 214{ 215 char n; 216 217 swaps(&rep->sequenceNumber, n); 218 swapl(&rep->length, n); 219 swapl(&rep->root, n); 220 swapl(&rep->child, n); 221 swapl(&rep->root_x, n); 222 swapl(&rep->root_y, n); 223 swapl(&rep->win_x, n); 224 swapl(&rep->win_y, n); 225 swaps(&rep->buttons_len, n); 226 227 WriteToClient(client, size, (char *)rep); 228} 229 230