xipassivegrab.c revision 806e81e9
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#include "misc.h" 47#include "inpututils.h" 48 49int _X_COLD 50SProcXIPassiveGrabDevice(ClientPtr client) 51{ 52 int i; 53 uint32_t *mods; 54 55 REQUEST(xXIPassiveGrabDeviceReq); 56 REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); 57 58 swaps(&stuff->length); 59 swaps(&stuff->deviceid); 60 swapl(&stuff->grab_window); 61 swapl(&stuff->cursor); 62 swapl(&stuff->time); 63 swapl(&stuff->detail); 64 swaps(&stuff->mask_len); 65 swaps(&stuff->num_modifiers); 66 67 REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, 68 ((uint32_t) stuff->mask_len + stuff->num_modifiers) *4); 69 mods = (uint32_t *) &stuff[1] + stuff->mask_len; 70 71 for (i = 0; i < stuff->num_modifiers; i++, mods++) { 72 swapl(mods); 73 } 74 75 return ProcXIPassiveGrabDevice(client); 76} 77 78int 79ProcXIPassiveGrabDevice(ClientPtr client) 80{ 81 DeviceIntPtr dev, mod_dev; 82 xXIPassiveGrabDeviceReply rep = { 83 .repType = X_Reply, 84 .RepType = X_XIPassiveGrabDevice, 85 .sequenceNumber = client->sequence, 86 .length = 0, 87 .num_modifiers = 0 88 }; 89 int i, ret = Success; 90 uint32_t *modifiers; 91 xXIGrabModifierInfo *modifiers_failed = NULL; 92 GrabMask mask = { 0 }; 93 GrabParameters param; 94 void *tmp; 95 int mask_len; 96 97 REQUEST(xXIPassiveGrabDeviceReq); 98 REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, 99 ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4); 100 101 if (stuff->deviceid == XIAllDevices) 102 dev = inputInfo.all_devices; 103 else if (stuff->deviceid == XIAllMasterDevices) 104 dev = inputInfo.all_master_devices; 105 else { 106 ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 107 if (ret != Success) { 108 client->errorValue = stuff->deviceid; 109 return ret; 110 } 111 } 112 113 if (stuff->grab_type != XIGrabtypeButton && 114 stuff->grab_type != XIGrabtypeKeycode && 115 stuff->grab_type != XIGrabtypeEnter && 116 stuff->grab_type != XIGrabtypeFocusIn && 117 stuff->grab_type != XIGrabtypeTouchBegin) { 118 client->errorValue = stuff->grab_type; 119 return BadValue; 120 } 121 122 if ((stuff->grab_type == XIGrabtypeEnter || 123 stuff->grab_type == XIGrabtypeFocusIn || 124 stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) { 125 client->errorValue = stuff->detail; 126 return BadValue; 127 } 128 129 if (stuff->grab_type == XIGrabtypeTouchBegin && 130 (stuff->grab_mode != XIGrabModeTouch || 131 stuff->paired_device_mode != GrabModeAsync)) { 132 client->errorValue = stuff->grab_mode; 133 return BadValue; 134 } 135 136 if (XICheckInvalidMaskBits(client, (unsigned char *) &stuff[1], 137 stuff->mask_len * 4) != Success) 138 return BadValue; 139 140 mask.xi2mask = xi2mask_new(); 141 if (!mask.xi2mask) 142 return BadAlloc; 143 144 mask_len = min(xi2mask_mask_size(mask.xi2mask), stuff->mask_len * 4); 145 xi2mask_set_one_mask(mask.xi2mask, stuff->deviceid, 146 (unsigned char *) &stuff[1], mask_len * 4); 147 148 memset(¶m, 0, sizeof(param)); 149 param.grabtype = XI2; 150 param.ownerEvents = stuff->owner_events; 151 param.grabWindow = stuff->grab_window; 152 param.cursor = stuff->cursor; 153 154 if (IsKeyboardDevice(dev)) { 155 param.this_device_mode = stuff->grab_mode; 156 param.other_devices_mode = stuff->paired_device_mode; 157 } 158 else { 159 param.this_device_mode = stuff->paired_device_mode; 160 param.other_devices_mode = stuff->grab_mode; 161 } 162 163 if (stuff->cursor != None) { 164 ret = dixLookupResourceByType(&tmp, stuff->cursor, 165 RT_CURSOR, client, DixUseAccess); 166 if (ret != Success) { 167 client->errorValue = stuff->cursor; 168 goto out; 169 } 170 } 171 172 ret = 173 dixLookupWindow((WindowPtr *) &tmp, stuff->grab_window, client, 174 DixSetAttrAccess); 175 if (ret != Success) 176 goto out; 177 178 ret = CheckGrabValues(client, ¶m); 179 if (ret != Success) 180 goto out; 181 182 modifiers = (uint32_t *) &stuff[1] + stuff->mask_len; 183 modifiers_failed = 184 calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo)); 185 if (!modifiers_failed) { 186 ret = BadAlloc; 187 goto out; 188 } 189 190 mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); 191 192 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { 193 uint8_t status = Success; 194 195 param.modifiers = *modifiers; 196 ret = CheckGrabValues(client, ¶m); 197 if (ret != Success) 198 goto out; 199 200 switch (stuff->grab_type) { 201 case XIGrabtypeButton: 202 status = GrabButton(client, dev, mod_dev, stuff->detail, 203 ¶m, XI2, &mask); 204 break; 205 case XIGrabtypeKeycode: 206 /* XI2 allows 32-bit keycodes but thanks to XKB we can never 207 * implement this. Just return an error for all keycodes that 208 * cannot work anyway */ 209 if (stuff->detail > 255) 210 status = XIAlreadyGrabbed; 211 else 212 status = GrabKey(client, dev, mod_dev, stuff->detail, 213 ¶m, XI2, &mask); 214 break; 215 case XIGrabtypeEnter: 216 case XIGrabtypeFocusIn: 217 status = GrabWindow(client, dev, stuff->grab_type, ¶m, &mask); 218 break; 219 case XIGrabtypeTouchBegin: 220 status = GrabTouch(client, dev, mod_dev, ¶m, &mask); 221 break; 222 } 223 224 if (status != GrabSuccess) { 225 xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; 226 227 info->status = status; 228 info->modifiers = *modifiers; 229 if (client->swapped) 230 swapl(&info->modifiers); 231 232 rep.num_modifiers++; 233 rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo)); 234 } 235 } 236 237 WriteReplyToClient(client, sizeof(rep), &rep); 238 if (rep.num_modifiers) 239 WriteToClient(client, rep.length * 4, modifiers_failed); 240 241 out: 242 free(modifiers_failed); 243 xi2mask_free(&mask.xi2mask); 244 return ret; 245} 246 247void _X_COLD 248SRepXIPassiveGrabDevice(ClientPtr client, int size, 249 xXIPassiveGrabDeviceReply * rep) 250{ 251 swaps(&rep->sequenceNumber); 252 swapl(&rep->length); 253 swaps(&rep->num_modifiers); 254 255 WriteToClient(client, size, rep); 256} 257 258int _X_COLD 259SProcXIPassiveUngrabDevice(ClientPtr client) 260{ 261 int i; 262 uint32_t *modifiers; 263 264 REQUEST(xXIPassiveUngrabDeviceReq); 265 REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); 266 267 swaps(&stuff->length); 268 swapl(&stuff->grab_window); 269 swaps(&stuff->deviceid); 270 swapl(&stuff->detail); 271 swaps(&stuff->num_modifiers); 272 273 REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 274 ((uint32_t) stuff->num_modifiers) << 2); 275 modifiers = (uint32_t *) &stuff[1]; 276 277 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 278 swapl(modifiers); 279 280 return ProcXIPassiveUngrabDevice(client); 281} 282 283int 284ProcXIPassiveUngrabDevice(ClientPtr client) 285{ 286 DeviceIntPtr dev, mod_dev; 287 WindowPtr win; 288 GrabPtr tempGrab; 289 uint32_t *modifiers; 290 int i, rc; 291 292 REQUEST(xXIPassiveUngrabDeviceReq); 293 REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 294 ((uint32_t) stuff->num_modifiers) << 2); 295 296 if (stuff->deviceid == XIAllDevices) 297 dev = inputInfo.all_devices; 298 else if (stuff->deviceid == XIAllMasterDevices) 299 dev = inputInfo.all_master_devices; 300 else { 301 rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 302 if (rc != Success) 303 return rc; 304 } 305 306 if (stuff->grab_type != XIGrabtypeButton && 307 stuff->grab_type != XIGrabtypeKeycode && 308 stuff->grab_type != XIGrabtypeEnter && 309 stuff->grab_type != XIGrabtypeFocusIn && 310 stuff->grab_type != XIGrabtypeTouchBegin) { 311 client->errorValue = stuff->grab_type; 312 return BadValue; 313 } 314 315 if ((stuff->grab_type == XIGrabtypeEnter || 316 stuff->grab_type == XIGrabtypeFocusIn || 317 stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) { 318 client->errorValue = stuff->detail; 319 return BadValue; 320 } 321 322 rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); 323 if (rc != Success) 324 return rc; 325 326 mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); 327 328 tempGrab = AllocGrab(NULL); 329 if (!tempGrab) 330 return BadAlloc; 331 332 tempGrab->resource = client->clientAsMask; 333 tempGrab->device = dev; 334 tempGrab->window = win; 335 switch (stuff->grab_type) { 336 case XIGrabtypeButton: 337 tempGrab->type = XI_ButtonPress; 338 break; 339 case XIGrabtypeKeycode: 340 tempGrab->type = XI_KeyPress; 341 break; 342 case XIGrabtypeEnter: 343 tempGrab->type = XI_Enter; 344 break; 345 case XIGrabtypeFocusIn: 346 tempGrab->type = XI_FocusIn; 347 break; 348 case XIGrabtypeTouchBegin: 349 tempGrab->type = XI_TouchBegin; 350 break; 351 } 352 tempGrab->grabtype = XI2; 353 tempGrab->modifierDevice = mod_dev; 354 tempGrab->modifiersDetail.pMask = NULL; 355 tempGrab->detail.exact = stuff->detail; 356 tempGrab->detail.pMask = NULL; 357 358 modifiers = (uint32_t *) &stuff[1]; 359 360 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { 361 tempGrab->modifiersDetail.exact = *modifiers; 362 DeletePassiveGrabFromList(tempGrab); 363 } 364 365 FreeGrab(tempGrab); 366 367 return Success; 368} 369