From bc909f71367a02297e725bb5769c2bcadab22395 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 12 Aug 2008 00:35:56 +0300 Subject: [PATCH] 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 Signed-off-by: Peter Hutterer --- Xi/exevents.c | 14 ------ Xi/setbmap.c | 22 ++++------ dix/devices.c | 74 +++++--------------------------- dix/inpututils.c | 105 +++++++++++++++++++++++++++++++++++++++++++++ include/exevents.h | 4 -- include/input.h | 4 +- 6 files changed, 127 insertions(+), 96 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 623f71036..76214b973 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1639,20 +1639,6 @@ SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map) return Success; } -void -SendDevicePointerMappingNotify(ClientPtr client, DeviceIntPtr dev) -{ - xEvent event; - deviceMappingNotify *ev = (deviceMappingNotify *) & event; - - ev->type = DeviceMappingNotify; - ev->request = MappingPointer; - ev->deviceid = dev->id; - ev->time = currentTime.milliseconds; - - SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) ev, 1); -} - int ChangeKeyMapping(ClientPtr client, DeviceIntPtr dev, diff --git a/Xi/setbmap.c b/Xi/setbmap.c index 0bcfbb8eb..b6f62dddb 100644 --- a/Xi/setbmap.c +++ b/Xi/setbmap.c @@ -107,21 +107,15 @@ ProcXSetDeviceButtonMapping(ClientPtr client) rep.sequenceNumber = client->sequence; rep.status = MappingSuccess; - ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess); - if (ret != Success) - return ret; + ret = ApplyPointerMapping(dev, (CARD8 *) &stuff[1], stuff->map_length, client); + if (ret == -1) + return BadValue; + else if (ret == MappingBusy) + rep.status = ret; + else if (ret != Success) + return ret; - ret = SetButtonMapping(client, dev, stuff->map_length, (BYTE *) & stuff[1]); - - if (ret == BadValue || ret == BadMatch) - return ret; - else { - rep.status = ret; - WriteReplyToClient(client, sizeof(xSetDeviceButtonMappingReply), &rep); - } - - if (ret != MappingBusy) - SendDevicePointerMappingNotify(client, dev); + WriteReplyToClient(client, sizeof(xSetDeviceButtonMappingReply), &rep); return Success; } 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 diff --git a/include/exevents.h b/include/exevents.h index 46df009a4..ff2922736 100644 --- a/include/exevents.h +++ b/include/exevents.h @@ -137,10 +137,6 @@ extern _X_EXPORT int SetButtonMapping ( int /* nElts */, BYTE * /* map */); -extern _X_EXPORT void SendDevicePointerMappingNotify( - ClientPtr /* client, */, - DeviceIntPtr /* dev */); - extern _X_EXPORT int ChangeKeyMapping( ClientPtr /* client */, DeviceIntPtr /* dev */, diff --git a/include/input.h b/include/input.h index 8a774c963..19d1ae74c 100644 --- a/include/input.h +++ b/include/input.h @@ -368,8 +368,10 @@ extern _X_EXPORT Bool InitKeyboardDeviceStruct( BellProcPtr /*bellProc*/, KbdCtrlProcPtr /*controlProc*/); -extern _X_EXPORT void SendPointerMappingNotify( +extern _X_EXPORT int ApplyPointerMapping( DeviceIntPtr /* pDev */, + CARD8 * /* map */, + int /* len */, ClientPtr /* client */); extern _X_EXPORT Bool BadDeviceMap(