summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2009-05-04 17:38:02 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2009-05-06 14:37:33 +1000
commitd220d6907d1d5138d1528c48b739e77f65616225 (patch)
treecaaaa8b401f9de2115f649557afeb74d9917fc87
parent1b593ced171d02f1d00034f0f733060706bb6d41 (diff)
Xi: add GrabButton and GrabKeysym code.
We don't do keycode grabs in XI2, they're pointless.
-rw-r--r--Xi/Makefile.am2
-rw-r--r--Xi/exevents.c34
-rw-r--r--Xi/extinit.c11
-rw-r--r--Xi/xipassivegrab.c269
-rw-r--r--Xi/xipassivegrab.h35
-rw-r--r--dix/events.c36
-rw-r--r--dix/grabs.c3
-rw-r--r--include/xkbsrv.h4
-rw-r--r--xkb/xkbUtils.c30
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(&param, 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,
+ &param, GRABTYPE_XI2, &mask);
+ break;
+ case GrabtypeKeysym:
+ status = GrabKey(client, dev, mod_dev, stuff->detail,
+ &param, 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);
+}