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