summaryrefslogtreecommitdiff
path: root/dix
diff options
context:
space:
mode:
authorDaniel Stone <daniel@fooishbar.org>2008-08-12 00:35:56 +0300
committerDaniel Stone <daniel@fooishbar.org>2009-01-22 15:08:58 +1100
commitbc909f71367a02297e725bb5769c2bcadab22395 (patch)
tree509819678ca888479e3142446d6e1c25cf68d3c0 /dix
parentf06a9d2e05e13466c115fc706966a90b1fb0518e (diff)
Input: Centralise pointer map changing
Replace both core and Xi functions with one function that validates the proposed map, and sends out both kinds of notification. Signed-off-by: Daniel Stone <daniel@fooishbar.org> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'dix')
-rw-r--r--dix/devices.c74
-rw-r--r--dix/inpututils.c105
2 files changed, 116 insertions, 63 deletions
diff --git a/dix/devices.c b/dix/devices.c
index 33f149ce4..884256c8d 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1396,28 +1396,6 @@ InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons,
InitPtrFeedbackClassDeviceStruct(dev, controlProc));
}
-_X_EXPORT void
-SendPointerMappingNotify(DeviceIntPtr pDev, ClientPtr client)
-{
- int i;
- xEvent event;
-
- /* 0 is the server client. */
- for (i = 1; i < currentMaxClients; i++) {
- /* Don't send irrelevant events to naïve clients. */
- if (PickPointer(clients[i]) != pDev)
- continue;
-
- if (clients[i] && clients[i]->clientState == ClientStateRunning) {
- event.u.u.type = MappingNotify;
- event.u.u.sequenceNumber = clients[i]->sequence;
- event.u.mappingNotify.request = MappingPointer;
-
- WriteEventsToClient(clients[i], 1, &event);
- }
- }
-}
-
/*
* Check if the given buffer contains elements between low (inclusive) and
* high (inclusive) only.
@@ -1553,31 +1531,6 @@ ProcChangeKeyboardMapping(ClientPtr client)
return client->noClientException;
}
-static int
-DoSetPointerMapping(ClientPtr client, DeviceIntPtr device, BYTE *map, int n)
-{
- int rc, i = 0;
-
- if (!device || !device->button)
- return BadDevice;
-
- rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixManageAccess);
- if (rc != Success)
- return rc;
-
- for (i = 0; i < n; i++) {
- if ((device->button->map[i + 1] != map[i]) &&
- BitIsOn(device->button->down, i + 1)) {
- return MappingBusy;
- }
- }
-
- for (i = 0; i < n; i++)
- device->button->map[i + 1] = map[i];
-
- return Success;
-}
-
int
ProcSetPointerMapping(ClientPtr client)
{
@@ -1607,31 +1560,26 @@ ProcSetPointerMapping(ClientPtr client)
client->errorValue = stuff->nElts;
return BadValue;
}
- if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue))
- return BadValue;
- /* core protocol specs don't allow for duplicate mappings. */
- for (i = 0; i < stuff->nElts; i++)
- {
- for (j = i + 1; j < stuff->nElts; j++)
- {
- if (map[i] && map[i] == map[j])
- {
+ /* Core protocol specs don't allow for duplicate mappings; this check
+ * almost certainly wants disabling through XFixes too. */
+ for (i = 0; i < stuff->nElts; i++) {
+ for (j = i + 1; j < stuff->nElts; j++) {
+ if (map[i] && map[i] == map[j]) {
client->errorValue = map[i];
return BadValue;
}
}
}
- ret = DoSetPointerMapping(client, ptr, map, stuff->nElts);
- if (ret != Success) {
+ ret = ApplyPointerMapping(ptr, map, stuff->nElts, client);
+ if (ret == MappingBusy)
rep.success = ret;
- WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
- return Success;
- }
+ else if (ret == -1)
+ return BadValue;
+ else if (ret != Success)
+ return ret;
- /* FIXME: Send mapping notifies for masters/slaves as well. */
- SendPointerMappingNotify(ptr, client);
WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
return Success;
}
diff --git a/dix/inpututils.c b/dix/inpututils.c
index 309ef516d..4763382c7 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -28,6 +28,7 @@
#endif
#include "exevents.h"
+#include "exglobals.h"
#include "misc.h"
#include "input.h"
#include "inputstr.h"
@@ -35,6 +36,110 @@
#include "xkbsrv.h"
#include "xkbstr.h"
+/* Check if a button map change is okay with the device.
+ * Returns -1 for BadValue, as it collides with MappingBusy. */
+static int
+check_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, CARD32 *errval_out,
+ ClientPtr client)
+{
+ int i, ret;
+
+ if (!dev || !dev->button)
+ return BadDevice;
+
+ ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
+ if (ret != Success)
+ return ret;
+
+ for (i = 0; i < len; i++) {
+ if (dev->button->map[i + 1] != map[i] && dev->button->down[i + 1])
+ return MappingBusy;
+
+ if (map[i] < 1 || map[i] > 255) {
+ if (errval_out)
+ *errval_out = map[i];
+ return -1;
+ }
+ }
+
+ return Success;
+}
+
+static void
+do_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
+{
+ int i;
+ xEvent core_mn;
+ deviceMappingNotify xi_mn;
+
+ /* The map in ButtonClassRec refers to button numbers, whereas the
+ * protocol is zero-indexed. Sigh. */
+ memcpy(&(dev->button->map[1]), map, len);
+
+ core_mn.u.u.type = MappingNotify;
+ core_mn.u.mappingNotify.request = MappingPointer;
+
+ /* 0 is the server client. */
+ for (i = 1; i < currentMaxClients; i++) {
+ /* Don't send irrelevant events to naïve clients. */
+ if (!clients[i] || clients[i]->clientState != ClientStateRunning)
+ continue;
+
+ if (!XIShouldNotify(clients[i], dev))
+ continue;
+
+ core_mn.u.u.sequenceNumber = clients[i]->sequence;
+ WriteEventsToClient(clients[i], 1, &core_mn);
+ }
+
+ xi_mn.type = DeviceMappingNotify;
+ xi_mn.request = MappingPointer;
+ xi_mn.deviceid = dev->id;
+ xi_mn.time = GetTimeInMillis();
+
+ SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1);
+}
+
+/*
+ * Does what it says on the box, both for core and Xi.
+ *
+ * Faithfully reports any errors encountered while trying to apply the map
+ * to the requested device, faithfully ignores any errors encountered while
+ * trying to apply the map to its master/slaves.
+ */
+_X_EXPORT int
+ApplyPointerMapping(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
+{
+ int ret;
+ DeviceIntPtr tmp;
+
+ /* If we can't perform the change on the requested device, bail out. */
+ ret = check_butmap_change(dev, map, len, &client->errorValue, client);
+ if (ret != Success)
+ return ret;
+ do_butmap_change(dev, map, len, client);
+
+ /* Change any attached masters/slaves. */
+ if (dev->isMaster) {
+ for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
+ if (!tmp->isMaster && tmp->u.master == dev)
+ if (check_butmap_change(tmp, map, len, NULL, client) == Success)
+ do_butmap_change(tmp, map, len, client);
+ }
+ }
+ else {
+ for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
+ if (tmp->isMaster && tmp->u.lastSlave == dev) {
+ /* If this fails, expect the results to be weird. */
+ if (check_butmap_change(tmp, map, len, NULL, client) == Success)
+ do_butmap_change(tmp, map, len, client);
+ }
+ }
+ }
+
+ return Success;
+}
+
/* Check if a modifier map change is okay with the device.
* Returns -1 for BadValue, as it collides with MappingBusy; this particular
* caveat can be removed with LegalModifier, as we have no other reason to