xipassivegrab.c revision e383896c
16747b715Smrg/* 26747b715Smrg * Copyright © 2009 Red Hat, Inc. 36747b715Smrg * 46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a 56747b715Smrg * copy of this software and associated documentation files (the "Software"), 66747b715Smrg * to deal in the Software without restriction, including without limitation 76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 96747b715Smrg * Software is furnished to do so, subject to the following conditions: 106747b715Smrg * 116747b715Smrg * The above copyright notice and this permission notice (including the next 126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 136747b715Smrg * Software. 146747b715Smrg * 156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 216747b715Smrg * DEALINGS IN THE SOFTWARE. 226747b715Smrg * 236747b715Smrg * Author: Peter Hutterer 246747b715Smrg */ 256747b715Smrg 266747b715Smrg/*********************************************************************** 276747b715Smrg * 286747b715Smrg * Request to grab or ungrab input device. 296747b715Smrg * 306747b715Smrg */ 316747b715Smrg 326747b715Smrg#ifdef HAVE_DIX_CONFIG_H 336747b715Smrg#include <dix-config.h> 346747b715Smrg#endif 356747b715Smrg 36f7df2e56Smrg#include "inputstr.h" /* DeviceIntPtr */ 37f7df2e56Smrg#include "windowstr.h" /* window structure */ 386747b715Smrg#include <X11/extensions/XI2.h> 396747b715Smrg#include <X11/extensions/XI2proto.h> 406747b715Smrg#include "swaprep.h" 416747b715Smrg 42f7df2e56Smrg#include "exglobals.h" /* BadDevice */ 436747b715Smrg#include "exevents.h" 446747b715Smrg#include "xipassivegrab.h" 456747b715Smrg#include "dixgrabs.h" 469ace9065Smrg#include "misc.h" 47f7df2e56Smrg#include "inpututils.h" 486747b715Smrg 497e31ba66Smrgint _X_COLD 506747b715SmrgSProcXIPassiveGrabDevice(ClientPtr client) 516747b715Smrg{ 526747b715Smrg int i; 53f7df2e56Smrg uint32_t *mods; 546747b715Smrg 556747b715Smrg REQUEST(xXIPassiveGrabDeviceReq); 560b0d8713Smrg REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); 576747b715Smrg 58f7df2e56Smrg swaps(&stuff->length); 59f7df2e56Smrg swaps(&stuff->deviceid); 60f7df2e56Smrg swapl(&stuff->grab_window); 61f7df2e56Smrg swapl(&stuff->cursor); 62f7df2e56Smrg swapl(&stuff->time); 63f7df2e56Smrg swapl(&stuff->detail); 64f7df2e56Smrg swaps(&stuff->mask_len); 65f7df2e56Smrg swaps(&stuff->num_modifiers); 666747b715Smrg 670b0d8713Smrg REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, 680b0d8713Smrg ((uint32_t) stuff->mask_len + stuff->num_modifiers) *4); 69f7df2e56Smrg mods = (uint32_t *) &stuff[1] + stuff->mask_len; 706747b715Smrg 71f7df2e56Smrg for (i = 0; i < stuff->num_modifiers; i++, mods++) { 72f7df2e56Smrg swapl(mods); 736747b715Smrg } 746747b715Smrg 756747b715Smrg return ProcXIPassiveGrabDevice(client); 766747b715Smrg} 776747b715Smrg 786747b715Smrgint 796747b715SmrgProcXIPassiveGrabDevice(ClientPtr client) 806747b715Smrg{ 816747b715Smrg DeviceIntPtr dev, mod_dev; 82f7df2e56Smrg xXIPassiveGrabDeviceReply rep = { 83f7df2e56Smrg .repType = X_Reply, 84f7df2e56Smrg .RepType = X_XIPassiveGrabDevice, 85f7df2e56Smrg .sequenceNumber = client->sequence, 86f7df2e56Smrg .length = 0, 87f7df2e56Smrg .num_modifiers = 0 88f7df2e56Smrg }; 896747b715Smrg int i, ret = Success; 906747b715Smrg uint32_t *modifiers; 917e31ba66Smrg xXIGrabModifierInfo *modifiers_failed = NULL; 92f7df2e56Smrg GrabMask mask = { 0 }; 936747b715Smrg GrabParameters param; 946747b715Smrg void *tmp; 956747b715Smrg int mask_len; 966747b715Smrg 976747b715Smrg REQUEST(xXIPassiveGrabDeviceReq); 980b0d8713Smrg REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, 990b0d8713Smrg ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4); 1006747b715Smrg 1016747b715Smrg if (stuff->deviceid == XIAllDevices) 1026747b715Smrg dev = inputInfo.all_devices; 1036747b715Smrg else if (stuff->deviceid == XIAllMasterDevices) 1046747b715Smrg dev = inputInfo.all_master_devices; 105f7df2e56Smrg else { 1066747b715Smrg ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 107f7df2e56Smrg if (ret != Success) { 1089ace9065Smrg client->errorValue = stuff->deviceid; 1096747b715Smrg return ret; 1109ace9065Smrg } 1116747b715Smrg } 1126747b715Smrg 1136747b715Smrg if (stuff->grab_type != XIGrabtypeButton && 1146747b715Smrg stuff->grab_type != XIGrabtypeKeycode && 1156747b715Smrg stuff->grab_type != XIGrabtypeEnter && 116f7df2e56Smrg stuff->grab_type != XIGrabtypeFocusIn && 1175a112b11Smrg stuff->grab_type != XIGrabtypeTouchBegin && 1185a112b11Smrg stuff->grab_type != XIGrabtypeGesturePinchBegin && 1195a112b11Smrg stuff->grab_type != XIGrabtypeGestureSwipeBegin) { 1206747b715Smrg client->errorValue = stuff->grab_type; 1216747b715Smrg return BadValue; 1226747b715Smrg } 1236747b715Smrg 1246747b715Smrg if ((stuff->grab_type == XIGrabtypeEnter || 125f7df2e56Smrg stuff->grab_type == XIGrabtypeFocusIn || 1265a112b11Smrg stuff->grab_type == XIGrabtypeTouchBegin || 1275a112b11Smrg stuff->grab_type == XIGrabtypeGesturePinchBegin || 1285a112b11Smrg stuff->grab_type == XIGrabtypeGestureSwipeBegin) && stuff->detail != 0) { 1296747b715Smrg client->errorValue = stuff->detail; 1306747b715Smrg return BadValue; 1316747b715Smrg } 1326747b715Smrg 133f7df2e56Smrg if (stuff->grab_type == XIGrabtypeTouchBegin && 134f7df2e56Smrg (stuff->grab_mode != XIGrabModeTouch || 135f7df2e56Smrg stuff->paired_device_mode != GrabModeAsync)) { 136f7df2e56Smrg client->errorValue = stuff->grab_mode; 137f7df2e56Smrg return BadValue; 138f7df2e56Smrg } 139f7df2e56Smrg 140e383896cSmrg /* XI2 allows 32-bit keycodes but thanks to XKB we can never 141e383896cSmrg * implement this. Just return an error for all keycodes that 142e383896cSmrg * cannot work anyway, same for buttons > 255. */ 143e383896cSmrg if (stuff->detail > 255) 144e383896cSmrg return XIAlreadyGrabbed; 145e383896cSmrg 146f7df2e56Smrg if (XICheckInvalidMaskBits(client, (unsigned char *) &stuff[1], 1476747b715Smrg stuff->mask_len * 4) != Success) 1486747b715Smrg return BadValue; 1496747b715Smrg 150f7df2e56Smrg mask.xi2mask = xi2mask_new(); 151f7df2e56Smrg if (!mask.xi2mask) 152f7df2e56Smrg return BadAlloc; 1536747b715Smrg 154f7df2e56Smrg mask_len = min(xi2mask_mask_size(mask.xi2mask), stuff->mask_len * 4); 155f7df2e56Smrg xi2mask_set_one_mask(mask.xi2mask, stuff->deviceid, 156f7df2e56Smrg (unsigned char *) &stuff[1], mask_len * 4); 1576747b715Smrg 1586747b715Smrg memset(¶m, 0, sizeof(param)); 159f7df2e56Smrg param.grabtype = XI2; 1606747b715Smrg param.ownerEvents = stuff->owner_events; 1616747b715Smrg param.grabWindow = stuff->grab_window; 1626747b715Smrg param.cursor = stuff->cursor; 1636747b715Smrg 164475c125cSmrg if (IsKeyboardDevice(dev)) { 165475c125cSmrg param.this_device_mode = stuff->grab_mode; 166475c125cSmrg param.other_devices_mode = stuff->paired_device_mode; 167f7df2e56Smrg } 168f7df2e56Smrg else { 169475c125cSmrg param.this_device_mode = stuff->paired_device_mode; 170475c125cSmrg param.other_devices_mode = stuff->grab_mode; 171475c125cSmrg } 172475c125cSmrg 173f7df2e56Smrg if (stuff->cursor != None) { 174f7df2e56Smrg ret = dixLookupResourceByType(&tmp, stuff->cursor, 175f7df2e56Smrg RT_CURSOR, client, DixUseAccess); 176f7df2e56Smrg if (ret != Success) { 177f7df2e56Smrg client->errorValue = stuff->cursor; 178f7df2e56Smrg goto out; 179f7df2e56Smrg } 1806747b715Smrg } 1816747b715Smrg 182f7df2e56Smrg ret = 183f7df2e56Smrg dixLookupWindow((WindowPtr *) &tmp, stuff->grab_window, client, 184f7df2e56Smrg DixSetAttrAccess); 185f7df2e56Smrg if (ret != Success) 186f7df2e56Smrg goto out; 187f7df2e56Smrg 188f7df2e56Smrg ret = CheckGrabValues(client, ¶m); 189f7df2e56Smrg if (ret != Success) 190f7df2e56Smrg goto out; 191f7df2e56Smrg 192f7df2e56Smrg modifiers = (uint32_t *) &stuff[1] + stuff->mask_len; 193f7df2e56Smrg modifiers_failed = 194f7df2e56Smrg calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo)); 195f7df2e56Smrg if (!modifiers_failed) { 196f7df2e56Smrg ret = BadAlloc; 197f7df2e56Smrg goto out; 198f7df2e56Smrg } 1996747b715Smrg 200f7df2e56Smrg mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); 2016747b715Smrg 202f7df2e56Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { 203f7df2e56Smrg uint8_t status = Success; 2046747b715Smrg 2056747b715Smrg param.modifiers = *modifiers; 206f7df2e56Smrg ret = CheckGrabValues(client, ¶m); 207f7df2e56Smrg if (ret != Success) 208f7df2e56Smrg goto out; 209f7df2e56Smrg 210f7df2e56Smrg switch (stuff->grab_type) { 211f7df2e56Smrg case XIGrabtypeButton: 212f7df2e56Smrg status = GrabButton(client, dev, mod_dev, stuff->detail, 213f7df2e56Smrg ¶m, XI2, &mask); 214f7df2e56Smrg break; 215f7df2e56Smrg case XIGrabtypeKeycode: 216e383896cSmrg status = GrabKey(client, dev, mod_dev, stuff->detail, 217e383896cSmrg ¶m, XI2, &mask); 218f7df2e56Smrg break; 219f7df2e56Smrg case XIGrabtypeEnter: 220f7df2e56Smrg case XIGrabtypeFocusIn: 221f7df2e56Smrg status = GrabWindow(client, dev, stuff->grab_type, ¶m, &mask); 222f7df2e56Smrg break; 223f7df2e56Smrg case XIGrabtypeTouchBegin: 2245a112b11Smrg status = GrabTouchOrGesture(client, dev, mod_dev, XI_TouchBegin, 2255a112b11Smrg ¶m, &mask); 2265a112b11Smrg break; 2275a112b11Smrg case XIGrabtypeGesturePinchBegin: 2285a112b11Smrg status = GrabTouchOrGesture(client, dev, mod_dev, 2295a112b11Smrg XI_GesturePinchBegin, ¶m, &mask); 2305a112b11Smrg break; 2315a112b11Smrg case XIGrabtypeGestureSwipeBegin: 2325a112b11Smrg status = GrabTouchOrGesture(client, dev, mod_dev, 2335a112b11Smrg XI_GestureSwipeBegin, ¶m, &mask); 234f7df2e56Smrg break; 2356747b715Smrg } 2366747b715Smrg 237f7df2e56Smrg if (status != GrabSuccess) { 2386747b715Smrg xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; 2396747b715Smrg 2406747b715Smrg info->status = status; 2416747b715Smrg info->modifiers = *modifiers; 2429ace9065Smrg if (client->swapped) 243f7df2e56Smrg swapl(&info->modifiers); 2449ace9065Smrg 2456747b715Smrg rep.num_modifiers++; 2469ace9065Smrg rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo)); 2476747b715Smrg } 2486747b715Smrg } 2496747b715Smrg 2506747b715Smrg WriteReplyToClient(client, sizeof(rep), &rep); 2516747b715Smrg if (rep.num_modifiers) 252f7df2e56Smrg WriteToClient(client, rep.length * 4, modifiers_failed); 2539ace9065Smrg 254f7df2e56Smrg out: 2557e31ba66Smrg free(modifiers_failed); 256f7df2e56Smrg xi2mask_free(&mask.xi2mask); 2576747b715Smrg return ret; 2586747b715Smrg} 2596747b715Smrg 2607e31ba66Smrgvoid _X_COLD 2616747b715SmrgSRepXIPassiveGrabDevice(ClientPtr client, int size, 2626747b715Smrg xXIPassiveGrabDeviceReply * rep) 2636747b715Smrg{ 264f7df2e56Smrg swaps(&rep->sequenceNumber); 265f7df2e56Smrg swapl(&rep->length); 266f7df2e56Smrg swaps(&rep->num_modifiers); 2676747b715Smrg 268f7df2e56Smrg WriteToClient(client, size, rep); 2696747b715Smrg} 2706747b715Smrg 2717e31ba66Smrgint _X_COLD 2726747b715SmrgSProcXIPassiveUngrabDevice(ClientPtr client) 2736747b715Smrg{ 2746747b715Smrg int i; 2756747b715Smrg uint32_t *modifiers; 2766747b715Smrg 2776747b715Smrg REQUEST(xXIPassiveUngrabDeviceReq); 2780b0d8713Smrg REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); 2796747b715Smrg 280f7df2e56Smrg swaps(&stuff->length); 281f7df2e56Smrg swapl(&stuff->grab_window); 282f7df2e56Smrg swaps(&stuff->deviceid); 283f7df2e56Smrg swapl(&stuff->detail); 284f7df2e56Smrg swaps(&stuff->num_modifiers); 2856747b715Smrg 2860b0d8713Smrg REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 2870b0d8713Smrg ((uint32_t) stuff->num_modifiers) << 2); 288f7df2e56Smrg modifiers = (uint32_t *) &stuff[1]; 2896747b715Smrg 2906747b715Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 291f7df2e56Smrg swapl(modifiers); 2926747b715Smrg 2936747b715Smrg return ProcXIPassiveUngrabDevice(client); 2946747b715Smrg} 2956747b715Smrg 2966747b715Smrgint 2976747b715SmrgProcXIPassiveUngrabDevice(ClientPtr client) 2986747b715Smrg{ 2996747b715Smrg DeviceIntPtr dev, mod_dev; 3006747b715Smrg WindowPtr win; 301f7df2e56Smrg GrabPtr tempGrab; 302f7df2e56Smrg uint32_t *modifiers; 3036747b715Smrg int i, rc; 3046747b715Smrg 3056747b715Smrg REQUEST(xXIPassiveUngrabDeviceReq); 3060b0d8713Smrg REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 3070b0d8713Smrg ((uint32_t) stuff->num_modifiers) << 2); 3086747b715Smrg 309475c125cSmrg if (stuff->deviceid == XIAllDevices) 310475c125cSmrg dev = inputInfo.all_devices; 311475c125cSmrg else if (stuff->deviceid == XIAllMasterDevices) 312475c125cSmrg dev = inputInfo.all_master_devices; 313f7df2e56Smrg else { 314475c125cSmrg rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 315475c125cSmrg if (rc != Success) 316f7df2e56Smrg return rc; 317475c125cSmrg } 3186747b715Smrg 3196747b715Smrg if (stuff->grab_type != XIGrabtypeButton && 3206747b715Smrg stuff->grab_type != XIGrabtypeKeycode && 3216747b715Smrg stuff->grab_type != XIGrabtypeEnter && 322f7df2e56Smrg stuff->grab_type != XIGrabtypeFocusIn && 3235a112b11Smrg stuff->grab_type != XIGrabtypeTouchBegin && 3245a112b11Smrg stuff->grab_type != XIGrabtypeGesturePinchBegin && 3255a112b11Smrg stuff->grab_type != XIGrabtypeGestureSwipeBegin) { 3266747b715Smrg client->errorValue = stuff->grab_type; 3276747b715Smrg return BadValue; 3286747b715Smrg } 3296747b715Smrg 3306747b715Smrg if ((stuff->grab_type == XIGrabtypeEnter || 331f7df2e56Smrg stuff->grab_type == XIGrabtypeFocusIn || 332f7df2e56Smrg stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) { 3336747b715Smrg client->errorValue = stuff->detail; 3346747b715Smrg return BadValue; 3356747b715Smrg } 3366747b715Smrg 337e383896cSmrg /* We don't allow passive grabs for details > 255 anyway */ 338e383896cSmrg if (stuff->detail > 255) { 339e383896cSmrg client->errorValue = stuff->detail; 340e383896cSmrg return BadValue; 341e383896cSmrg } 342e383896cSmrg 3436747b715Smrg rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); 3446747b715Smrg if (rc != Success) 3456747b715Smrg return rc; 3466747b715Smrg 347f7df2e56Smrg mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); 348f7df2e56Smrg 349f7df2e56Smrg tempGrab = AllocGrab(NULL); 350f7df2e56Smrg if (!tempGrab) 351f7df2e56Smrg return BadAlloc; 352f7df2e56Smrg 353f7df2e56Smrg tempGrab->resource = client->clientAsMask; 354f7df2e56Smrg tempGrab->device = dev; 355f7df2e56Smrg tempGrab->window = win; 356f7df2e56Smrg switch (stuff->grab_type) { 357f7df2e56Smrg case XIGrabtypeButton: 358f7df2e56Smrg tempGrab->type = XI_ButtonPress; 359f7df2e56Smrg break; 360f7df2e56Smrg case XIGrabtypeKeycode: 361f7df2e56Smrg tempGrab->type = XI_KeyPress; 362f7df2e56Smrg break; 363f7df2e56Smrg case XIGrabtypeEnter: 364f7df2e56Smrg tempGrab->type = XI_Enter; 365f7df2e56Smrg break; 366f7df2e56Smrg case XIGrabtypeFocusIn: 367f7df2e56Smrg tempGrab->type = XI_FocusIn; 368f7df2e56Smrg break; 369f7df2e56Smrg case XIGrabtypeTouchBegin: 370f7df2e56Smrg tempGrab->type = XI_TouchBegin; 371f7df2e56Smrg break; 3725a112b11Smrg case XIGrabtypeGesturePinchBegin: 3735a112b11Smrg tempGrab->type = XI_GesturePinchBegin; 3745a112b11Smrg break; 3755a112b11Smrg case XIGrabtypeGestureSwipeBegin: 3765a112b11Smrg tempGrab->type = XI_GestureSwipeBegin; 3775a112b11Smrg break; 3786747b715Smrg } 379f7df2e56Smrg tempGrab->grabtype = XI2; 380f7df2e56Smrg tempGrab->modifierDevice = mod_dev; 381f7df2e56Smrg tempGrab->modifiersDetail.pMask = NULL; 382f7df2e56Smrg tempGrab->detail.exact = stuff->detail; 383f7df2e56Smrg tempGrab->detail.pMask = NULL; 3846747b715Smrg 385f7df2e56Smrg modifiers = (uint32_t *) &stuff[1]; 3866747b715Smrg 387f7df2e56Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { 388f7df2e56Smrg tempGrab->modifiersDetail.exact = *modifiers; 389f7df2e56Smrg DeletePassiveGrabFromList(tempGrab); 3906747b715Smrg } 3916747b715Smrg 392f7df2e56Smrg FreeGrab(tempGrab); 393f7df2e56Smrg 3946747b715Smrg return Success; 3956747b715Smrg} 396