diff options
author | Daniel Stone <daniel@fooishbar.org> | 2008-08-12 00:35:56 +0300 |
---|---|---|
committer | Daniel Stone <daniel@fooishbar.org> | 2009-01-22 15:08:58 +1100 |
commit | bc909f71367a02297e725bb5769c2bcadab22395 (patch) | |
tree | 509819678ca888479e3142446d6e1c25cf68d3c0 /dix | |
parent | f06a9d2e05e13466c115fc706966a90b1fb0518e (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.c | 74 | ||||
-rw-r--r-- | dix/inpututils.c | 105 |
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 |