aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix/inpututils.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/dix/inpututils.c')
-rw-r--r--xorg-server/dix/inpututils.c668
1 files changed, 334 insertions, 334 deletions
diff --git a/xorg-server/dix/inpututils.c b/xorg-server/dix/inpututils.c
index 4848c1bc2..55c27e80f 100644
--- a/xorg-server/dix/inpututils.c
+++ b/xorg-server/dix/inpututils.c
@@ -1,334 +1,334 @@
-/*
- * Copyright © 2008 Daniel Stone
- *
- * 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: Daniel Stone <daniel@fooishbar.org>
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include "dix-config.h"
-#endif
-
-#include "exevents.h"
-#include "exglobals.h"
-#include "misc.h"
-#include "input.h"
-#include "inputstr.h"
-#include "xace.h"
-#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)
- {
- client->errorValue = (dev) ? dev->id : 0;
- return BadDevice;
- }
-
- ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
- if (ret != Success)
- {
- client->errorValue = dev->id;
- return ret;
- }
-
- for (i = 0; i < len; i++) {
- if (dev->button->map[i + 1] != map[i] && dev->button->down[i + 1])
- return MappingBusy;
- }
-
- 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.
- */
-int
-ApplyPointerMapping(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
-{
- int ret;
-
- /* 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);
-
- 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
- * set MappingFailed. Sigh. */
-static int
-check_modmap_change(ClientPtr client, DeviceIntPtr dev, KeyCode *modmap)
-{
- int ret, i;
- XkbDescPtr xkb;
-
- ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
- if (ret != Success)
- return ret;
-
- if (!dev->key)
- return BadMatch;
- xkb = dev->key->xkbInfo->desc;
-
- for (i = 0; i < MAP_LENGTH; i++) {
- if (!modmap[i])
- continue;
-
- /* Check that all the new modifiers fall within the advertised
- * keycode range. */
- if (i < xkb->min_key_code || i > xkb->max_key_code) {
- client->errorValue = i;
- return -1;
- }
-
- /* Make sure the mapping is okay with the DDX. */
- if (!LegalModifier(i, dev)) {
- client->errorValue = i;
- return MappingFailed;
- }
-
- /* None of the new modifiers may be down while we change the
- * map. */
- if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
- client->errorValue = i;
- return MappingBusy;
- }
- }
-
- /* None of the old modifiers may be down while we change the map,
- * either. */
- for (i = xkb->min_key_code; i < xkb->max_key_code; i++) {
- if (!xkb->map->modmap[i])
- continue;
- if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
- client->errorValue = i;
- return MappingBusy;
- }
- }
-
- return Success;
-}
-
-static int
-check_modmap_change_slave(ClientPtr client, DeviceIntPtr master,
- DeviceIntPtr slave, CARD8 *modmap)
-{
- XkbDescPtr master_xkb, slave_xkb;
- int i, j;
-
- if (!slave->key || !master->key)
- return 0;
-
- master_xkb = master->key->xkbInfo->desc;
- slave_xkb = slave->key->xkbInfo->desc;
-
- /* Ignore devices with a clearly different keymap. */
- if (slave_xkb->min_key_code != master_xkb->min_key_code ||
- slave_xkb->max_key_code != master_xkb->max_key_code)
- return 0;
-
- for (i = 0; i < MAP_LENGTH; i++) {
- if (!modmap[i])
- continue;
-
- /* If we have different symbols for any modifier on an
- * extended keyboard, ignore the whole remap request. */
- for (j = 0;
- j < XkbKeyNumSyms(slave_xkb, i) &&
- j < XkbKeyNumSyms(master_xkb, i);
- j++)
- if (XkbKeySymsPtr(slave_xkb, i)[j] != XkbKeySymsPtr(master_xkb, i)[j])
- return 0;
- }
-
- if (check_modmap_change(client, slave, modmap) != Success)
- return 0;
-
- return 1;
-}
-
-/* Actually change the modifier map, and send notifications. Cannot fail. */
-static void
-do_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap)
-{
- XkbApplyMappingChange(dev, NULL, 0, 0, modmap, serverClient);
-}
-
-/* Rebuild modmap (key -> mod) from map (mod -> key). */
-static int build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap,
- int max_keys_per_mod)
-{
- int i, len = max_keys_per_mod * 8;
-
- memset(modmap, 0, MAP_LENGTH);
-
- for (i = 0; i < len; i++) {
- if (!modkeymap[i])
- continue;
-
- if (modkeymap[i] >= MAP_LENGTH)
- return BadValue;
-
- if (modmap[modkeymap[i]])
- return BadValue;
-
- modmap[modkeymap[i]] = 1 << (i / max_keys_per_mod);
- }
-
- return Success;
-}
-
-int
-change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap,
- int max_keys_per_mod)
-{
- int ret;
- CARD8 modmap[MAP_LENGTH];
- DeviceIntPtr tmp;
-
- ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod);
- if (ret != Success)
- return ret;
-
- /* If we can't perform the change on the requested device, bail out. */
- ret = check_modmap_change(client, dev, modmap);
- if (ret != Success)
- return ret;
- do_modmap_change(client, dev, modmap);
-
- /* Change any attached masters/slaves. */
- if (IsMaster(dev)) {
- for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
- if (!IsMaster(tmp) && tmp->u.master == dev)
- if (check_modmap_change_slave(client, dev, tmp, modmap))
- do_modmap_change(client, tmp, modmap);
- }
- }
- else if (dev->u.master && dev->u.master->u.lastSlave == dev) {
- /* If this fails, expect the results to be weird. */
- if (check_modmap_change(client, dev->u.master, modmap))
- do_modmap_change(client, dev->u.master, modmap);
- }
-
- return Success;
-}
-
-int generate_modkeymap(ClientPtr client, DeviceIntPtr dev,
- KeyCode **modkeymap_out, int *max_keys_per_mod_out)
-{
- CARD8 keys_per_mod[8];
- int max_keys_per_mod;
- KeyCode *modkeymap;
- int i, j, ret;
-
- ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
- if (ret != Success)
- return ret;
-
- if (!dev->key)
- return BadMatch;
-
- /* Count the number of keys per modifier to determine how wide we
- * should make the map. */
- max_keys_per_mod = 0;
- for (i = 0; i < 8; i++)
- keys_per_mod[i] = 0;
- for (i = 8; i < MAP_LENGTH; i++) {
- for (j = 0; j < 8; j++) {
- if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
- if (++keys_per_mod[j] > max_keys_per_mod)
- max_keys_per_mod = keys_per_mod[j];
- }
- }
- }
-
- modkeymap = xcalloc(max_keys_per_mod * 8, sizeof(KeyCode));
- if (!modkeymap)
- return BadAlloc;
-
- for (i = 0; i < 8; i++)
- keys_per_mod[i] = 0;
-
- for (i = 8; i < MAP_LENGTH; i++) {
- for (j = 0; j < 8; j++) {
- if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
- modkeymap[(j * max_keys_per_mod) + keys_per_mod[j]] = i;
- keys_per_mod[j]++;
- }
- }
- }
-
- *max_keys_per_mod_out = max_keys_per_mod;
- *modkeymap_out = modkeymap;
-
- return Success;
-}
+/*
+ * Copyright © 2008 Daniel Stone
+ *
+ * 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: Daniel Stone <daniel@fooishbar.org>
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include "dix-config.h"
+#endif
+
+#include "exevents.h"
+#include "exglobals.h"
+#include "misc.h"
+#include "input.h"
+#include "inputstr.h"
+#include "xace.h"
+#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)
+ {
+ client->errorValue = (dev) ? dev->id : 0;
+ return BadDevice;
+ }
+
+ ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
+ if (ret != Success)
+ {
+ client->errorValue = dev->id;
+ return ret;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (dev->button->map[i + 1] != map[i] && dev->button->down[i + 1])
+ return MappingBusy;
+ }
+
+ 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.
+ */
+int
+ApplyPointerMapping(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
+{
+ int ret;
+
+ /* 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);
+
+ 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
+ * set MappingFailed. Sigh. */
+static int
+check_modmap_change(ClientPtr client, DeviceIntPtr dev, KeyCode *modmap)
+{
+ int ret, i;
+ XkbDescPtr xkb;
+
+ ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
+ if (ret != Success)
+ return ret;
+
+ if (!dev->key)
+ return BadMatch;
+ xkb = dev->key->xkbInfo->desc;
+
+ for (i = 0; i < MAP_LENGTH; i++) {
+ if (!modmap[i])
+ continue;
+
+ /* Check that all the new modifiers fall within the advertised
+ * keycode range. */
+ if (i < xkb->min_key_code || i > xkb->max_key_code) {
+ client->errorValue = i;
+ return -1;
+ }
+
+ /* Make sure the mapping is okay with the DDX. */
+ if (!LegalModifier(i, dev)) {
+ client->errorValue = i;
+ return MappingFailed;
+ }
+
+ /* None of the new modifiers may be down while we change the
+ * map. */
+ if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
+ client->errorValue = i;
+ return MappingBusy;
+ }
+ }
+
+ /* None of the old modifiers may be down while we change the map,
+ * either. */
+ for (i = xkb->min_key_code; i < xkb->max_key_code; i++) {
+ if (!xkb->map->modmap[i])
+ continue;
+ if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
+ client->errorValue = i;
+ return MappingBusy;
+ }
+ }
+
+ return Success;
+}
+
+static int
+check_modmap_change_slave(ClientPtr client, DeviceIntPtr master,
+ DeviceIntPtr slave, CARD8 *modmap)
+{
+ XkbDescPtr master_xkb, slave_xkb;
+ int i, j;
+
+ if (!slave->key || !master->key)
+ return 0;
+
+ master_xkb = master->key->xkbInfo->desc;
+ slave_xkb = slave->key->xkbInfo->desc;
+
+ /* Ignore devices with a clearly different keymap. */
+ if (slave_xkb->min_key_code != master_xkb->min_key_code ||
+ slave_xkb->max_key_code != master_xkb->max_key_code)
+ return 0;
+
+ for (i = 0; i < MAP_LENGTH; i++) {
+ if (!modmap[i])
+ continue;
+
+ /* If we have different symbols for any modifier on an
+ * extended keyboard, ignore the whole remap request. */
+ for (j = 0;
+ j < XkbKeyNumSyms(slave_xkb, i) &&
+ j < XkbKeyNumSyms(master_xkb, i);
+ j++)
+ if (XkbKeySymsPtr(slave_xkb, i)[j] != XkbKeySymsPtr(master_xkb, i)[j])
+ return 0;
+ }
+
+ if (check_modmap_change(client, slave, modmap) != Success)
+ return 0;
+
+ return 1;
+}
+
+/* Actually change the modifier map, and send notifications. Cannot fail. */
+static void
+do_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap)
+{
+ XkbApplyMappingChange(dev, NULL, 0, 0, modmap, serverClient);
+}
+
+/* Rebuild modmap (key -> mod) from map (mod -> key). */
+static int build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap,
+ int max_keys_per_mod)
+{
+ int i, len = max_keys_per_mod * 8;
+
+ memset(modmap, 0, MAP_LENGTH);
+
+ for (i = 0; i < len; i++) {
+ if (!modkeymap[i])
+ continue;
+
+ if (modkeymap[i] >= MAP_LENGTH)
+ return BadValue;
+
+ if (modmap[modkeymap[i]])
+ return BadValue;
+
+ modmap[modkeymap[i]] = 1 << (i / max_keys_per_mod);
+ }
+
+ return Success;
+}
+
+int
+change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap,
+ int max_keys_per_mod)
+{
+ int ret;
+ CARD8 modmap[MAP_LENGTH];
+ DeviceIntPtr tmp;
+
+ ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod);
+ if (ret != Success)
+ return ret;
+
+ /* If we can't perform the change on the requested device, bail out. */
+ ret = check_modmap_change(client, dev, modmap);
+ if (ret != Success)
+ return ret;
+ do_modmap_change(client, dev, modmap);
+
+ /* Change any attached masters/slaves. */
+ if (IsMaster(dev)) {
+ for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
+ if (!IsMaster(tmp) && tmp->u.master == dev)
+ if (check_modmap_change_slave(client, dev, tmp, modmap))
+ do_modmap_change(client, tmp, modmap);
+ }
+ }
+ else if (dev->u.master && dev->u.master->u.lastSlave == dev) {
+ /* If this fails, expect the results to be weird. */
+ if (check_modmap_change(client, dev->u.master, modmap))
+ do_modmap_change(client, dev->u.master, modmap);
+ }
+
+ return Success;
+}
+
+int generate_modkeymap(ClientPtr client, DeviceIntPtr dev,
+ KeyCode **modkeymap_out, int *max_keys_per_mod_out)
+{
+ CARD8 keys_per_mod[8];
+ int max_keys_per_mod;
+ KeyCode *modkeymap;
+ int i, j, ret;
+
+ ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
+ if (ret != Success)
+ return ret;
+
+ if (!dev->key)
+ return BadMatch;
+
+ /* Count the number of keys per modifier to determine how wide we
+ * should make the map. */
+ max_keys_per_mod = 0;
+ for (i = 0; i < 8; i++)
+ keys_per_mod[i] = 0;
+ for (i = 8; i < MAP_LENGTH; i++) {
+ for (j = 0; j < 8; j++) {
+ if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
+ if (++keys_per_mod[j] > max_keys_per_mod)
+ max_keys_per_mod = keys_per_mod[j];
+ }
+ }
+ }
+
+ modkeymap = calloc(max_keys_per_mod * 8, sizeof(KeyCode));
+ if (!modkeymap)
+ return BadAlloc;
+
+ for (i = 0; i < 8; i++)
+ keys_per_mod[i] = 0;
+
+ for (i = 8; i < MAP_LENGTH; i++) {
+ for (j = 0; j < 8; j++) {
+ if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
+ modkeymap[(j * max_keys_per_mod) + keys_per_mod[j]] = i;
+ keys_per_mod[j]++;
+ }
+ }
+ }
+
+ *max_keys_per_mod_out = max_keys_per_mod;
+ *modkeymap_out = modkeymap;
+
+ return Success;
+}