1706f2543Smrg/* 2706f2543Smrg * Copyright © 2009 Red Hat, Inc. 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice (including the next 12706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the 13706f2543Smrg * Software. 14706f2543Smrg * 15706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20706f2543Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21706f2543Smrg * DEALINGS IN THE SOFTWARE. 22706f2543Smrg * 23706f2543Smrg * Author: Peter Hutterer 24706f2543Smrg */ 25706f2543Smrg 26706f2543Smrg/*********************************************************************** 27706f2543Smrg * 28706f2543Smrg * Request to grab or ungrab input device. 29706f2543Smrg * 30706f2543Smrg */ 31706f2543Smrg 32706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 33706f2543Smrg#include <dix-config.h> 34706f2543Smrg#endif 35706f2543Smrg 36706f2543Smrg#include "inputstr.h" /* DeviceIntPtr */ 37706f2543Smrg#include "windowstr.h" /* window structure */ 38706f2543Smrg#include <X11/extensions/XI2.h> 39706f2543Smrg#include <X11/extensions/XI2proto.h> 40706f2543Smrg#include "swaprep.h" 41706f2543Smrg 42706f2543Smrg#include "exglobals.h" /* BadDevice */ 43706f2543Smrg#include "exevents.h" 44706f2543Smrg#include "xipassivegrab.h" 45706f2543Smrg#include "dixgrabs.h" 46706f2543Smrg#include "misc.h" 47706f2543Smrg 48706f2543Smrgint 49706f2543SmrgSProcXIPassiveGrabDevice(ClientPtr client) 50706f2543Smrg{ 51706f2543Smrg int i; 52706f2543Smrg char n; 53706f2543Smrg xXIModifierInfo *mods; 54706f2543Smrg 55706f2543Smrg REQUEST(xXIPassiveGrabDeviceReq); 56706f2543Smrg REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); 57706f2543Smrg 58706f2543Smrg swaps(&stuff->length, n); 59706f2543Smrg swaps(&stuff->deviceid, n); 60706f2543Smrg swapl(&stuff->grab_window, n); 61706f2543Smrg swapl(&stuff->cursor, n); 62706f2543Smrg swapl(&stuff->time, n); 63706f2543Smrg swapl(&stuff->detail, n); 64706f2543Smrg swaps(&stuff->mask_len, n); 65706f2543Smrg swaps(&stuff->num_modifiers, n); 66706f2543Smrg 67706f2543Smrg REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, 68706f2543Smrg ((uint32_t) stuff->mask_len + stuff->num_modifiers) *4); 69706f2543Smrg mods = (xXIModifierInfo*)&stuff[1]; 70706f2543Smrg 71706f2543Smrg for (i = 0; i < stuff->num_modifiers; i++, mods++) 72706f2543Smrg { 73706f2543Smrg swapl(&mods->base_mods, n); 74706f2543Smrg swapl(&mods->latched_mods, n); 75706f2543Smrg swapl(&mods->locked_mods, n); 76706f2543Smrg } 77706f2543Smrg 78706f2543Smrg return ProcXIPassiveGrabDevice(client); 79706f2543Smrg} 80706f2543Smrg 81706f2543Smrgint 82706f2543SmrgProcXIPassiveGrabDevice(ClientPtr client) 83706f2543Smrg{ 84706f2543Smrg DeviceIntPtr dev, mod_dev; 85706f2543Smrg xXIPassiveGrabDeviceReply rep; 86706f2543Smrg int i, ret = Success; 87706f2543Smrg uint8_t status; 88706f2543Smrg uint32_t *modifiers; 89706f2543Smrg xXIGrabModifierInfo *modifiers_failed; 90706f2543Smrg GrabMask mask; 91706f2543Smrg GrabParameters param; 92706f2543Smrg void *tmp; 93706f2543Smrg int mask_len; 94706f2543Smrg int n; 9515d5bffaSmrg uint32_t length; 96706f2543Smrg 97706f2543Smrg REQUEST(xXIPassiveGrabDeviceReq); 98706f2543Smrg REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, 99706f2543Smrg ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4); 100706f2543Smrg 101706f2543Smrg if (stuff->deviceid == XIAllDevices) 102706f2543Smrg dev = inputInfo.all_devices; 103706f2543Smrg else if (stuff->deviceid == XIAllMasterDevices) 104706f2543Smrg dev = inputInfo.all_master_devices; 105706f2543Smrg else 106706f2543Smrg { 107706f2543Smrg ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 108706f2543Smrg if (ret != Success) 109706f2543Smrg { 110706f2543Smrg client->errorValue = stuff->deviceid; 111706f2543Smrg return ret; 112706f2543Smrg } 113706f2543Smrg } 114706f2543Smrg 115706f2543Smrg if (stuff->grab_type != XIGrabtypeButton && 116706f2543Smrg stuff->grab_type != XIGrabtypeKeycode && 117706f2543Smrg stuff->grab_type != XIGrabtypeEnter && 118706f2543Smrg stuff->grab_type != XIGrabtypeFocusIn) 119706f2543Smrg { 120706f2543Smrg client->errorValue = stuff->grab_type; 121706f2543Smrg return BadValue; 122706f2543Smrg } 123706f2543Smrg 124706f2543Smrg if ((stuff->grab_type == XIGrabtypeEnter || 125706f2543Smrg stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0) 126706f2543Smrg { 127706f2543Smrg client->errorValue = stuff->detail; 128706f2543Smrg return BadValue; 129706f2543Smrg } 130706f2543Smrg 131706f2543Smrg if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1], 132706f2543Smrg stuff->mask_len * 4) != Success) 133706f2543Smrg return BadValue; 134706f2543Smrg 135706f2543Smrg mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4); 136706f2543Smrg memset(mask.xi2mask, 0, sizeof(mask.xi2mask)); 137706f2543Smrg memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4); 138706f2543Smrg 139706f2543Smrg rep.repType = X_Reply; 140706f2543Smrg rep.RepType = X_XIPassiveGrabDevice; 141706f2543Smrg rep.length = 0; 142706f2543Smrg rep.sequenceNumber = client->sequence; 143706f2543Smrg rep.num_modifiers = 0; 144706f2543Smrg 145706f2543Smrg memset(¶m, 0, sizeof(param)); 146706f2543Smrg param.grabtype = GRABTYPE_XI2; 147706f2543Smrg param.ownerEvents = stuff->owner_events; 148706f2543Smrg param.grabWindow = stuff->grab_window; 149706f2543Smrg param.cursor = stuff->cursor; 150706f2543Smrg 151706f2543Smrg if (IsKeyboardDevice(dev)) { 152706f2543Smrg param.this_device_mode = stuff->grab_mode; 153706f2543Smrg param.other_devices_mode = stuff->paired_device_mode; 154706f2543Smrg } else { 155706f2543Smrg param.this_device_mode = stuff->paired_device_mode; 156706f2543Smrg param.other_devices_mode = stuff->grab_mode; 157706f2543Smrg } 158706f2543Smrg 159706f2543Smrg if (stuff->cursor != None) 160706f2543Smrg { 161706f2543Smrg status = dixLookupResourceByType(&tmp, stuff->cursor, 162706f2543Smrg RT_CURSOR, client, DixUseAccess); 163706f2543Smrg if (status != Success) 164706f2543Smrg { 165706f2543Smrg client->errorValue = stuff->cursor; 166706f2543Smrg return status; 167706f2543Smrg } 168706f2543Smrg } 169706f2543Smrg 170706f2543Smrg status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess); 171706f2543Smrg if (status != Success) 172706f2543Smrg return status; 173706f2543Smrg 174706f2543Smrg status = CheckGrabValues(client, ¶m); 175706f2543Smrg if (status != Success) 176706f2543Smrg return status; 177706f2543Smrg 178706f2543Smrg modifiers = (uint32_t*)&stuff[1] + stuff->mask_len; 179706f2543Smrg modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo)); 180706f2543Smrg if (!modifiers_failed) 181706f2543Smrg return BadAlloc; 182706f2543Smrg 183706f2543Smrg if (!IsMaster(dev) && dev->u.master) 184706f2543Smrg mod_dev = GetMaster(dev, MASTER_KEYBOARD); 185706f2543Smrg else 186706f2543Smrg mod_dev = dev; 187706f2543Smrg 188706f2543Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 189706f2543Smrg { 190706f2543Smrg param.modifiers = *modifiers; 191706f2543Smrg switch(stuff->grab_type) 192706f2543Smrg { 193706f2543Smrg case XIGrabtypeButton: 194706f2543Smrg status = GrabButton(client, dev, mod_dev, stuff->detail, 195706f2543Smrg ¶m, GRABTYPE_XI2, &mask); 196706f2543Smrg break; 197706f2543Smrg case XIGrabtypeKeycode: 198706f2543Smrg status = GrabKey(client, dev, mod_dev, stuff->detail, 199706f2543Smrg ¶m, GRABTYPE_XI2, &mask); 200706f2543Smrg break; 201706f2543Smrg case XIGrabtypeEnter: 202706f2543Smrg case XIGrabtypeFocusIn: 203706f2543Smrg status = GrabWindow(client, dev, stuff->grab_type, 204706f2543Smrg ¶m, &mask); 205706f2543Smrg break; 206706f2543Smrg } 207706f2543Smrg 208706f2543Smrg if (status != GrabSuccess) 209706f2543Smrg { 210706f2543Smrg xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; 211706f2543Smrg 212706f2543Smrg info->status = status; 213706f2543Smrg info->modifiers = *modifiers; 214706f2543Smrg if (client->swapped) 215706f2543Smrg swapl(&info->modifiers, n); 216706f2543Smrg 217706f2543Smrg rep.num_modifiers++; 218706f2543Smrg rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo)); 219706f2543Smrg } 220706f2543Smrg } 221706f2543Smrg 22215d5bffaSmrg /* save the value before SRepXIPassiveGrabDevice swaps it */ 22315d5bffaSmrg length = rep.length; 224706f2543Smrg WriteReplyToClient(client, sizeof(rep), &rep); 225706f2543Smrg if (rep.num_modifiers) 22615d5bffaSmrg WriteToClient(client, length * 4, (char*)modifiers_failed); 227706f2543Smrg 228706f2543Smrg free(modifiers_failed); 229706f2543Smrg return ret; 230706f2543Smrg} 231706f2543Smrg 232706f2543Smrgvoid 233706f2543SmrgSRepXIPassiveGrabDevice(ClientPtr client, int size, 234706f2543Smrg xXIPassiveGrabDeviceReply * rep) 235706f2543Smrg{ 236706f2543Smrg char n; 237706f2543Smrg 238706f2543Smrg swaps(&rep->sequenceNumber, n); 239706f2543Smrg swapl(&rep->length, n); 240706f2543Smrg swaps(&rep->num_modifiers, n); 241706f2543Smrg 242706f2543Smrg WriteToClient(client, size, (char *)rep); 243706f2543Smrg} 244706f2543Smrg 245706f2543Smrgint 246706f2543SmrgSProcXIPassiveUngrabDevice(ClientPtr client) 247706f2543Smrg{ 248706f2543Smrg char n; 249706f2543Smrg int i; 250706f2543Smrg uint32_t *modifiers; 251706f2543Smrg 252706f2543Smrg REQUEST(xXIPassiveUngrabDeviceReq); 253706f2543Smrg REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); 254706f2543Smrg 255706f2543Smrg swaps(&stuff->length, n); 256706f2543Smrg swapl(&stuff->grab_window, n); 257706f2543Smrg swaps(&stuff->deviceid, n); 258706f2543Smrg swapl(&stuff->detail, n); 259706f2543Smrg swaps(&stuff->num_modifiers, n); 260706f2543Smrg 261706f2543Smrg REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 262706f2543Smrg ((uint32_t) stuff->num_modifiers) << 2); 263706f2543Smrg modifiers = (uint32_t*)&stuff[1]; 264706f2543Smrg 265706f2543Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 266706f2543Smrg swapl(modifiers, n); 267706f2543Smrg 268706f2543Smrg return ProcXIPassiveUngrabDevice(client); 269706f2543Smrg} 270706f2543Smrg 271706f2543Smrgint 272706f2543SmrgProcXIPassiveUngrabDevice(ClientPtr client) 273706f2543Smrg{ 274706f2543Smrg DeviceIntPtr dev, mod_dev; 275706f2543Smrg WindowPtr win; 276706f2543Smrg GrabRec tempGrab; 277706f2543Smrg uint32_t* modifiers; 278706f2543Smrg int i, rc; 279706f2543Smrg 280706f2543Smrg REQUEST(xXIPassiveUngrabDeviceReq); 281706f2543Smrg REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 282706f2543Smrg ((uint32_t) stuff->num_modifiers) << 2); 283706f2543Smrg 284706f2543Smrg if (stuff->deviceid == XIAllDevices) 285706f2543Smrg dev = inputInfo.all_devices; 286706f2543Smrg else if (stuff->deviceid == XIAllMasterDevices) 287706f2543Smrg dev = inputInfo.all_master_devices; 288706f2543Smrg else 289706f2543Smrg { 290706f2543Smrg rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 291706f2543Smrg if (rc != Success) 292706f2543Smrg return rc; 293706f2543Smrg } 294706f2543Smrg 295706f2543Smrg if (stuff->grab_type != XIGrabtypeButton && 296706f2543Smrg stuff->grab_type != XIGrabtypeKeycode && 297706f2543Smrg stuff->grab_type != XIGrabtypeEnter && 298706f2543Smrg stuff->grab_type != XIGrabtypeFocusIn) 299706f2543Smrg { 300706f2543Smrg client->errorValue = stuff->grab_type; 301706f2543Smrg return BadValue; 302706f2543Smrg } 303706f2543Smrg 304706f2543Smrg if ((stuff->grab_type == XIGrabtypeEnter || 305706f2543Smrg stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0) 306706f2543Smrg { 307706f2543Smrg client->errorValue = stuff->detail; 308706f2543Smrg return BadValue; 309706f2543Smrg } 310706f2543Smrg 311706f2543Smrg rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); 312706f2543Smrg if (rc != Success) 313706f2543Smrg return rc; 314706f2543Smrg 315706f2543Smrg if (!IsMaster(dev) && dev->u.master) 316706f2543Smrg mod_dev = GetMaster(dev, MASTER_KEYBOARD); 317706f2543Smrg else 318706f2543Smrg mod_dev = dev; 319706f2543Smrg 320706f2543Smrg tempGrab.resource = client->clientAsMask; 321706f2543Smrg tempGrab.device = dev; 322706f2543Smrg tempGrab.window = win; 323706f2543Smrg switch(stuff->grab_type) 324706f2543Smrg { 325706f2543Smrg case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break; 326706f2543Smrg case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break; 327706f2543Smrg case XIGrabtypeEnter: tempGrab.type = XI_Enter; break; 328706f2543Smrg case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break; 329706f2543Smrg } 330706f2543Smrg tempGrab.grabtype = GRABTYPE_XI2; 331706f2543Smrg tempGrab.modifierDevice = mod_dev; 332706f2543Smrg tempGrab.modifiersDetail.pMask = NULL; 333706f2543Smrg tempGrab.detail.exact = stuff->detail; 334706f2543Smrg tempGrab.detail.pMask = NULL; 335706f2543Smrg 336706f2543Smrg modifiers = (uint32_t*)&stuff[1]; 337706f2543Smrg 338706f2543Smrg for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 339706f2543Smrg { 340706f2543Smrg tempGrab.modifiersDetail.exact = *modifiers; 341706f2543Smrg DeletePassiveGrabFromList(&tempGrab); 342706f2543Smrg } 343706f2543Smrg 344706f2543Smrg return Success; 345706f2543Smrg} 346