xipassivegrab.c revision 5a112b11
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 stuff->grab_type != XIGrabtypeGesturePinchBegin && 119 stuff->grab_type != XIGrabtypeGestureSwipeBegin) { 120 client->errorValue = stuff->grab_type; 121 return BadValue; 122 } 123 124 if ((stuff->grab_type == XIGrabtypeEnter || 125 stuff->grab_type == XIGrabtypeFocusIn || 126 stuff->grab_type == XIGrabtypeTouchBegin || 127 stuff->grab_type == XIGrabtypeGesturePinchBegin || 128 stuff->grab_type == XIGrabtypeGestureSwipeBegin) && stuff->detail != 0) { 129 client->errorValue = stuff->detail; 130 return BadValue; 131 } 132 133 if (stuff->grab_type == XIGrabtypeTouchBegin && 134 (stuff->grab_mode != XIGrabModeTouch || 135 stuff->paired_device_mode != GrabModeAsync)) { 136 client->errorValue = stuff->grab_mode; 137 return BadValue; 138 } 139 140 if (XICheckInvalidMaskBits(client, (unsigned char *) &stuff[1], 141 stuff->mask_len * 4) != Success) 142 return BadValue; 143 144 mask.xi2mask = xi2mask_new(); 145 if (!mask.xi2mask) 146 return BadAlloc; 147 148 mask_len = min(xi2mask_mask_size(mask.xi2mask), stuff->mask_len * 4); 149 xi2mask_set_one_mask(mask.xi2mask, stuff->deviceid, 150 (unsigned char *) &stuff[1], mask_len * 4); 151 152 memset(¶m, 0, sizeof(param)); 153 param.grabtype = XI2; 154 param.ownerEvents = stuff->owner_events; 155 param.grabWindow = stuff->grab_window; 156 param.cursor = stuff->cursor; 157 158 if (IsKeyboardDevice(dev)) { 159 param.this_device_mode = stuff->grab_mode; 160 param.other_devices_mode = stuff->paired_device_mode; 161 } 162 else { 163 param.this_device_mode = stuff->paired_device_mode; 164 param.other_devices_mode = stuff->grab_mode; 165 } 166 167 if (stuff->cursor != None) { 168 ret = dixLookupResourceByType(&tmp, stuff->cursor, 169 RT_CURSOR, client, DixUseAccess); 170 if (ret != Success) { 171 client->errorValue = stuff->cursor; 172 goto out; 173 } 174 } 175 176 ret = 177 dixLookupWindow((WindowPtr *) &tmp, stuff->grab_window, client, 178 DixSetAttrAccess); 179 if (ret != Success) 180 goto out; 181 182 ret = CheckGrabValues(client, ¶m); 183 if (ret != Success) 184 goto out; 185 186 modifiers = (uint32_t *) &stuff[1] + stuff->mask_len; 187 modifiers_failed = 188 calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo)); 189 if (!modifiers_failed) { 190 ret = BadAlloc; 191 goto out; 192 } 193 194 mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); 195 196 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { 197 uint8_t status = Success; 198 199 param.modifiers = *modifiers; 200 ret = CheckGrabValues(client, ¶m); 201 if (ret != Success) 202 goto out; 203 204 switch (stuff->grab_type) { 205 case XIGrabtypeButton: 206 status = GrabButton(client, dev, mod_dev, stuff->detail, 207 ¶m, XI2, &mask); 208 break; 209 case XIGrabtypeKeycode: 210 /* XI2 allows 32-bit keycodes but thanks to XKB we can never 211 * implement this. Just return an error for all keycodes that 212 * cannot work anyway */ 213 if (stuff->detail > 255) 214 status = XIAlreadyGrabbed; 215 else 216 status = GrabKey(client, dev, mod_dev, stuff->detail, 217 ¶m, XI2, &mask); 218 break; 219 case XIGrabtypeEnter: 220 case XIGrabtypeFocusIn: 221 status = GrabWindow(client, dev, stuff->grab_type, ¶m, &mask); 222 break; 223 case XIGrabtypeTouchBegin: 224 status = GrabTouchOrGesture(client, dev, mod_dev, XI_TouchBegin, 225 ¶m, &mask); 226 break; 227 case XIGrabtypeGesturePinchBegin: 228 status = GrabTouchOrGesture(client, dev, mod_dev, 229 XI_GesturePinchBegin, ¶m, &mask); 230 break; 231 case XIGrabtypeGestureSwipeBegin: 232 status = GrabTouchOrGesture(client, dev, mod_dev, 233 XI_GestureSwipeBegin, ¶m, &mask); 234 break; 235 } 236 237 if (status != GrabSuccess) { 238 xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; 239 240 info->status = status; 241 info->modifiers = *modifiers; 242 if (client->swapped) 243 swapl(&info->modifiers); 244 245 rep.num_modifiers++; 246 rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo)); 247 } 248 } 249 250 WriteReplyToClient(client, sizeof(rep), &rep); 251 if (rep.num_modifiers) 252 WriteToClient(client, rep.length * 4, modifiers_failed); 253 254 out: 255 free(modifiers_failed); 256 xi2mask_free(&mask.xi2mask); 257 return ret; 258} 259 260void _X_COLD 261SRepXIPassiveGrabDevice(ClientPtr client, int size, 262 xXIPassiveGrabDeviceReply * rep) 263{ 264 swaps(&rep->sequenceNumber); 265 swapl(&rep->length); 266 swaps(&rep->num_modifiers); 267 268 WriteToClient(client, size, rep); 269} 270 271int _X_COLD 272SProcXIPassiveUngrabDevice(ClientPtr client) 273{ 274 int i; 275 uint32_t *modifiers; 276 277 REQUEST(xXIPassiveUngrabDeviceReq); 278 REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); 279 280 swaps(&stuff->length); 281 swapl(&stuff->grab_window); 282 swaps(&stuff->deviceid); 283 swapl(&stuff->detail); 284 swaps(&stuff->num_modifiers); 285 286 REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 287 ((uint32_t) stuff->num_modifiers) << 2); 288 modifiers = (uint32_t *) &stuff[1]; 289 290 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 291 swapl(modifiers); 292 293 return ProcXIPassiveUngrabDevice(client); 294} 295 296int 297ProcXIPassiveUngrabDevice(ClientPtr client) 298{ 299 DeviceIntPtr dev, mod_dev; 300 WindowPtr win; 301 GrabPtr tempGrab; 302 uint32_t *modifiers; 303 int i, rc; 304 305 REQUEST(xXIPassiveUngrabDeviceReq); 306 REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 307 ((uint32_t) stuff->num_modifiers) << 2); 308 309 if (stuff->deviceid == XIAllDevices) 310 dev = inputInfo.all_devices; 311 else if (stuff->deviceid == XIAllMasterDevices) 312 dev = inputInfo.all_master_devices; 313 else { 314 rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 315 if (rc != Success) 316 return rc; 317 } 318 319 if (stuff->grab_type != XIGrabtypeButton && 320 stuff->grab_type != XIGrabtypeKeycode && 321 stuff->grab_type != XIGrabtypeEnter && 322 stuff->grab_type != XIGrabtypeFocusIn && 323 stuff->grab_type != XIGrabtypeTouchBegin && 324 stuff->grab_type != XIGrabtypeGesturePinchBegin && 325 stuff->grab_type != XIGrabtypeGestureSwipeBegin) { 326 client->errorValue = stuff->grab_type; 327 return BadValue; 328 } 329 330 if ((stuff->grab_type == XIGrabtypeEnter || 331 stuff->grab_type == XIGrabtypeFocusIn || 332 stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) { 333 client->errorValue = stuff->detail; 334 return BadValue; 335 } 336 337 rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); 338 if (rc != Success) 339 return rc; 340 341 mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); 342 343 tempGrab = AllocGrab(NULL); 344 if (!tempGrab) 345 return BadAlloc; 346 347 tempGrab->resource = client->clientAsMask; 348 tempGrab->device = dev; 349 tempGrab->window = win; 350 switch (stuff->grab_type) { 351 case XIGrabtypeButton: 352 tempGrab->type = XI_ButtonPress; 353 break; 354 case XIGrabtypeKeycode: 355 tempGrab->type = XI_KeyPress; 356 break; 357 case XIGrabtypeEnter: 358 tempGrab->type = XI_Enter; 359 break; 360 case XIGrabtypeFocusIn: 361 tempGrab->type = XI_FocusIn; 362 break; 363 case XIGrabtypeTouchBegin: 364 tempGrab->type = XI_TouchBegin; 365 break; 366 case XIGrabtypeGesturePinchBegin: 367 tempGrab->type = XI_GesturePinchBegin; 368 break; 369 case XIGrabtypeGestureSwipeBegin: 370 tempGrab->type = XI_GestureSwipeBegin; 371 break; 372 } 373 tempGrab->grabtype = XI2; 374 tempGrab->modifierDevice = mod_dev; 375 tempGrab->modifiersDetail.pMask = NULL; 376 tempGrab->detail.exact = stuff->detail; 377 tempGrab->detail.pMask = NULL; 378 379 modifiers = (uint32_t *) &stuff[1]; 380 381 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { 382 tempGrab->modifiersDetail.exact = *modifiers; 383 DeletePassiveGrabFromList(tempGrab); 384 } 385 386 FreeGrab(tempGrab); 387 388 return Success; 389} 390