diff options
Diffstat (limited to 'xorg-server/Xi/xipassivegrab.c')
-rw-r--r-- | xorg-server/Xi/xipassivegrab.c | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/xorg-server/Xi/xipassivegrab.c b/xorg-server/Xi/xipassivegrab.c new file mode 100644 index 000000000..41a56b14e --- /dev/null +++ b/xorg-server/Xi/xipassivegrab.c @@ -0,0 +1,313 @@ +/* + * 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 <dix-config.h> +#endif + +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include <X11/extensions/XI2.h> +#include <X11/extensions/XI2proto.h> +#include "swaprep.h" + +#include "exglobals.h" /* BadDevice */ +#include "exevents.h" +#include "xipassivegrab.h" +#include "dixgrabs.h" + +int +SProcXIPassiveGrabDevice(ClientPtr client) +{ + int i; + char n; + xXIModifierInfo *mods; + + REQUEST(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); + + 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; + + REQUEST(xXIPassiveGrabDeviceReq); + REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); + + 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) + 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((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.this_device_mode = stuff->grab_mode; + param.other_devices_mode = stuff->paired_device_mode; + param.grabWindow = stuff->grab_window; + param.cursor = stuff->cursor; + + if (stuff->cursor != None) + { + status = dixLookupResourceByType(&tmp, stuff->cursor, + RT_CURSOR, client, DixUseAccess); + if (status != Success) + { + client->errorValue = stuff->cursor; + return (status == BadValue) ? BadCursor : status; + } + } + + status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess); + if (status != Success) + return status; + + status = CheckGrabValues(client, ¶m); + + modifiers = (uint32_t*)&stuff[1] + stuff->mask_len; + modifiers_failed = xcalloc(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; + rep.num_modifiers++; + rep.length++; + } + } + + WriteReplyToClient(client, sizeof(rep), &rep); + if (rep.num_modifiers) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, rep.num_modifiers * 4, (char*)modifiers_failed); + } + xfree(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); + + swaps(&stuff->length, n); + swapl(&stuff->grab_window, n); + swaps(&stuff->deviceid, n); + swapl(&stuff->detail, n); + swaps(&stuff->num_modifiers, n); + + 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_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); + + 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; +} |