diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2009-05-04 17:38:02 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2009-05-06 14:37:33 +1000 |
commit | d220d6907d1d5138d1528c48b739e77f65616225 (patch) | |
tree | caaaa8b401f9de2115f649557afeb74d9917fc87 | |
parent | 1b593ced171d02f1d00034f0f733060706bb6d41 (diff) |
Xi: add GrabButton and GrabKeysym code.
We don't do keycode grabs in XI2, they're pointless.
-rw-r--r-- | Xi/Makefile.am | 2 | ||||
-rw-r--r-- | Xi/exevents.c | 34 | ||||
-rw-r--r-- | Xi/extinit.c | 11 | ||||
-rw-r--r-- | Xi/xipassivegrab.c | 269 | ||||
-rw-r--r-- | Xi/xipassivegrab.h | 35 | ||||
-rw-r--r-- | dix/events.c | 36 | ||||
-rw-r--r-- | dix/grabs.c | 3 | ||||
-rw-r--r-- | include/xkbsrv.h | 4 | ||||
-rw-r--r-- | xkb/xkbUtils.c | 30 |
9 files changed, 405 insertions, 19 deletions
diff --git a/Xi/Makefile.am b/Xi/Makefile.am index 1fa7b9aeb..56404b6eb 100644 --- a/Xi/Makefile.am +++ b/Xi/Makefile.am @@ -96,6 +96,8 @@ libXi_la_SOURCES = \ xiallowev.h \ xigrabdev.c \ xigrabdev.h \ + xipassivegrab.h \ + xipassivegrab.c \ xiproperty.c \ xiproperty.h \ xiselectev.c \ diff --git a/Xi/exevents.c b/Xi/exevents.c index a01432cf2..12c53eba2 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1388,7 +1388,7 @@ GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, WindowPtr pWin, confineTo; CursorPtr cursor; GrabPtr grab; - int rc; + int rc, type; Mask access_mode = DixGrabAccess; rc = CheckGrabValues(client, param); @@ -1422,14 +1422,22 @@ GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, if (rc != Success) return rc; + if (grabtype == GRABTYPE_XI) + type = DeviceButtonPress; + else if (grabtype == GRABTYPE_XI2) + type = XI_ButtonPress; grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, - mask, param, DeviceButtonPress, button, confineTo, cursor); + mask, param, type, button, confineTo, cursor); if (!grab) return BadAlloc; return AddPassiveGrabToList(client, grab); } +/** + * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If + * grabtype is GRABTYPE_XI2, the key is a keysym. + */ int GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, int key, GrabParameters *param, GrabType grabtype, GrabMask *mask) @@ -1438,19 +1446,25 @@ GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, GrabPtr grab; KeyClassPtr k = dev->key; Mask access_mode = DixGrabAccess; - int rc; + int rc, type; rc = CheckGrabValues(client, param); if (rc != Success) return rc; if (k == NULL) return BadMatch; - if ((key > k->xkbInfo->desc->max_key_code || - key < k->xkbInfo->desc->min_key_code) - && (key != AnyKey)) { - client->errorValue = key; - return BadValue; - } + if (grabtype == GRABTYPE_XI) + { + if ((key > k->xkbInfo->desc->max_key_code || + key < k->xkbInfo->desc->min_key_code) + && (key != AnyKey)) { + client->errorValue = key; + return BadValue; + } + type = DeviceKeyPress; + } else if (grabtype == GRABTYPE_XI2) + type = XI_KeyPress; + rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess); if (rc != Success) return rc; @@ -1461,7 +1475,7 @@ GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device, return rc; grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype, - mask, param, DeviceKeyPress, key, NULL, NULL); + mask, param, type, key, NULL, NULL); if (!grab) return BadAlloc; return AddPassiveGrabToList(client, grab); diff --git a/Xi/extinit.c b/Xi/extinit.c index fa7031e6c..ea778e62f 100644 --- a/Xi/extinit.c +++ b/Xi/extinit.c @@ -122,6 +122,7 @@ SOFTWARE. #include "xiallowev.h" #include "xiselectev.h" #include "xigrabdev.h" +#include "xipassivegrab.h" #include "xisetdevfocus.h" #include "xiproperty.h" @@ -247,7 +248,9 @@ static int (*ProcIVector[])(ClientPtr) = { ProcXIGetDeviceFocus, /* 50 */ ProcXIGrabDevice, /* 51 */ ProcXIUngrabDevice, /* 52 */ - ProcXIAllowEvents /* 53 */ + ProcXIAllowEvents, /* 53 */ + ProcXIPassiveGrabDevice, /* 54 */ + ProcXIPassiveUngrabDevice /* 55 */ }; /* For swapped clients */ @@ -305,7 +308,9 @@ static int (*SProcIVector[])(ClientPtr) = { SProcXIGetDeviceFocus, /* 50 */ SProcXIGrabDevice, /* 51 */ SProcXIUngrabDevice, /* 52 */ - SProcXIAllowEvents /* 53 */ + SProcXIAllowEvents, /* 53 */ + SProcXIPassiveGrabDevice, /* 54 */ + SProcXIPassiveUngrabDevice /* 55 */ }; /***************************************************************** @@ -498,6 +503,8 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep) SRepXIQueryDevice(client, len, (xXIQueryDeviceReply*)rep); else if (rep->RepType == X_XIGrabDevice) SRepXIGrabDevice(client, len, (xXIGrabDeviceReply *) rep); + else if (rep->RepType == X_XIGrabDevice) + SRepXIPassiveGrabDevice(client, len, (xXIPassiveGrabDeviceReply *) rep); else { FatalError("XINPUT confused sending swapped reply"); } diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c new file mode 100644 index 000000000..61f36d268 --- /dev/null +++ b/Xi/xipassivegrab.c @@ -0,0 +1,269 @@ +/* + * 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; + + REQUEST(xXIPassiveGrabDeviceReq); + REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); + + ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); + if (ret != Success) + return ret; + + if (stuff->grab_type != GrabtypeButton && + stuff->grab_type != GrabtypeKeysym) + { + client->errorValue = stuff->grab_type; + return BadValue; + } + + /* Can't grab for modifiers on an attached slave device */ + if (!dev->isMaster) + { + if (!dev->u.master) + stuff->paired_device_mode = GrabModeAsync; + else if (dev->u.master && stuff->num_modifiers) + return BadDevice; + } + if ((stuff->mask_len * 4) > XI_LASTEVENT) + { + unsigned char *bits = (unsigned char*)&stuff[1]; + for (i = XI_LASTEVENT; i < stuff->mask_len * 4; i++) + { + if (BitIsOn(bits, i)) + return BadValue; + } + } + + memset(mask.xi2mask, 0, sizeof(mask.xi2mask)); + memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], stuff->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.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; + + modifiers = (uint32_t*)&stuff[1] + stuff->mask_len; + modifiers_failed = xcalloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo)); + if (!modifiers_failed) + return BadAlloc; + + if (dev->isMaster) + mod_dev = GetPairedDevice(dev); + else + mod_dev = dev; + + for (i = 0; i < stuff->num_modifiers; i++, modifiers++) + { + param.modifiers = *modifiers; + switch(stuff->grab_type) + { + case GrabtypeButton: + status = GrabButton(client, dev, mod_dev, stuff->detail, + ¶m, GRABTYPE_XI2, &mask); + break; + case GrabtypeKeysym: + status = GrabKey(client, dev, mod_dev, stuff->detail, + ¶m, GRABTYPE_XI2, &mask); + break; + } + + if (status != GrabSuccess) + { + xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; + + info->status = status; + info->modifiers = *modifiers; + rep.num_modifiers++; + } + } + + 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 != GrabtypeButton && + stuff->grab_type != GrabtypeKeysym) + { + client->errorValue = stuff->grab_type; + return BadValue; + } + + rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); + if (rc != Success) + return rc; + + if (dev->isMaster) + mod_dev = GetPairedDevice(dev); + else + mod_dev = dev; + + tempGrab.device = dev; + tempGrab.window = win; + tempGrab.type = + (stuff->grab_type == GrabtypeButton) ? XI_ButtonPress : XI_KeyPress; + 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; +} diff --git a/Xi/xipassivegrab.h b/Xi/xipassivegrab.h new file mode 100644 index 000000000..84fb5eb84 --- /dev/null +++ b/Xi/xipassivegrab.h @@ -0,0 +1,35 @@ +/* + * 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 + */ + +#ifndef XIPASSIVEGRAB_H +#define XIPASSIVEGRAB_H + +int SProcXIPassiveUngrabDevice(ClientPtr client); +int ProcXIPassiveUngrabDevice(ClientPtr client); +void SRepXIPassiveGrabDevice(ClientPtr client, int size, xXIPassiveGrabDeviceReply * rep); +int ProcXIPassiveGrabDevice(ClientPtr client); +int SProcXIPassiveGrabDevice(ClientPtr client); + +#endif diff --git a/dix/events.c b/dix/events.c index 0ff8308f2..bfdb096e0 100644 --- a/dix/events.c +++ b/dix/events.c @@ -3290,6 +3290,7 @@ CheckPassiveGrabsOnWindow( GrabInfoPtr grabinfo; #define CORE_MATCH 0x1 #define XI_MATCH 0x2 +#define XI2_MATCH 0x4 int match = 0; if (!grab) @@ -3319,13 +3320,24 @@ CheckPassiveGrabsOnWindow( xkbi= gdev->key->xkbInfo; tempGrab.modifierDevice = grab->modifierDevice; tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; - /* FIXME: check for xi2 grabs */ - /* Check for XI grabs first */ - tempGrab.type = GetXIType((InternalEvent*)event); - tempGrab.grabtype = GRABTYPE_XI; - if (GrabMatchesSecond(&tempGrab, grab, FALSE)) - match = XI_MATCH; + /* Check for XI2 and XI grabs first */ + tempGrab.type = GetXI2Type((InternalEvent*)event); + tempGrab.grabtype = GRABTYPE_XI2; + if (event->type == ET_KeyPress) + tempGrab.detail.exact = XkbGetKeysym(device, event); + if (GrabMatchesSecond(&tempGrab, grab, FALSE)) + match = XI2_MATCH; + + tempGrab.detail.exact = event->detail.key; + if (!match) + { + tempGrab.type = GetXIType((InternalEvent*)event); + tempGrab.grabtype = GRABTYPE_XI; + if (GrabMatchesSecond(&tempGrab, grab, FALSE)) + match = XI_MATCH; + } + /* Check for a core grab (ignore the device when comparing) */ if (!match && checkCore) { @@ -3399,6 +3411,15 @@ CheckPassiveGrabsOnWindow( } xE = &core; count = 1; + } else if (match & XI2_MATCH) + { + rc = EventToXI2((InternalEvent*)event, &xE); + if (rc != Success) + { + ErrorF("[dix] %s: XI2 conversion failed in CPGFW " + "(%d, %d).\n", device->name, event->type, rc); + continue; + } } else { rc = EventToXI((InternalEvent*)event, &xE, &count); @@ -3427,7 +3448,7 @@ CheckPassiveGrabsOnWindow( grabinfo->sync.state = FROZEN_WITH_EVENT; } - if (match & XI_MATCH) + if (match & (XI_MATCH | XI2_MATCH)) xfree(xE); /* on core match xE == &core */ return TRUE; } @@ -3435,6 +3456,7 @@ CheckPassiveGrabsOnWindow( return FALSE; #undef CORE_MATCH #undef XI_MATCH +#undef XI2_MATCH } /** diff --git a/dix/grabs.c b/dix/grabs.c index 03776d2e5..eb8bec85f 100644 --- a/dix/grabs.c +++ b/dix/grabs.c @@ -104,6 +104,9 @@ CreateGrab( grab->confineTo = confineTo; grab->cursor = cursor; grab->next = NULL; + + if (grabtype == GRABTYPE_XI2) + memcpy(grab->xi2mask, mask->xi2mask, sizeof(mask->xi2mask)); if (cursor) cursor->refcnt++; return grab; diff --git a/include/xkbsrv.h b/include/xkbsrv.h index 1ca0e3059..64584ff96 100644 --- a/include/xkbsrv.h +++ b/include/xkbsrv.h @@ -948,6 +948,10 @@ extern Bool XkbCopyDeviceKeymap( DeviceIntPtr /* dst */, DeviceIntPtr /* src */); +extern int XkbGetKeysym( + DeviceIntPtr /* dev */, + DeviceEvent* /* event*/); + #include "xkbfile.h" #include <X11/extensions/XKMformat.h> #include "xkbrules.h" diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index 5ae426dbb..0bd41cd34 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -2116,3 +2116,33 @@ XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src) return ret; } + +int +XkbGetKeysym(DeviceIntPtr dev, DeviceEvent *event) +{ + XkbDescPtr xkb = dev->key->xkbInfo->desc; + XkbKeyTypePtr kt; + int group; + int i, level = 0; + int modmask; + + group = event->group.base + event->group.latched + event->group.locked; + + if (group >= xkb->ctrls->num_groups) + group = XkbAdjustGroup(group, xkb->ctrls); + + modmask = event->mods.base | event->mods.latched; /* don't care about + locked mods */ + kt = XkbKeyKeyType(xkb, event->detail.key, group); + + for (i = 0; i < kt->map_count; i++) + { + if (kt->map[i].mods.mask == modmask) + { + level = kt->map[i].level; + break; + } + } + + return XkbKeySymEntry(xkb, event->detail.key, level, group); +} |