xipassivegrab.c revision 706f2543
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 48int 49SProcXIPassiveGrabDevice(ClientPtr client) 50{ 51 int i; 52 char n; 53 xXIModifierInfo *mods; 54 55 REQUEST(xXIPassiveGrabDeviceReq); 56 REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); 57 58 swaps(&stuff->length, n); 59 swaps(&stuff->deviceid, n); 60 swapl(&stuff->grab_window, n); 61 swapl(&stuff->cursor, n); 62 swapl(&stuff->time, n); 63 swapl(&stuff->detail, n); 64 swaps(&stuff->mask_len, n); 65 swaps(&stuff->num_modifiers, n); 66 67 REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, 68 ((uint32_t) stuff->mask_len + stuff->num_modifiers) *4); 69 mods = (xXIModifierInfo*)&stuff[1]; 70 71 for (i = 0; i < stuff->num_modifiers; i++, mods++) 72 { 73 swapl(&mods->base_mods, n); 74 swapl(&mods->latched_mods, n); 75 swapl(&mods->locked_mods, n); 76 } 77 78 return ProcXIPassiveGrabDevice(client); 79} 80 81int 82ProcXIPassiveGrabDevice(ClientPtr client) 83{ 84 DeviceIntPtr dev, mod_dev; 85 xXIPassiveGrabDeviceReply rep; 86 int i, ret = Success; 87 uint8_t status; 88 uint32_t *modifiers; 89 xXIGrabModifierInfo *modifiers_failed; 90 GrabMask mask; 91 GrabParameters param; 92 void *tmp; 93 int mask_len; 94 int n; 95 96 REQUEST(xXIPassiveGrabDeviceReq); 97 REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, 98 ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4); 99 100 if (stuff->deviceid == XIAllDevices) 101 dev = inputInfo.all_devices; 102 else if (stuff->deviceid == XIAllMasterDevices) 103 dev = inputInfo.all_master_devices; 104 else 105 { 106 ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 107 if (ret != Success) 108 { 109 client->errorValue = stuff->deviceid; 110 return ret; 111 } 112 } 113 114 if (stuff->grab_type != XIGrabtypeButton && 115 stuff->grab_type != XIGrabtypeKeycode && 116 stuff->grab_type != XIGrabtypeEnter && 117 stuff->grab_type != XIGrabtypeFocusIn) 118 { 119 client->errorValue = stuff->grab_type; 120 return BadValue; 121 } 122 123 if ((stuff->grab_type == XIGrabtypeEnter || 124 stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0) 125 { 126 client->errorValue = stuff->detail; 127 return BadValue; 128 } 129 130 if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1], 131 stuff->mask_len * 4) != Success) 132 return BadValue; 133 134 mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4); 135 memset(mask.xi2mask, 0, sizeof(mask.xi2mask)); 136 memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4); 137 138 rep.repType = X_Reply; 139 rep.RepType = X_XIPassiveGrabDevice; 140 rep.length = 0; 141 rep.sequenceNumber = client->sequence; 142 rep.num_modifiers = 0; 143 144 memset(¶m, 0, sizeof(param)); 145 param.grabtype = GRABTYPE_XI2; 146 param.ownerEvents = stuff->owner_events; 147 param.grabWindow = stuff->grab_window; 148 param.cursor = stuff->cursor; 149 150 if (IsKeyboardDevice(dev)) { 151 param.this_device_mode = stuff->grab_mode; 152 param.other_devices_mode = stuff->paired_device_mode; 153 } else { 154 param.this_device_mode = stuff->paired_device_mode; 155 param.other_devices_mode = stuff->grab_mode; 156 } 157 158 if (stuff->cursor != None) 159 { 160 status = dixLookupResourceByType(&tmp, stuff->cursor, 161 RT_CURSOR, client, DixUseAccess); 162 if (status != Success) 163 { 164 client->errorValue = stuff->cursor; 165 return status; 166 } 167 } 168 169 status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess); 170 if (status != Success) 171 return status; 172 173 status = CheckGrabValues(client, ¶m); 174 if (status != Success) 175 return status; 176 177 modifiers = (uint32_t*)&stuff[1] + stuff->mask_len; 178 modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo)); 179 if (!modifiers_failed) 180 return BadAlloc; 181 182 if (!IsMaster(dev) && dev->u.master) 183 mod_dev = GetMaster(dev, MASTER_KEYBOARD); 184 else 185 mod_dev = dev; 186 187 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 188 { 189 param.modifiers = *modifiers; 190 switch(stuff->grab_type) 191 { 192 case XIGrabtypeButton: 193 status = GrabButton(client, dev, mod_dev, stuff->detail, 194 ¶m, GRABTYPE_XI2, &mask); 195 break; 196 case XIGrabtypeKeycode: 197 status = GrabKey(client, dev, mod_dev, stuff->detail, 198 ¶m, GRABTYPE_XI2, &mask); 199 break; 200 case XIGrabtypeEnter: 201 case XIGrabtypeFocusIn: 202 status = GrabWindow(client, dev, stuff->grab_type, 203 ¶m, &mask); 204 break; 205 } 206 207 if (status != GrabSuccess) 208 { 209 xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; 210 211 info->status = status; 212 info->modifiers = *modifiers; 213 if (client->swapped) 214 swapl(&info->modifiers, n); 215 216 rep.num_modifiers++; 217 rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo)); 218 } 219 } 220 221 WriteReplyToClient(client, sizeof(rep), &rep); 222 if (rep.num_modifiers) 223 WriteToClient(client, rep.length * 4, (char*)modifiers_failed); 224 225 free(modifiers_failed); 226 return ret; 227} 228 229void 230SRepXIPassiveGrabDevice(ClientPtr client, int size, 231 xXIPassiveGrabDeviceReply * rep) 232{ 233 char n; 234 235 swaps(&rep->sequenceNumber, n); 236 swapl(&rep->length, n); 237 swaps(&rep->num_modifiers, n); 238 239 WriteToClient(client, size, (char *)rep); 240} 241 242int 243SProcXIPassiveUngrabDevice(ClientPtr client) 244{ 245 char n; 246 int i; 247 uint32_t *modifiers; 248 249 REQUEST(xXIPassiveUngrabDeviceReq); 250 REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); 251 252 swaps(&stuff->length, n); 253 swapl(&stuff->grab_window, n); 254 swaps(&stuff->deviceid, n); 255 swapl(&stuff->detail, n); 256 swaps(&stuff->num_modifiers, n); 257 258 REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 259 ((uint32_t) stuff->num_modifiers) << 2); 260 modifiers = (uint32_t*)&stuff[1]; 261 262 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 263 swapl(modifiers, n); 264 265 return ProcXIPassiveUngrabDevice(client); 266} 267 268int 269ProcXIPassiveUngrabDevice(ClientPtr client) 270{ 271 DeviceIntPtr dev, mod_dev; 272 WindowPtr win; 273 GrabRec tempGrab; 274 uint32_t* modifiers; 275 int i, rc; 276 277 REQUEST(xXIPassiveUngrabDeviceReq); 278 REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, 279 ((uint32_t) stuff->num_modifiers) << 2); 280 281 if (stuff->deviceid == XIAllDevices) 282 dev = inputInfo.all_devices; 283 else if (stuff->deviceid == XIAllMasterDevices) 284 dev = inputInfo.all_master_devices; 285 else 286 { 287 rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); 288 if (rc != Success) 289 return rc; 290 } 291 292 if (stuff->grab_type != XIGrabtypeButton && 293 stuff->grab_type != XIGrabtypeKeycode && 294 stuff->grab_type != XIGrabtypeEnter && 295 stuff->grab_type != XIGrabtypeFocusIn) 296 { 297 client->errorValue = stuff->grab_type; 298 return BadValue; 299 } 300 301 if ((stuff->grab_type == XIGrabtypeEnter || 302 stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0) 303 { 304 client->errorValue = stuff->detail; 305 return BadValue; 306 } 307 308 rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); 309 if (rc != Success) 310 return rc; 311 312 if (!IsMaster(dev) && dev->u.master) 313 mod_dev = GetMaster(dev, MASTER_KEYBOARD); 314 else 315 mod_dev = dev; 316 317 tempGrab.resource = client->clientAsMask; 318 tempGrab.device = dev; 319 tempGrab.window = win; 320 switch(stuff->grab_type) 321 { 322 case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break; 323 case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break; 324 case XIGrabtypeEnter: tempGrab.type = XI_Enter; break; 325 case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break; 326 } 327 tempGrab.grabtype = GRABTYPE_XI2; 328 tempGrab.modifierDevice = mod_dev; 329 tempGrab.modifiersDetail.pMask = NULL; 330 tempGrab.detail.exact = stuff->detail; 331 tempGrab.detail.pMask = NULL; 332 333 modifiers = (uint32_t*)&stuff[1]; 334 335 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) 336 { 337 tempGrab.modifiersDetail.exact = *modifiers; 338 DeletePassiveGrabFromList(&tempGrab); 339 } 340 341 return Success; 342} 343