xipassivegrab.c revision 7e31ba66
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 status = GrabKey(client, dev, mod_dev, stuff->detail, 207 ¶m, XI2, &mask); 208 break; 209 case XIGrabtypeEnter: 210 case XIGrabtypeFocusIn: 211 status = GrabWindow(client, dev, stuff->grab_type, ¶m, &mask); 212 break; 213 case XIGrabtypeTouchBegin: 214 status = GrabTouch(client, dev, mod_dev, ¶m, &mask); 215 break; 216 } 217 218 if (status != GrabSuccess) { 219 xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; 220 221 info->status = status; 222 info->modifiers = *modifiers; 223 if (client->swapped) 224 swapl(&info->modifiers); 225 226 rep.num_modifiers++; 227 rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo)); 228 } 229 } 230 231 WriteReplyToClient(client, sizeof(rep), &rep); 232 if (rep.num_modifiers) 233 WriteToClient(client, rep.length * 4, modifiers_failed); 234 235 out: 236 free(modifiers_failed); 237 xi2mask_free(&mask.xi2mask); 238 return ret; 239} 240 241void _X_COLD 242SRepXIPassiveGrabDevice(ClientPtr client, int size, 243 xXIPassiveGrabDeviceReply * rep) 244{ 245 swaps(&rep->sequenceNumber); 246 swapl(&rep->length); 247 swaps(&rep->num_modifiers); 248 249 WriteToClient(client, size, rep); 250} 251 252int _X_COLD 253SProcXIPassiveUngrabDevice(ClientPtr client) 254{ 255 int i; 256 uint32_t *modifiers; 257 258 REQUEST(xXIPassiveUngrabDeviceReq); 259 REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); 260 261 swaps(&stuff->length); 262 swapl(&stuff->grab_window); 263 swaps(&stuff->deviceid); 264 swapl(&stuff->detail); 265 swaps(&stuff->num_modifiers); 266 267 REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 268 ((uint32_t) stuff->num_modifiers) << 2); 269 modifiers = (uint32_t *) &stuff[1]; 270 271 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 272 swapl(modifiers); 273 274 return ProcXIPassiveUngrabDevice(client); 275} 276 277int 278ProcXIPassiveUngrabDevice(ClientPtr client) 279{ 280 DeviceIntPtr dev, mod_dev; 281 WindowPtr win; 282 GrabPtr tempGrab; 283 uint32_t *modifiers; 284 int i, rc; 285 286 REQUEST(xXIPassiveUngrabDeviceReq); 287 REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 288 ((uint32_t) stuff->num_modifiers) << 2); 289 290 if (stuff->deviceid == XIAllDevices) 291 dev = inputInfo.all_devices; 292 else if (stuff->deviceid == XIAllMasterDevices) 293 dev = inputInfo.all_master_devices; 294 else { 295 rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 296 if (rc != Success) 297 return rc; 298 } 299 300 if (stuff->grab_type != XIGrabtypeButton && 301 stuff->grab_type != XIGrabtypeKeycode && 302 stuff->grab_type != XIGrabtypeEnter && 303 stuff->grab_type != XIGrabtypeFocusIn && 304 stuff->grab_type != XIGrabtypeTouchBegin) { 305 client->errorValue = stuff->grab_type; 306 return BadValue; 307 } 308 309 if ((stuff->grab_type == XIGrabtypeEnter || 310 stuff->grab_type == XIGrabtypeFocusIn || 311 stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) { 312 client->errorValue = stuff->detail; 313 return BadValue; 314 } 315 316 rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); 317 if (rc != Success) 318 return rc; 319 320 mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); 321 322 tempGrab = AllocGrab(NULL); 323 if (!tempGrab) 324 return BadAlloc; 325 326 tempGrab->resource = client->clientAsMask; 327 tempGrab->device = dev; 328 tempGrab->window = win; 329 switch (stuff->grab_type) { 330 case XIGrabtypeButton: 331 tempGrab->type = XI_ButtonPress; 332 break; 333 case XIGrabtypeKeycode: 334 tempGrab->type = XI_KeyPress; 335 break; 336 case XIGrabtypeEnter: 337 tempGrab->type = XI_Enter; 338 break; 339 case XIGrabtypeFocusIn: 340 tempGrab->type = XI_FocusIn; 341 break; 342 case XIGrabtypeTouchBegin: 343 tempGrab->type = XI_TouchBegin; 344 break; 345 } 346 tempGrab->grabtype = XI2; 347 tempGrab->modifierDevice = mod_dev; 348 tempGrab->modifiersDetail.pMask = NULL; 349 tempGrab->detail.exact = stuff->detail; 350 tempGrab->detail.pMask = NULL; 351 352 modifiers = (uint32_t *) &stuff[1]; 353 354 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { 355 tempGrab->modifiersDetail.exact = *modifiers; 356 DeletePassiveGrabFromList(tempGrab); 357 } 358 359 FreeGrab(tempGrab); 360 361 return Success; 362} 363