/* * Copyright © 2009 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Author: Peter Hutterer */ /*********************************************************************** * * Request to grab or ungrab input device. * */ #ifdef HAVE_DIX_CONFIG_H #include #endif #include "inputstr.h" /* DeviceIntPtr */ #include "windowstr.h" /* window structure */ #include #include #include "swaprep.h" #include "exglobals.h" /* BadDevice */ #include "exevents.h" #include "xipassivegrab.h" #include "dixgrabs.h" #include "misc.h" int SProcXIPassiveGrabDevice(ClientPtr client) { int i; char n; xXIModifierInfo *mods; REQUEST(xXIPassiveGrabDeviceReq); REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); swaps(&stuff->length, n); swaps(&stuff->deviceid, n); swapl(&stuff->grab_window, n); swapl(&stuff->cursor, n); swapl(&stuff->time, n); swapl(&stuff->detail, n); swaps(&stuff->mask_len, n); swaps(&stuff->num_modifiers, n); REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, ((uint32_t) stuff->mask_len + stuff->num_modifiers) *4); mods = (xXIModifierInfo*)&stuff[1]; for (i = 0; i < stuff->num_modifiers; i++, mods++) { swapl(&mods->base_mods, n); swapl(&mods->latched_mods, n); swapl(&mods->locked_mods, n); } return ProcXIPassiveGrabDevice(client); } int ProcXIPassiveGrabDevice(ClientPtr client) { DeviceIntPtr dev, mod_dev; xXIPassiveGrabDeviceReply rep; int i, ret = Success; uint8_t status; uint32_t *modifiers; xXIGrabModifierInfo *modifiers_failed; GrabMask mask; GrabParameters param; void *tmp; int mask_len; int n; uint32_t length; REQUEST(xXIPassiveGrabDeviceReq); REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4); if (stuff->deviceid == XIAllDevices) dev = inputInfo.all_devices; else if (stuff->deviceid == XIAllMasterDevices) dev = inputInfo.all_master_devices; else { ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); if (ret != Success) { client->errorValue = stuff->deviceid; return ret; } } if (stuff->grab_type != XIGrabtypeButton && stuff->grab_type != XIGrabtypeKeycode && stuff->grab_type != XIGrabtypeEnter && stuff->grab_type != XIGrabtypeFocusIn) { client->errorValue = stuff->grab_type; return BadValue; } if ((stuff->grab_type == XIGrabtypeEnter || stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0) { client->errorValue = stuff->detail; return BadValue; } if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1], stuff->mask_len * 4) != Success) return BadValue; mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4); memset(mask.xi2mask, 0, sizeof(mask.xi2mask)); memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4); rep.repType = X_Reply; rep.RepType = X_XIPassiveGrabDevice; rep.length = 0; rep.sequenceNumber = client->sequence; rep.num_modifiers = 0; memset(¶m, 0, sizeof(param)); param.grabtype = GRABTYPE_XI2; param.ownerEvents = stuff->owner_events; param.grabWindow = stuff->grab_window; param.cursor = stuff->cursor; if (IsKeyboardDevice(dev)) { param.this_device_mode = stuff->grab_mode; param.other_devices_mode = stuff->paired_device_mode; } else { param.this_device_mode = stuff->paired_device_mode; param.other_devices_mode = stuff->grab_mode; } if (stuff->cursor != None) { status = dixLookupResourceByType(&tmp, stuff->cursor, RT_CURSOR, client, DixUseAccess); if (status != Success) { client->errorValue = stuff->cursor; return status; } } status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess); if (status != Success) return status; status = CheckGrabValues(client, ¶m); if (status != Success) return status; modifiers = (uint32_t*)&stuff[1] + stuff->mask_len; modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo)); if (!modifiers_failed) return BadAlloc; if (!IsMaster(dev) && dev->u.master) mod_dev = GetMaster(dev, MASTER_KEYBOARD); else mod_dev = dev; for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { param.modifiers = *modifiers; switch(stuff->grab_type) { case XIGrabtypeButton: status = GrabButton(client, dev, mod_dev, stuff->detail, ¶m, GRABTYPE_XI2, &mask); break; case XIGrabtypeKeycode: status = GrabKey(client, dev, mod_dev, stuff->detail, ¶m, GRABTYPE_XI2, &mask); break; case XIGrabtypeEnter: case XIGrabtypeFocusIn: status = GrabWindow(client, dev, stuff->grab_type, ¶m, &mask); break; } if (status != GrabSuccess) { xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; info->status = status; info->modifiers = *modifiers; if (client->swapped) swapl(&info->modifiers, n); rep.num_modifiers++; rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo)); } } /* save the value before SRepXIPassiveGrabDevice swaps it */ length = rep.length; WriteReplyToClient(client, sizeof(rep), &rep); if (rep.num_modifiers) WriteToClient(client, length * 4, (char*)modifiers_failed); free(modifiers_failed); return ret; } void SRepXIPassiveGrabDevice(ClientPtr client, int size, xXIPassiveGrabDeviceReply * rep) { char n; swaps(&rep->sequenceNumber, n); swapl(&rep->length, n); swaps(&rep->num_modifiers, n); WriteToClient(client, size, (char *)rep); } int SProcXIPassiveUngrabDevice(ClientPtr client) { char n; int i; uint32_t *modifiers; REQUEST(xXIPassiveUngrabDeviceReq); REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); swaps(&stuff->length, n); swapl(&stuff->grab_window, n); swaps(&stuff->deviceid, n); swapl(&stuff->detail, n); swaps(&stuff->num_modifiers, n); REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, ((uint32_t) stuff->num_modifiers) << 2); modifiers = (uint32_t*)&stuff[1]; for (i = 0; i < stuff->num_modifiers; i++, modifiers++) swapl(modifiers, n); return ProcXIPassiveUngrabDevice(client); } int ProcXIPassiveUngrabDevice(ClientPtr client) { DeviceIntPtr dev, mod_dev; WindowPtr win; GrabRec tempGrab; uint32_t* modifiers; int i, rc; REQUEST(xXIPassiveUngrabDeviceReq); REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, ((uint32_t) stuff->num_modifiers) << 2); if (stuff->deviceid == XIAllDevices) dev = inputInfo.all_devices; else if (stuff->deviceid == XIAllMasterDevices) dev = inputInfo.all_master_devices; else { rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); if (rc != Success) return rc; } if (stuff->grab_type != XIGrabtypeButton && stuff->grab_type != XIGrabtypeKeycode && stuff->grab_type != XIGrabtypeEnter && stuff->grab_type != XIGrabtypeFocusIn) { client->errorValue = stuff->grab_type; return BadValue; } if ((stuff->grab_type == XIGrabtypeEnter || stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0) { client->errorValue = stuff->detail; return BadValue; } rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); if (rc != Success) return rc; if (!IsMaster(dev) && dev->u.master) mod_dev = GetMaster(dev, MASTER_KEYBOARD); else mod_dev = dev; tempGrab.resource = client->clientAsMask; tempGrab.device = dev; tempGrab.window = win; switch(stuff->grab_type) { case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break; case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break; case XIGrabtypeEnter: tempGrab.type = XI_Enter; break; case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break; } tempGrab.grabtype = GRABTYPE_XI2; tempGrab.modifierDevice = mod_dev; tempGrab.modifiersDetail.pMask = NULL; tempGrab.detail.exact = stuff->detail; tempGrab.detail.pMask = NULL; modifiers = (uint32_t*)&stuff[1]; for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { tempGrab.modifiersDetail.exact = *modifiers; DeletePassiveGrabFromList(&tempGrab); } return Success; }