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; 96875c6e4fSmrg uint32_t length; 976747b715Smrg 986747b715Smrg REQUEST(xXIPassiveGrabDeviceReq); 990b0d8713Smrg REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, 1000b0d8713Smrg ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4); 1016747b715Smrg 1026747b715Smrg if (stuff->deviceid == XIAllDevices) 1036747b715Smrg dev = inputInfo.all_devices; 1046747b715Smrg else if (stuff->deviceid == XIAllMasterDevices) 1056747b715Smrg dev = inputInfo.all_master_devices; 106f7df2e56Smrg else { 1076747b715Smrg ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 108f7df2e56Smrg if (ret != Success) { 1099ace9065Smrg client->errorValue = stuff->deviceid; 1106747b715Smrg return ret; 1119ace9065Smrg } 1126747b715Smrg } 1136747b715Smrg 1146747b715Smrg if (stuff->grab_type != XIGrabtypeButton && 1156747b715Smrg stuff->grab_type != XIGrabtypeKeycode && 1166747b715Smrg stuff->grab_type != XIGrabtypeEnter && 117f7df2e56Smrg stuff->grab_type != XIGrabtypeFocusIn && 1185a112b11Smrg stuff->grab_type != XIGrabtypeTouchBegin && 1195a112b11Smrg stuff->grab_type != XIGrabtypeGesturePinchBegin && 1205a112b11Smrg stuff->grab_type != XIGrabtypeGestureSwipeBegin) { 1216747b715Smrg client->errorValue = stuff->grab_type; 1226747b715Smrg return BadValue; 1236747b715Smrg } 1246747b715Smrg 1256747b715Smrg if ((stuff->grab_type == XIGrabtypeEnter || 126f7df2e56Smrg stuff->grab_type == XIGrabtypeFocusIn || 1275a112b11Smrg stuff->grab_type == XIGrabtypeTouchBegin || 1285a112b11Smrg stuff->grab_type == XIGrabtypeGesturePinchBegin || 1295a112b11Smrg stuff->grab_type == XIGrabtypeGestureSwipeBegin) && stuff->detail != 0) { 1306747b715Smrg client->errorValue = stuff->detail; 1316747b715Smrg return BadValue; 1326747b715Smrg } 1336747b715Smrg 134f7df2e56Smrg if (stuff->grab_type == XIGrabtypeTouchBegin && 135f7df2e56Smrg (stuff->grab_mode != XIGrabModeTouch || 136f7df2e56Smrg stuff->paired_device_mode != GrabModeAsync)) { 137f7df2e56Smrg client->errorValue = stuff->grab_mode; 138f7df2e56Smrg return BadValue; 139f7df2e56Smrg } 140f7df2e56Smrg 141e383896cSmrg /* XI2 allows 32-bit keycodes but thanks to XKB we can never 142e383896cSmrg * implement this. Just return an error for all keycodes that 143e383896cSmrg * cannot work anyway, same for buttons > 255. */ 144e383896cSmrg if (stuff->detail > 255) 145e383896cSmrg return XIAlreadyGrabbed; 146e383896cSmrg 147f7df2e56Smrg if (XICheckInvalidMaskBits(client, (unsigned char *) &stuff[1], 1486747b715Smrg stuff->mask_len * 4) != Success) 1496747b715Smrg return BadValue; 1506747b715Smrg 151f7df2e56Smrg mask.xi2mask = xi2mask_new(); 152f7df2e56Smrg if (!mask.xi2mask) 153f7df2e56Smrg return BadAlloc; 1546747b715Smrg 155f7df2e56Smrg mask_len = min(xi2mask_mask_size(mask.xi2mask), stuff->mask_len * 4); 156f7df2e56Smrg xi2mask_set_one_mask(mask.xi2mask, stuff->deviceid, 157f7df2e56Smrg (unsigned char *) &stuff[1], mask_len * 4); 1586747b715Smrg 1596747b715Smrg memset(¶m, 0, sizeof(param)); 160f7df2e56Smrg param.grabtype = XI2; 1616747b715Smrg param.ownerEvents = stuff->owner_events; 1626747b715Smrg param.grabWindow = stuff->grab_window; 1636747b715Smrg param.cursor = stuff->cursor; 1646747b715Smrg 165475c125cSmrg if (IsKeyboardDevice(dev)) { 166475c125cSmrg param.this_device_mode = stuff->grab_mode; 167475c125cSmrg param.other_devices_mode = stuff->paired_device_mode; 168f7df2e56Smrg } 169f7df2e56Smrg else { 170475c125cSmrg param.this_device_mode = stuff->paired_device_mode; 171475c125cSmrg param.other_devices_mode = stuff->grab_mode; 172475c125cSmrg } 173475c125cSmrg 174f7df2e56Smrg if (stuff->cursor != None) { 175f7df2e56Smrg ret = dixLookupResourceByType(&tmp, stuff->cursor, 176f7df2e56Smrg RT_CURSOR, client, DixUseAccess); 177f7df2e56Smrg if (ret != Success) { 178f7df2e56Smrg client->errorValue = stuff->cursor; 179f7df2e56Smrg goto out; 180f7df2e56Smrg } 1816747b715Smrg } 1826747b715Smrg 183f7df2e56Smrg ret = 184f7df2e56Smrg dixLookupWindow((WindowPtr *) &tmp, stuff->grab_window, client, 185f7df2e56Smrg DixSetAttrAccess); 186f7df2e56Smrg if (ret != Success) 187f7df2e56Smrg goto out; 188f7df2e56Smrg 189f7df2e56Smrg ret = CheckGrabValues(client, ¶m); 190f7df2e56Smrg if (ret != Success) 191f7df2e56Smrg goto out; 192f7df2e56Smrg 193f7df2e56Smrg modifiers = (uint32_t *) &stuff[1] + stuff->mask_len; 194f7df2e56Smrg modifiers_failed = 195f7df2e56Smrg calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo)); 196f7df2e56Smrg if (!modifiers_failed) { 197f7df2e56Smrg ret = BadAlloc; 198f7df2e56Smrg goto out; 199f7df2e56Smrg } 2006747b715Smrg 201f7df2e56Smrg mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); 2026747b715Smrg 203f7df2e56Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { 204f7df2e56Smrg uint8_t status = Success; 2056747b715Smrg 2066747b715Smrg param.modifiers = *modifiers; 207f7df2e56Smrg ret = CheckGrabValues(client, ¶m); 208f7df2e56Smrg if (ret != Success) 209f7df2e56Smrg goto out; 210f7df2e56Smrg 211f7df2e56Smrg switch (stuff->grab_type) { 212f7df2e56Smrg case XIGrabtypeButton: 213f7df2e56Smrg status = GrabButton(client, dev, mod_dev, stuff->detail, 214f7df2e56Smrg ¶m, XI2, &mask); 215f7df2e56Smrg break; 216f7df2e56Smrg case XIGrabtypeKeycode: 217e383896cSmrg status = GrabKey(client, dev, mod_dev, stuff->detail, 218e383896cSmrg ¶m, XI2, &mask); 219f7df2e56Smrg break; 220f7df2e56Smrg case XIGrabtypeEnter: 221f7df2e56Smrg case XIGrabtypeFocusIn: 222f7df2e56Smrg status = GrabWindow(client, dev, stuff->grab_type, ¶m, &mask); 223f7df2e56Smrg break; 224f7df2e56Smrg case XIGrabtypeTouchBegin: 2255a112b11Smrg status = GrabTouchOrGesture(client, dev, mod_dev, XI_TouchBegin, 2265a112b11Smrg ¶m, &mask); 2275a112b11Smrg break; 2285a112b11Smrg case XIGrabtypeGesturePinchBegin: 2295a112b11Smrg status = GrabTouchOrGesture(client, dev, mod_dev, 2305a112b11Smrg XI_GesturePinchBegin, ¶m, &mask); 2315a112b11Smrg break; 2325a112b11Smrg case XIGrabtypeGestureSwipeBegin: 2335a112b11Smrg status = GrabTouchOrGesture(client, dev, mod_dev, 2345a112b11Smrg XI_GestureSwipeBegin, ¶m, &mask); 235f7df2e56Smrg break; 2366747b715Smrg } 2376747b715Smrg 238f7df2e56Smrg if (status != GrabSuccess) { 2396747b715Smrg xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; 2406747b715Smrg 2416747b715Smrg info->status = status; 2426747b715Smrg info->modifiers = *modifiers; 2439ace9065Smrg if (client->swapped) 244f7df2e56Smrg swapl(&info->modifiers); 2459ace9065Smrg 2466747b715Smrg rep.num_modifiers++; 2479ace9065Smrg rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo)); 2486747b715Smrg } 2496747b715Smrg } 2506747b715Smrg 251875c6e4fSmrg /* save the value before SRepXIPassiveGrabDevice swaps it */ 252875c6e4fSmrg length = rep.length; 2536747b715Smrg WriteReplyToClient(client, sizeof(rep), &rep); 2546747b715Smrg if (rep.num_modifiers) 255875c6e4fSmrg WriteToClient(client, length * 4, modifiers_failed); 2569ace9065Smrg 257f7df2e56Smrg out: 2587e31ba66Smrg free(modifiers_failed); 259f7df2e56Smrg xi2mask_free(&mask.xi2mask); 2606747b715Smrg return ret; 2616747b715Smrg} 2626747b715Smrg 2637e31ba66Smrgvoid _X_COLD 2646747b715SmrgSRepXIPassiveGrabDevice(ClientPtr client, int size, 2656747b715Smrg xXIPassiveGrabDeviceReply * rep) 2666747b715Smrg{ 267f7df2e56Smrg swaps(&rep->sequenceNumber); 268f7df2e56Smrg swapl(&rep->length); 269f7df2e56Smrg swaps(&rep->num_modifiers); 2706747b715Smrg 271f7df2e56Smrg WriteToClient(client, size, rep); 2726747b715Smrg} 2736747b715Smrg 2747e31ba66Smrgint _X_COLD 2756747b715SmrgSProcXIPassiveUngrabDevice(ClientPtr client) 2766747b715Smrg{ 2776747b715Smrg int i; 2786747b715Smrg uint32_t *modifiers; 2796747b715Smrg 2806747b715Smrg REQUEST(xXIPassiveUngrabDeviceReq); 2810b0d8713Smrg REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); 2826747b715Smrg 283f7df2e56Smrg swaps(&stuff->length); 284f7df2e56Smrg swapl(&stuff->grab_window); 285f7df2e56Smrg swaps(&stuff->deviceid); 286f7df2e56Smrg swapl(&stuff->detail); 287f7df2e56Smrg swaps(&stuff->num_modifiers); 2886747b715Smrg 2890b0d8713Smrg REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 2900b0d8713Smrg ((uint32_t) stuff->num_modifiers) << 2); 291f7df2e56Smrg modifiers = (uint32_t *) &stuff[1]; 2926747b715Smrg 2936747b715Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 294f7df2e56Smrg swapl(modifiers); 2956747b715Smrg 2966747b715Smrg return ProcXIPassiveUngrabDevice(client); 2976747b715Smrg} 2986747b715Smrg 2996747b715Smrgint 3006747b715SmrgProcXIPassiveUngrabDevice(ClientPtr client) 3016747b715Smrg{ 3026747b715Smrg DeviceIntPtr dev, mod_dev; 3036747b715Smrg WindowPtr win; 304f7df2e56Smrg GrabPtr tempGrab; 305f7df2e56Smrg uint32_t *modifiers; 3066747b715Smrg int i, rc; 3076747b715Smrg 3086747b715Smrg REQUEST(xXIPassiveUngrabDeviceReq); 3090b0d8713Smrg REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 3100b0d8713Smrg ((uint32_t) stuff->num_modifiers) << 2); 3116747b715Smrg 312475c125cSmrg if (stuff->deviceid == XIAllDevices) 313475c125cSmrg dev = inputInfo.all_devices; 314475c125cSmrg else if (stuff->deviceid == XIAllMasterDevices) 315475c125cSmrg dev = inputInfo.all_master_devices; 316f7df2e56Smrg else { 317475c125cSmrg rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 318475c125cSmrg if (rc != Success) 319f7df2e56Smrg return rc; 320475c125cSmrg } 3216747b715Smrg 3226747b715Smrg if (stuff->grab_type != XIGrabtypeButton && 3236747b715Smrg stuff->grab_type != XIGrabtypeKeycode && 3246747b715Smrg stuff->grab_type != XIGrabtypeEnter && 325f7df2e56Smrg stuff->grab_type != XIGrabtypeFocusIn && 3265a112b11Smrg stuff->grab_type != XIGrabtypeTouchBegin && 3275a112b11Smrg stuff->grab_type != XIGrabtypeGesturePinchBegin && 3285a112b11Smrg stuff->grab_type != XIGrabtypeGestureSwipeBegin) { 3296747b715Smrg client->errorValue = stuff->grab_type; 3306747b715Smrg return BadValue; 3316747b715Smrg } 3326747b715Smrg 3336747b715Smrg if ((stuff->grab_type == XIGrabtypeEnter || 334f7df2e56Smrg stuff->grab_type == XIGrabtypeFocusIn || 335f7df2e56Smrg stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) { 3366747b715Smrg client->errorValue = stuff->detail; 3376747b715Smrg return BadValue; 3386747b715Smrg } 3396747b715Smrg 340e383896cSmrg /* We don't allow passive grabs for details > 255 anyway */ 341e383896cSmrg if (stuff->detail > 255) { 342e383896cSmrg client->errorValue = stuff->detail; 343e383896cSmrg return BadValue; 344e383896cSmrg } 345e383896cSmrg 3466747b715Smrg rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); 3476747b715Smrg if (rc != Success) 3486747b715Smrg return rc; 3496747b715Smrg 350f7df2e56Smrg mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); 351f7df2e56Smrg 352f7df2e56Smrg tempGrab = AllocGrab(NULL); 353f7df2e56Smrg if (!tempGrab) 354f7df2e56Smrg return BadAlloc; 355f7df2e56Smrg 356f7df2e56Smrg tempGrab->resource = client->clientAsMask; 357f7df2e56Smrg tempGrab->device = dev; 358f7df2e56Smrg tempGrab->window = win; 359f7df2e56Smrg switch (stuff->grab_type) { 360f7df2e56Smrg case XIGrabtypeButton: 361f7df2e56Smrg tempGrab->type = XI_ButtonPress; 362f7df2e56Smrg break; 363f7df2e56Smrg case XIGrabtypeKeycode: 364f7df2e56Smrg tempGrab->type = XI_KeyPress; 365f7df2e56Smrg break; 366f7df2e56Smrg case XIGrabtypeEnter: 367f7df2e56Smrg tempGrab->type = XI_Enter; 368f7df2e56Smrg break; 369f7df2e56Smrg case XIGrabtypeFocusIn: 370f7df2e56Smrg tempGrab->type = XI_FocusIn; 371f7df2e56Smrg break; 372f7df2e56Smrg case XIGrabtypeTouchBegin: 373f7df2e56Smrg tempGrab->type = XI_TouchBegin; 374f7df2e56Smrg break; 3755a112b11Smrg case XIGrabtypeGesturePinchBegin: 3765a112b11Smrg tempGrab->type = XI_GesturePinchBegin; 3775a112b11Smrg break; 3785a112b11Smrg case XIGrabtypeGestureSwipeBegin: 3795a112b11Smrg tempGrab->type = XI_GestureSwipeBegin; 3805a112b11Smrg break; 3816747b715Smrg } 382f7df2e56Smrg tempGrab->grabtype = XI2; 383f7df2e56Smrg tempGrab->modifierDevice = mod_dev; 384f7df2e56Smrg tempGrab->modifiersDetail.pMask = NULL; 385f7df2e56Smrg tempGrab->detail.exact = stuff->detail; 386f7df2e56Smrg tempGrab->detail.pMask = NULL; 3876747b715Smrg 388f7df2e56Smrg modifiers = (uint32_t *) &stuff[1]; 3896747b715Smrg 390f7df2e56Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { 391f7df2e56Smrg tempGrab->modifiersDetail.exact = *modifiers; 392f7df2e56Smrg DeletePassiveGrabFromList(tempGrab); 3936747b715Smrg } 3946747b715Smrg 395f7df2e56Smrg FreeGrab(tempGrab); 396f7df2e56Smrg 3976747b715Smrg return Success; 3986747b715Smrg} 399