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