xipassivegrab.c revision 806e81e9
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 && 117f7df2e56Smrg stuff->grab_type != XIGrabtypeTouchBegin) { 1186747b715Smrg client->errorValue = stuff->grab_type; 1196747b715Smrg return BadValue; 1206747b715Smrg } 1216747b715Smrg 1226747b715Smrg if ((stuff->grab_type == XIGrabtypeEnter || 123f7df2e56Smrg stuff->grab_type == XIGrabtypeFocusIn || 124f7df2e56Smrg stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) { 1256747b715Smrg client->errorValue = stuff->detail; 1266747b715Smrg return BadValue; 1276747b715Smrg } 1286747b715Smrg 129f7df2e56Smrg if (stuff->grab_type == XIGrabtypeTouchBegin && 130f7df2e56Smrg (stuff->grab_mode != XIGrabModeTouch || 131f7df2e56Smrg stuff->paired_device_mode != GrabModeAsync)) { 132f7df2e56Smrg client->errorValue = stuff->grab_mode; 133f7df2e56Smrg return BadValue; 134f7df2e56Smrg } 135f7df2e56Smrg 136f7df2e56Smrg if (XICheckInvalidMaskBits(client, (unsigned char *) &stuff[1], 1376747b715Smrg stuff->mask_len * 4) != Success) 1386747b715Smrg return BadValue; 1396747b715Smrg 140f7df2e56Smrg mask.xi2mask = xi2mask_new(); 141f7df2e56Smrg if (!mask.xi2mask) 142f7df2e56Smrg return BadAlloc; 1436747b715Smrg 144f7df2e56Smrg mask_len = min(xi2mask_mask_size(mask.xi2mask), stuff->mask_len * 4); 145f7df2e56Smrg xi2mask_set_one_mask(mask.xi2mask, stuff->deviceid, 146f7df2e56Smrg (unsigned char *) &stuff[1], mask_len * 4); 1476747b715Smrg 1486747b715Smrg memset(¶m, 0, sizeof(param)); 149f7df2e56Smrg param.grabtype = XI2; 1506747b715Smrg param.ownerEvents = stuff->owner_events; 1516747b715Smrg param.grabWindow = stuff->grab_window; 1526747b715Smrg param.cursor = stuff->cursor; 1536747b715Smrg 154475c125cSmrg if (IsKeyboardDevice(dev)) { 155475c125cSmrg param.this_device_mode = stuff->grab_mode; 156475c125cSmrg param.other_devices_mode = stuff->paired_device_mode; 157f7df2e56Smrg } 158f7df2e56Smrg else { 159475c125cSmrg param.this_device_mode = stuff->paired_device_mode; 160475c125cSmrg param.other_devices_mode = stuff->grab_mode; 161475c125cSmrg } 162475c125cSmrg 163f7df2e56Smrg if (stuff->cursor != None) { 164f7df2e56Smrg ret = dixLookupResourceByType(&tmp, stuff->cursor, 165f7df2e56Smrg RT_CURSOR, client, DixUseAccess); 166f7df2e56Smrg if (ret != Success) { 167f7df2e56Smrg client->errorValue = stuff->cursor; 168f7df2e56Smrg goto out; 169f7df2e56Smrg } 1706747b715Smrg } 1716747b715Smrg 172f7df2e56Smrg ret = 173f7df2e56Smrg dixLookupWindow((WindowPtr *) &tmp, stuff->grab_window, client, 174f7df2e56Smrg DixSetAttrAccess); 175f7df2e56Smrg if (ret != Success) 176f7df2e56Smrg goto out; 177f7df2e56Smrg 178f7df2e56Smrg ret = CheckGrabValues(client, ¶m); 179f7df2e56Smrg if (ret != Success) 180f7df2e56Smrg goto out; 181f7df2e56Smrg 182f7df2e56Smrg modifiers = (uint32_t *) &stuff[1] + stuff->mask_len; 183f7df2e56Smrg modifiers_failed = 184f7df2e56Smrg calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo)); 185f7df2e56Smrg if (!modifiers_failed) { 186f7df2e56Smrg ret = BadAlloc; 187f7df2e56Smrg goto out; 188f7df2e56Smrg } 1896747b715Smrg 190f7df2e56Smrg mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); 1916747b715Smrg 192f7df2e56Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { 193f7df2e56Smrg uint8_t status = Success; 1946747b715Smrg 1956747b715Smrg param.modifiers = *modifiers; 196f7df2e56Smrg ret = CheckGrabValues(client, ¶m); 197f7df2e56Smrg if (ret != Success) 198f7df2e56Smrg goto out; 199f7df2e56Smrg 200f7df2e56Smrg switch (stuff->grab_type) { 201f7df2e56Smrg case XIGrabtypeButton: 202f7df2e56Smrg status = GrabButton(client, dev, mod_dev, stuff->detail, 203f7df2e56Smrg ¶m, XI2, &mask); 204f7df2e56Smrg break; 205f7df2e56Smrg case XIGrabtypeKeycode: 206806e81e9Smrg /* XI2 allows 32-bit keycodes but thanks to XKB we can never 207806e81e9Smrg * implement this. Just return an error for all keycodes that 208806e81e9Smrg * cannot work anyway */ 209806e81e9Smrg if (stuff->detail > 255) 210806e81e9Smrg status = XIAlreadyGrabbed; 211806e81e9Smrg else 212806e81e9Smrg status = GrabKey(client, dev, mod_dev, stuff->detail, 213806e81e9Smrg ¶m, XI2, &mask); 214f7df2e56Smrg break; 215f7df2e56Smrg case XIGrabtypeEnter: 216f7df2e56Smrg case XIGrabtypeFocusIn: 217f7df2e56Smrg status = GrabWindow(client, dev, stuff->grab_type, ¶m, &mask); 218f7df2e56Smrg break; 219f7df2e56Smrg case XIGrabtypeTouchBegin: 220f7df2e56Smrg status = GrabTouch(client, dev, mod_dev, ¶m, &mask); 221f7df2e56Smrg break; 2226747b715Smrg } 2236747b715Smrg 224f7df2e56Smrg if (status != GrabSuccess) { 2256747b715Smrg xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; 2266747b715Smrg 2276747b715Smrg info->status = status; 2286747b715Smrg info->modifiers = *modifiers; 2299ace9065Smrg if (client->swapped) 230f7df2e56Smrg swapl(&info->modifiers); 2319ace9065Smrg 2326747b715Smrg rep.num_modifiers++; 2339ace9065Smrg rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo)); 2346747b715Smrg } 2356747b715Smrg } 2366747b715Smrg 2376747b715Smrg WriteReplyToClient(client, sizeof(rep), &rep); 2386747b715Smrg if (rep.num_modifiers) 239f7df2e56Smrg WriteToClient(client, rep.length * 4, modifiers_failed); 2409ace9065Smrg 241f7df2e56Smrg out: 2427e31ba66Smrg free(modifiers_failed); 243f7df2e56Smrg xi2mask_free(&mask.xi2mask); 2446747b715Smrg return ret; 2456747b715Smrg} 2466747b715Smrg 2477e31ba66Smrgvoid _X_COLD 2486747b715SmrgSRepXIPassiveGrabDevice(ClientPtr client, int size, 2496747b715Smrg xXIPassiveGrabDeviceReply * rep) 2506747b715Smrg{ 251f7df2e56Smrg swaps(&rep->sequenceNumber); 252f7df2e56Smrg swapl(&rep->length); 253f7df2e56Smrg swaps(&rep->num_modifiers); 2546747b715Smrg 255f7df2e56Smrg WriteToClient(client, size, rep); 2566747b715Smrg} 2576747b715Smrg 2587e31ba66Smrgint _X_COLD 2596747b715SmrgSProcXIPassiveUngrabDevice(ClientPtr client) 2606747b715Smrg{ 2616747b715Smrg int i; 2626747b715Smrg uint32_t *modifiers; 2636747b715Smrg 2646747b715Smrg REQUEST(xXIPassiveUngrabDeviceReq); 2650b0d8713Smrg REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); 2666747b715Smrg 267f7df2e56Smrg swaps(&stuff->length); 268f7df2e56Smrg swapl(&stuff->grab_window); 269f7df2e56Smrg swaps(&stuff->deviceid); 270f7df2e56Smrg swapl(&stuff->detail); 271f7df2e56Smrg swaps(&stuff->num_modifiers); 2726747b715Smrg 2730b0d8713Smrg REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 2740b0d8713Smrg ((uint32_t) stuff->num_modifiers) << 2); 275f7df2e56Smrg modifiers = (uint32_t *) &stuff[1]; 2766747b715Smrg 2776747b715Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 278f7df2e56Smrg swapl(modifiers); 2796747b715Smrg 2806747b715Smrg return ProcXIPassiveUngrabDevice(client); 2816747b715Smrg} 2826747b715Smrg 2836747b715Smrgint 2846747b715SmrgProcXIPassiveUngrabDevice(ClientPtr client) 2856747b715Smrg{ 2866747b715Smrg DeviceIntPtr dev, mod_dev; 2876747b715Smrg WindowPtr win; 288f7df2e56Smrg GrabPtr tempGrab; 289f7df2e56Smrg uint32_t *modifiers; 2906747b715Smrg int i, rc; 2916747b715Smrg 2926747b715Smrg REQUEST(xXIPassiveUngrabDeviceReq); 2930b0d8713Smrg REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 2940b0d8713Smrg ((uint32_t) stuff->num_modifiers) << 2); 2956747b715Smrg 296475c125cSmrg if (stuff->deviceid == XIAllDevices) 297475c125cSmrg dev = inputInfo.all_devices; 298475c125cSmrg else if (stuff->deviceid == XIAllMasterDevices) 299475c125cSmrg dev = inputInfo.all_master_devices; 300f7df2e56Smrg else { 301475c125cSmrg rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 302475c125cSmrg if (rc != Success) 303f7df2e56Smrg return rc; 304475c125cSmrg } 3056747b715Smrg 3066747b715Smrg if (stuff->grab_type != XIGrabtypeButton && 3076747b715Smrg stuff->grab_type != XIGrabtypeKeycode && 3086747b715Smrg stuff->grab_type != XIGrabtypeEnter && 309f7df2e56Smrg stuff->grab_type != XIGrabtypeFocusIn && 310f7df2e56Smrg stuff->grab_type != XIGrabtypeTouchBegin) { 3116747b715Smrg client->errorValue = stuff->grab_type; 3126747b715Smrg return BadValue; 3136747b715Smrg } 3146747b715Smrg 3156747b715Smrg if ((stuff->grab_type == XIGrabtypeEnter || 316f7df2e56Smrg stuff->grab_type == XIGrabtypeFocusIn || 317f7df2e56Smrg stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) { 3186747b715Smrg client->errorValue = stuff->detail; 3196747b715Smrg return BadValue; 3206747b715Smrg } 3216747b715Smrg 3226747b715Smrg rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); 3236747b715Smrg if (rc != Success) 3246747b715Smrg return rc; 3256747b715Smrg 326f7df2e56Smrg mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); 327f7df2e56Smrg 328f7df2e56Smrg tempGrab = AllocGrab(NULL); 329f7df2e56Smrg if (!tempGrab) 330f7df2e56Smrg return BadAlloc; 331f7df2e56Smrg 332f7df2e56Smrg tempGrab->resource = client->clientAsMask; 333f7df2e56Smrg tempGrab->device = dev; 334f7df2e56Smrg tempGrab->window = win; 335f7df2e56Smrg switch (stuff->grab_type) { 336f7df2e56Smrg case XIGrabtypeButton: 337f7df2e56Smrg tempGrab->type = XI_ButtonPress; 338f7df2e56Smrg break; 339f7df2e56Smrg case XIGrabtypeKeycode: 340f7df2e56Smrg tempGrab->type = XI_KeyPress; 341f7df2e56Smrg break; 342f7df2e56Smrg case XIGrabtypeEnter: 343f7df2e56Smrg tempGrab->type = XI_Enter; 344f7df2e56Smrg break; 345f7df2e56Smrg case XIGrabtypeFocusIn: 346f7df2e56Smrg tempGrab->type = XI_FocusIn; 347f7df2e56Smrg break; 348f7df2e56Smrg case XIGrabtypeTouchBegin: 349f7df2e56Smrg tempGrab->type = XI_TouchBegin; 350f7df2e56Smrg break; 3516747b715Smrg } 352f7df2e56Smrg tempGrab->grabtype = XI2; 353f7df2e56Smrg tempGrab->modifierDevice = mod_dev; 354f7df2e56Smrg tempGrab->modifiersDetail.pMask = NULL; 355f7df2e56Smrg tempGrab->detail.exact = stuff->detail; 356f7df2e56Smrg tempGrab->detail.pMask = NULL; 3576747b715Smrg 358f7df2e56Smrg modifiers = (uint32_t *) &stuff[1]; 3596747b715Smrg 360f7df2e56Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { 361f7df2e56Smrg tempGrab->modifiersDetail.exact = *modifiers; 362f7df2e56Smrg DeletePassiveGrabFromList(tempGrab); 3636747b715Smrg } 3646747b715Smrg 365f7df2e56Smrg FreeGrab(tempGrab); 366f7df2e56Smrg 3676747b715Smrg return Success; 3686747b715Smrg} 369