xipassivegrab.c revision 6747b715
1/* 2 * Copyright © 2009 Red Hat, Inc. 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 24 */ 25 26/*********************************************************************** 27 * 28 * Request to grab or ungrab input device. 29 * 30 */ 31 32#ifdef HAVE_DIX_CONFIG_H 33#include <dix-config.h> 34#endif 35 36#include "inputstr.h" /* DeviceIntPtr */ 37#include "windowstr.h" /* window structure */ 38#include <X11/extensions/XI2.h> 39#include <X11/extensions/XI2proto.h> 40#include "swaprep.h" 41 42#include "exglobals.h" /* BadDevice */ 43#include "exevents.h" 44#include "xipassivegrab.h" 45#include "dixgrabs.h" 46 47int 48SProcXIPassiveGrabDevice(ClientPtr client) 49{ 50 int i; 51 char n; 52 xXIModifierInfo *mods; 53 54 REQUEST(xXIPassiveGrabDeviceReq); 55 56 swaps(&stuff->length, n); 57 swaps(&stuff->deviceid, n); 58 swapl(&stuff->grab_window, n); 59 swapl(&stuff->cursor, n); 60 swapl(&stuff->time, n); 61 swapl(&stuff->detail, n); 62 swaps(&stuff->mask_len, n); 63 swaps(&stuff->num_modifiers, n); 64 65 mods = (xXIModifierInfo*)&stuff[1]; 66 67 for (i = 0; i < stuff->num_modifiers; i++, mods++) 68 { 69 swapl(&mods->base_mods, n); 70 swapl(&mods->latched_mods, n); 71 swapl(&mods->locked_mods, n); 72 } 73 74 return ProcXIPassiveGrabDevice(client); 75} 76 77int 78ProcXIPassiveGrabDevice(ClientPtr client) 79{ 80 DeviceIntPtr dev, mod_dev; 81 xXIPassiveGrabDeviceReply rep; 82 int i, ret = Success; 83 uint8_t status; 84 uint32_t *modifiers; 85 xXIGrabModifierInfo *modifiers_failed; 86 GrabMask mask; 87 GrabParameters param; 88 void *tmp; 89 int mask_len; 90 91 REQUEST(xXIPassiveGrabDeviceReq); 92 REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); 93 94 if (stuff->deviceid == XIAllDevices) 95 dev = inputInfo.all_devices; 96 else if (stuff->deviceid == XIAllMasterDevices) 97 dev = inputInfo.all_master_devices; 98 else 99 { 100 ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 101 if (ret != Success) 102 return ret; 103 } 104 105 if (stuff->grab_type != XIGrabtypeButton && 106 stuff->grab_type != XIGrabtypeKeycode && 107 stuff->grab_type != XIGrabtypeEnter && 108 stuff->grab_type != XIGrabtypeFocusIn) 109 { 110 client->errorValue = stuff->grab_type; 111 return BadValue; 112 } 113 114 if ((stuff->grab_type == XIGrabtypeEnter || 115 stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0) 116 { 117 client->errorValue = stuff->detail; 118 return BadValue; 119 } 120 121 if (XICheckInvalidMaskBits((unsigned char*)&stuff[1], 122 stuff->mask_len * 4) != Success) 123 return BadValue; 124 125 mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4); 126 memset(mask.xi2mask, 0, sizeof(mask.xi2mask)); 127 memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4); 128 129 rep.repType = X_Reply; 130 rep.RepType = X_XIPassiveGrabDevice; 131 rep.length = 0; 132 rep.sequenceNumber = client->sequence; 133 rep.num_modifiers = 0; 134 135 memset(¶m, 0, sizeof(param)); 136 param.grabtype = GRABTYPE_XI2; 137 param.ownerEvents = stuff->owner_events; 138 param.this_device_mode = stuff->grab_mode; 139 param.other_devices_mode = stuff->paired_device_mode; 140 param.grabWindow = stuff->grab_window; 141 param.cursor = stuff->cursor; 142 143 if (stuff->cursor != None) 144 { 145 status = dixLookupResourceByType(&tmp, stuff->cursor, 146 RT_CURSOR, client, DixUseAccess); 147 if (status != Success) 148 { 149 client->errorValue = stuff->cursor; 150 return status; 151 } 152 } 153 154 status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess); 155 if (status != Success) 156 return status; 157 158 status = CheckGrabValues(client, ¶m); 159 160 modifiers = (uint32_t*)&stuff[1] + stuff->mask_len; 161 modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo)); 162 if (!modifiers_failed) 163 return BadAlloc; 164 165 if (!IsMaster(dev) && dev->u.master) 166 mod_dev = GetMaster(dev, MASTER_KEYBOARD); 167 else 168 mod_dev = dev; 169 170 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 171 { 172 param.modifiers = *modifiers; 173 switch(stuff->grab_type) 174 { 175 case XIGrabtypeButton: 176 status = GrabButton(client, dev, mod_dev, stuff->detail, 177 ¶m, GRABTYPE_XI2, &mask); 178 break; 179 case XIGrabtypeKeycode: 180 status = GrabKey(client, dev, mod_dev, stuff->detail, 181 ¶m, GRABTYPE_XI2, &mask); 182 break; 183 case XIGrabtypeEnter: 184 case XIGrabtypeFocusIn: 185 status = GrabWindow(client, dev, stuff->grab_type, 186 ¶m, &mask); 187 break; 188 } 189 190 if (status != GrabSuccess) 191 { 192 xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; 193 194 info->status = status; 195 info->modifiers = *modifiers; 196 rep.num_modifiers++; 197 rep.length++; 198 } 199 } 200 201 WriteReplyToClient(client, sizeof(rep), &rep); 202 if (rep.num_modifiers) 203 { 204 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 205 WriteSwappedDataToClient(client, rep.num_modifiers * 4, (char*)modifiers_failed); 206 } 207 free(modifiers_failed); 208 return ret; 209} 210 211void 212SRepXIPassiveGrabDevice(ClientPtr client, int size, 213 xXIPassiveGrabDeviceReply * rep) 214{ 215 char n; 216 217 swaps(&rep->sequenceNumber, n); 218 swapl(&rep->length, n); 219 swaps(&rep->num_modifiers, n); 220 221 WriteToClient(client, size, (char *)rep); 222} 223 224int 225SProcXIPassiveUngrabDevice(ClientPtr client) 226{ 227 char n; 228 int i; 229 uint32_t *modifiers; 230 231 REQUEST(xXIPassiveUngrabDeviceReq); 232 233 swaps(&stuff->length, n); 234 swapl(&stuff->grab_window, n); 235 swaps(&stuff->deviceid, n); 236 swapl(&stuff->detail, n); 237 swaps(&stuff->num_modifiers, n); 238 239 modifiers = (uint32_t*)&stuff[1]; 240 241 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 242 swapl(modifiers, n); 243 244 return ProcXIPassiveUngrabDevice(client); 245} 246 247int 248ProcXIPassiveUngrabDevice(ClientPtr client) 249{ 250 DeviceIntPtr dev, mod_dev; 251 WindowPtr win; 252 GrabRec tempGrab; 253 uint32_t* modifiers; 254 int i, rc; 255 256 REQUEST(xXIPassiveUngrabDeviceReq); 257 REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); 258 259 rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 260 if (rc != Success) 261 return rc; 262 263 if (stuff->grab_type != XIGrabtypeButton && 264 stuff->grab_type != XIGrabtypeKeycode && 265 stuff->grab_type != XIGrabtypeEnter && 266 stuff->grab_type != XIGrabtypeFocusIn) 267 { 268 client->errorValue = stuff->grab_type; 269 return BadValue; 270 } 271 272 if ((stuff->grab_type == XIGrabtypeEnter || 273 stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0) 274 { 275 client->errorValue = stuff->detail; 276 return BadValue; 277 } 278 279 rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); 280 if (rc != Success) 281 return rc; 282 283 if (!IsMaster(dev) && dev->u.master) 284 mod_dev = GetMaster(dev, MASTER_KEYBOARD); 285 else 286 mod_dev = dev; 287 288 tempGrab.resource = client->clientAsMask; 289 tempGrab.device = dev; 290 tempGrab.window = win; 291 switch(stuff->grab_type) 292 { 293 case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break; 294 case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break; 295 case XIGrabtypeEnter: tempGrab.type = XI_Enter; break; 296 case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break; 297 } 298 tempGrab.grabtype = GRABTYPE_XI2; 299 tempGrab.modifierDevice = mod_dev; 300 tempGrab.modifiersDetail.pMask = NULL; 301 tempGrab.detail.exact = stuff->detail; 302 tempGrab.detail.pMask = NULL; 303 304 modifiers = (uint32_t*)&stuff[1]; 305 306 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 307 { 308 tempGrab.modifiersDetail.exact = *modifiers; 309 DeletePassiveGrabFromList(&tempGrab); 310 } 311 312 return Success; 313} 314