summaryrefslogtreecommitdiff
path: root/xserver/dix/inpututils.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2012-06-10 13:21:33 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2012-06-10 13:21:33 +0000
commit171e929a08098b6c844887adc43879c7579dc15f (patch)
tree6b4d2e3bc20dbd4dc9a1f031416e66614c53dd21 /xserver/dix/inpututils.c
parent68781b09de2c95b87ea898c4ecf3018dfb4460d2 (diff)
Update to xserver 1.12.2. tested by naddy@, krw@, mpi@.
Diffstat (limited to 'xserver/dix/inpututils.c')
-rw-r--r--xserver/dix/inpututils.c642
1 files changed, 601 insertions, 41 deletions
diff --git a/xserver/dix/inpututils.c b/xserver/dix/inpututils.c
index 49e175822..223d547c5 100644
--- a/xserver/dix/inpututils.c
+++ b/xserver/dix/inpututils.c
@@ -37,6 +37,8 @@
#include "xkbstr.h"
#include "inpututils.h"
#include "eventstr.h"
+#include "scrnintstr.h"
+#include "optionstr.h"
/* Check if a button map change is okay with the device.
* Returns -1 for BadValue, as it collides with MappingBusy. */
@@ -46,15 +48,13 @@ check_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, CARD32 *errval_out,
{
int i, ret;
- if (!dev || !dev->button)
- {
+ if (!dev || !dev->button) {
client->errorValue = (dev) ? dev->id : 0;
return BadDevice;
}
ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
- if (ret != Success)
- {
+ if (ret != Success) {
client->errorValue = dev->id;
return ret;
}
@@ -205,9 +205,9 @@ check_modmap_change_slave(ClientPtr client, DeviceIntPtr master,
* 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])
+ j < XkbKeyNumSyms(master_xkb, i); j++)
+ if (XkbKeySymsPtr(slave_xkb, i)[j] !=
+ XkbKeySymsPtr(master_xkb, i)[j])
return 0;
}
@@ -225,8 +225,9 @@ do_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap)
}
/* Rebuild modmap (key -> mod) from map (mod -> key). */
-static int build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap,
- int max_keys_per_mod)
+static int
+build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap,
+ int max_keys_per_mod)
{
int i, len = max_keys_per_mod * 8;
@@ -274,7 +275,8 @@ change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap,
do_modmap_change(client, tmp, modmap);
}
}
- else if (!IsFloating(dev) && GetMaster(dev, MASTER_KEYBOARD)->lastSlave == dev) {
+ else if (!IsFloating(dev) &&
+ GetMaster(dev, MASTER_KEYBOARD)->lastSlave == dev) {
/* If this fails, expect the results to be weird. */
if (check_modmap_change(client, dev->master, modmap))
do_modmap_change(client, dev->master, modmap);
@@ -283,8 +285,9 @@ change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap,
return Success;
}
-int generate_modkeymap(ClientPtr client, DeviceIntPtr dev,
- KeyCode **modkeymap_out, int *max_keys_per_mod_out)
+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;
@@ -342,8 +345,8 @@ int generate_modkeymap(ClientPtr client, DeviceIntPtr dev,
* flexibility with the data. Drivers should be able to call realloc on the
* product string if needed and perform similar operations.
*/
-InputAttributes*
-DuplicateInputAttributes(InputAttributes *attrs)
+InputAttributes *
+DuplicateInputAttributes(InputAttributes * attrs)
{
InputAttributes *new_attr;
int ntags = 0;
@@ -368,20 +371,18 @@ DuplicateInputAttributes(InputAttributes *attrs)
new_attr->flags = attrs->flags;
- if ((tags = attrs->tags))
- {
- while(*tags++)
+ if ((tags = attrs->tags)) {
+ while (*tags++)
ntags++;
- new_attr->tags = calloc(ntags + 1, sizeof(char*));
+ new_attr->tags = calloc(ntags + 1, sizeof(char *));
if (!new_attr->tags)
goto unwind;
tags = attrs->tags;
new_tags = new_attr->tags;
- while(*tags)
- {
+ while (*tags) {
*new_tags = strdup(*tags);
if (!*new_tags)
goto unwind;
@@ -393,13 +394,13 @@ DuplicateInputAttributes(InputAttributes *attrs)
return new_attr;
-unwind:
+ unwind:
FreeInputAttributes(new_attr);
return NULL;
}
void
-FreeInputAttributes(InputAttributes *attrs)
+FreeInputAttributes(InputAttributes * attrs)
{
char **tags;
@@ -413,7 +414,7 @@ FreeInputAttributes(InputAttributes *attrs)
free(attrs->usb_id);
if ((tags = attrs->tags))
- while(*tags)
+ while (*tags)
free(*tags++);
free(attrs->tags);
@@ -423,13 +424,17 @@ FreeInputAttributes(InputAttributes *attrs)
/**
* Alloc a valuator mask large enough for num_valuators.
*/
-ValuatorMask*
+ValuatorMask *
valuator_mask_new(int num_valuators)
{
/* alloc a fixed size mask for now and ignore num_valuators. in the
* flying-car future, when we can dynamically alloc the masks and are
* not constrained by signals, we can start using num_valuators */
ValuatorMask *mask = calloc(1, sizeof(ValuatorMask));
+
+ if (mask == NULL)
+ return NULL;
+
mask->last_bit = -1;
return mask;
}
@@ -441,20 +446,20 @@ valuator_mask_free(ValuatorMask **mask)
*mask = NULL;
}
-
/**
* Sets a range of valuators between first_valuator and num_valuators with
* the data in the valuators array. All other values are set to 0.
*/
void
-valuator_mask_set_range(ValuatorMask *mask, int first_valuator, int num_valuators,
- const int* valuators)
+valuator_mask_set_range(ValuatorMask *mask, int first_valuator,
+ int num_valuators, const int *valuators)
{
int i;
valuator_mask_zero(mask);
- for (i = first_valuator; i < min(first_valuator + num_valuators, MAX_VALUATORS); i++)
+ for (i = first_valuator;
+ i < min(first_valuator + num_valuators, MAX_VALUATORS); i++)
valuator_mask_set(mask, i, valuators[i - first_valuator]);
}
@@ -497,10 +502,10 @@ valuator_mask_isset(const ValuatorMask *mask, int valuator)
}
/**
- * Set the valuator to the given data.
+ * Set the valuator to the given floating-point data.
*/
void
-valuator_mask_set(ValuatorMask *mask, int valuator, int data)
+valuator_mask_set_double(ValuatorMask *mask, int valuator, double data)
{
mask->last_bit = max(valuator, mask->last_bit);
SetBit(mask->mask, valuator);
@@ -508,13 +513,70 @@ valuator_mask_set(ValuatorMask *mask, int valuator, int data)
}
/**
- * Return the requested valuator value. If the mask bit is not set for the
- * given valuator, the returned value is undefined.
+ * Set the valuator to the given integer data.
+ */
+void
+valuator_mask_set(ValuatorMask *mask, int valuator, int data)
+{
+ valuator_mask_set_double(mask, valuator, data);
+}
+
+/**
+ * Return the requested valuator value as a double. If the mask bit is not
+ * set for the given valuator, the returned value is undefined.
+ */
+double
+valuator_mask_get_double(const ValuatorMask *mask, int valuator)
+{
+ return mask->valuators[valuator];
+}
+
+/**
+ * Return the requested valuator value as an integer, rounding towards zero.
+ * If the mask bit is not set for the given valuator, the returned value is
+ * undefined.
*/
int
valuator_mask_get(const ValuatorMask *mask, int valuator)
{
- return mask->valuators[valuator];
+ return trunc(valuator_mask_get_double(mask, valuator));
+}
+
+/**
+ * Set value to the requested valuator. If the mask bit is set for this
+ * valuator, value contains the requested valuator value and TRUE is
+ * returned.
+ * If the mask bit is not set for this valuator, value is unchanged and
+ * FALSE is returned.
+ */
+Bool
+valuator_mask_fetch_double(const ValuatorMask *mask, int valuator,
+ double *value)
+{
+ if (valuator_mask_isset(mask, valuator)) {
+ *value = valuator_mask_get_double(mask, valuator);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/**
+ * Set value to the requested valuator. If the mask bit is set for this
+ * valuator, value contains the requested valuator value and TRUE is
+ * returned.
+ * If the mask bit is not set for this valuator, value is unchanged and
+ * FALSE is returned.
+ */
+Bool
+valuator_mask_fetch(const ValuatorMask *mask, int valuator, int *value)
+{
+ if (valuator_mask_isset(mask, valuator)) {
+ *value = valuator_mask_get(mask, valuator);
+ return TRUE;
+ }
+ else
+ return FALSE;
}
/**
@@ -527,7 +589,7 @@ valuator_mask_unset(ValuatorMask *mask, int valuator)
int i, lastbit = -1;
ClearBit(mask->mask, valuator);
- mask->valuators[valuator] = 0;
+ mask->valuators[valuator] = 0.0;
for (i = 0; i <= mask->last_bit; i++)
if (valuator_mask_isset(mask, i))
@@ -546,7 +608,7 @@ valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src)
}
int
-CountBits(const uint8_t *mask, int len)
+CountBits(const uint8_t * mask, int len)
{
int i;
int ret = 0;
@@ -563,17 +625,16 @@ CountBits(const uint8_t *mask, int len)
* memdumps the first 32 bytes of event to the log, a backtrace, then kill
* the server.
*/
-void verify_internal_event(const InternalEvent *ev)
+void
+verify_internal_event(const InternalEvent *ev)
{
- if (ev && ev->any.header != ET_Internal)
- {
+ if (ev && ev->any.header != ET_Internal) {
int i;
- unsigned char *data = (unsigned char*)ev;
+ const unsigned char *data = (const unsigned char *) ev;
ErrorF("dix: invalid event type %d\n", ev->any.header);
- for (i = 0; i < sizeof(xEvent); i++, data++)
- {
+ for (i = 0; i < sizeof(xEvent); i++, data++) {
ErrorF("%02hhx ", *data);
if ((i % 8) == 7)
@@ -584,3 +645,502 @@ void verify_internal_event(const InternalEvent *ev)
FatalError("Wrong event type %d. Aborting server\n", ev->any.header);
}
}
+
+/**
+ * Initializes the given event to zero (or default values), for the given
+ * device.
+ */
+void
+init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms)
+{
+ memset(event, 0, sizeof(DeviceEvent));
+ event->header = ET_Internal;
+ event->length = sizeof(DeviceEvent);
+ event->time = ms;
+ event->deviceid = dev->id;
+ event->sourceid = dev->id;
+}
+
+int
+event_get_corestate(DeviceIntPtr mouse, DeviceIntPtr kbd)
+{
+ int corestate;
+
+ /* core state needs to be assembled BEFORE the device is updated. */
+ corestate = (kbd &&
+ kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->
+ state) : 0;
+ corestate |= (mouse && mouse->button) ? (mouse->button->state) : 0;
+ corestate |= (mouse && mouse->touch) ? (mouse->touch->state) : 0;
+
+ return corestate;
+}
+
+void
+event_set_state(DeviceIntPtr mouse, DeviceIntPtr kbd, DeviceEvent *event)
+{
+ int i;
+
+ for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
+ if (BitIsOn(mouse->button->down, i))
+ SetBit(event->buttons, mouse->button->map[i]);
+
+ if (mouse && mouse->touch && mouse->touch->buttonsDown > 0)
+ SetBit(event->buttons, mouse->button->map[1]);
+
+ if (kbd && kbd->key) {
+ XkbStatePtr state;
+
+ /* we need the state before the event happens */
+ if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
+ state = &kbd->key->xkbInfo->prev_state;
+ else
+ state = &kbd->key->xkbInfo->state;
+
+ event->mods.base = state->base_mods;
+ event->mods.latched = state->latched_mods;
+ event->mods.locked = state->locked_mods;
+ event->mods.effective = state->mods;
+
+ event->group.base = state->base_group;
+ event->group.latched = state->latched_group;
+ event->group.locked = state->locked_group;
+ event->group.effective = state->group;
+ }
+}
+
+/**
+ * Return the event filter mask for the given device and the given core or
+ * XI1 protocol type.
+ */
+Mask
+event_get_filter_from_type(DeviceIntPtr dev, int evtype)
+{
+ return event_filters[dev ? dev->id : 0][evtype];
+}
+
+/**
+ * Return the event filter mask for the given device and the given core or
+ * XI2 protocol type.
+ */
+Mask
+event_get_filter_from_xi2type(int evtype)
+{
+ return (1 << (evtype % 8));
+}
+
+Bool
+point_on_screen(ScreenPtr pScreen, int x, int y)
+{
+ return x >= pScreen->x && x < pScreen->x + pScreen->width &&
+ y >= pScreen->y && y < pScreen->y + pScreen->height;
+}
+
+/**
+ * Update desktop dimensions on the screenInfo struct.
+ */
+void
+update_desktop_dimensions(void)
+{
+ int i;
+ int x1 = INT_MAX, y1 = INT_MAX; /* top-left */
+ int x2 = INT_MIN, y2 = INT_MIN; /* bottom-right */
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ ScreenPtr screen = screenInfo.screens[i];
+
+ x1 = min(x1, screen->x);
+ y1 = min(y1, screen->y);
+ x2 = max(x2, screen->x + screen->width);
+ y2 = max(y2, screen->y + screen->height);
+ }
+
+ screenInfo.x = x1;
+ screenInfo.y = y1;
+ screenInfo.width = x2 - x1;
+ screenInfo.height = y2 - y1;
+}
+
+/*
+ * Delete the element with the key from the list, freeing all memory
+ * associated with the element..
+ */
+static void
+input_option_free(InputOption *o)
+{
+ free(o->opt_name);
+ free(o->opt_val);
+ free(o->opt_comment);
+ free(o);
+}
+
+/*
+ * Create a new InputOption with the key/value pair provided.
+ * If a list is provided, the new options is added to the list and the list
+ * is returned.
+ *
+ * If a new option is added to a list that already contains that option, the
+ * previous option is overwritten.
+ *
+ * @param list The list to add to.
+ * @param key Option key, will be copied.
+ * @param value Option value, will be copied.
+ *
+ * @return If list is not NULL, the list with the new option added. If list
+ * is NULL, a new option list with one element. On failure, NULL is
+ * returned.
+ */
+InputOption *
+input_option_new(InputOption *list, const char *key, const char *value)
+{
+ InputOption *opt = NULL;
+
+ if (!key)
+ return NULL;
+
+ if (list) {
+ nt_list_for_each_entry(opt, list, list.next) {
+ if (strcmp(input_option_get_key(opt), key) == 0) {
+ input_option_set_value(opt, value);
+ return list;
+ }
+ }
+ }
+
+ opt = calloc(1, sizeof(InputOption));
+ if (!opt)
+ return NULL;
+
+ nt_list_init(opt, list.next);
+ input_option_set_key(opt, key);
+ input_option_set_value(opt, value);
+
+ if (list) {
+ nt_list_append(opt, list, InputOption, list.next);
+
+ return list;
+ }
+ else
+ return opt;
+}
+
+InputOption *
+input_option_free_element(InputOption *list, const char *key)
+{
+ InputOption *element;
+
+ nt_list_for_each_entry(element, list, list.next) {
+ if (strcmp(input_option_get_key(element), key) == 0) {
+ nt_list_del(element, list, InputOption, list.next);
+
+ input_option_free(element);
+ break;
+ }
+ }
+ return list;
+}
+
+/**
+ * Free the list pointed at by opt.
+ */
+void
+input_option_free_list(InputOption **opt)
+{
+ InputOption *element, *tmp;
+
+ nt_list_for_each_entry_safe(element, tmp, *opt, list.next) {
+ nt_list_del(element, *opt, InputOption, list.next);
+
+ input_option_free(element);
+ }
+ *opt = NULL;
+}
+
+/**
+ * Find the InputOption with the given option name.
+ *
+ * @return The InputOption or NULL if not present.
+ */
+InputOption *
+input_option_find(InputOption *list, const char *key)
+{
+ InputOption *element;
+
+ nt_list_for_each_entry(element, list, list.next) {
+ if (strcmp(input_option_get_key(element), key) == 0)
+ return element;
+ }
+
+ return NULL;
+}
+
+const char *
+input_option_get_key(const InputOption *opt)
+{
+ return opt->opt_name;
+}
+
+const char *
+input_option_get_value(const InputOption *opt)
+{
+ return opt->opt_val;
+}
+
+void
+input_option_set_key(InputOption *opt, const char *key)
+{
+ free(opt->opt_name);
+ if (key)
+ opt->opt_name = strdup(key);
+}
+
+void
+input_option_set_value(InputOption *opt, const char *value)
+{
+ free(opt->opt_val);
+ if (value)
+ opt->opt_val = strdup(value);
+}
+
+/* FP1616/FP3232 conversion functions.
+ * Fixed point types are encoded as signed integral and unsigned frac. So any
+ * negative number -n.m is encoded as floor(n) + (1 - 0.m).
+ */
+double
+fp1616_to_double(FP1616 in)
+{
+ double ret;
+
+ ret = (double) (in >> 16);
+ ret += (double) (in & 0xffff) * (1.0 / (1UL << 16)); /* Optimized: ldexp((double)(in & 0xffff), -16); */
+ return ret;
+}
+
+double
+fp3232_to_double(FP3232 in)
+{
+ double ret;
+
+ ret = (double) in.integral;
+ ret += (double) in.frac * (1.0 / (1ULL << 32)); /* Optimized: ldexp((double)in.frac, -32); */
+ return ret;
+}
+
+FP1616
+double_to_fp1616(double in)
+{
+ FP1616 ret;
+ int32_t integral;
+ double tmp;
+ uint32_t frac_d;
+
+ tmp = floor(in);
+ integral = (int32_t) tmp;
+
+ tmp = (in - integral) * (1UL << 16); /* Optimized: ldexp(in - integral, 16) */
+ frac_d = (uint16_t) tmp;
+
+ ret = integral << 16;
+ ret |= frac_d & 0xffff;
+ return ret;
+}
+
+FP3232
+double_to_fp3232(double in)
+{
+ FP3232 ret;
+ int32_t integral;
+ double tmp;
+ uint32_t frac_d;
+
+ tmp = floor(in);
+ integral = (int32_t) tmp;
+
+ tmp = (in - integral) * (1ULL << 32); /* Optimized: ldexp(in - integral, 32) */
+ frac_d = (uint32_t) tmp;
+
+ ret.integral = integral;
+ ret.frac = frac_d;
+ return ret;
+}
+
+/**
+ * DO NOT USE THIS FUNCTION. It only exists for the test cases. Use
+ * xi2mask_new() instead to get the standard sized masks.
+ *
+ * @param nmasks The number of masks (== number of devices)
+ * @param size The size of the masks in bytes
+ * @return The new mask or NULL on allocation error.
+ */
+XI2Mask *
+xi2mask_new_with_size(size_t nmasks, size_t size)
+{
+ int i;
+
+ XI2Mask *mask = calloc(1, sizeof(*mask));
+
+ if (!mask)
+ return NULL;
+
+ mask->nmasks = nmasks;
+ mask->mask_size = size;
+
+ mask->masks = calloc(mask->nmasks, sizeof(*mask->masks));
+ if (!mask->masks)
+ goto unwind;
+
+ for (i = 0; i < mask->nmasks; i++) {
+ mask->masks[i] = calloc(1, mask->mask_size);
+ if (!mask->masks[i])
+ goto unwind;
+ }
+ return mask;
+
+ unwind:
+ xi2mask_free(&mask);
+ return NULL;
+}
+
+/**
+ * Create a new XI2 mask of the standard size, i.e. for all devices + fake
+ * devices and for the highest supported XI2 event type.
+ *
+ * @return The new mask or NULL on allocation error.
+ */
+XI2Mask *
+xi2mask_new(void)
+{
+ return xi2mask_new_with_size(EMASKSIZE, XI2MASKSIZE);
+}
+
+/**
+ * Frees memory associated with mask and resets mask to NULL.
+ */
+void
+xi2mask_free(XI2Mask **mask)
+{
+ int i;
+
+ if (!(*mask))
+ return;
+
+ for (i = 0; (*mask)->masks && i < (*mask)->nmasks; i++)
+ free((*mask)->masks[i]);
+ free((*mask)->masks);
+ free((*mask));
+ *mask = NULL;
+}
+
+/**
+ * Test if the bit for event type is set for this device, or the
+ * XIAllDevices/XIAllMasterDevices (if applicable) is set.
+ *
+ * @return TRUE if the bit is set, FALSE otherwise
+ */
+Bool
+xi2mask_isset(XI2Mask *mask, const DeviceIntPtr dev, int event_type)
+{
+ int set = 0;
+
+ BUG_WARN(dev->id < 0);
+ BUG_WARN(dev->id >= mask->nmasks);
+ BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size);
+
+ set = ! !BitIsOn(mask->masks[XIAllDevices], event_type);
+ if (!set)
+ set = ! !BitIsOn(mask->masks[dev->id], event_type);
+ if (!set && IsMaster(dev))
+ set = ! !BitIsOn(mask->masks[XIAllMasterDevices], event_type);
+
+ return set;
+}
+
+/**
+ * Set the mask bit for this event type for this device.
+ */
+void
+xi2mask_set(XI2Mask *mask, int deviceid, int event_type)
+{
+ BUG_WARN(deviceid < 0);
+ BUG_WARN(deviceid >= mask->nmasks);
+ BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size);
+
+ SetBit(mask->masks[deviceid], event_type);
+}
+
+/**
+ * Zero out the xi2mask, for the deviceid given. If the deviceid is < 0, all
+ * masks are zeroed.
+ */
+void
+xi2mask_zero(XI2Mask *mask, int deviceid)
+{
+ int i;
+
+ BUG_WARN(deviceid > 0 && deviceid >= mask->nmasks);
+
+ if (deviceid >= 0)
+ memset(mask->masks[deviceid], 0, mask->mask_size);
+ else
+ for (i = 0; i < mask->nmasks; i++)
+ memset(mask->masks[i], 0, mask->mask_size);
+}
+
+/**
+ * Merge source into dest, i.e. dest |= source.
+ * If the masks are of different size, only the overlapping section is merged.
+ */
+void
+xi2mask_merge(XI2Mask *dest, const XI2Mask *source)
+{
+ int i, j;
+
+ for (i = 0; i < min(dest->nmasks, source->nmasks); i++)
+ for (j = 0; j < min(dest->mask_size, source->mask_size); j++)
+ dest->masks[i][j] |= source->masks[i][j];
+}
+
+/**
+ * @return The number of masks in mask
+ */
+size_t
+xi2mask_num_masks(const XI2Mask *mask)
+{
+ return mask->nmasks;
+}
+
+/**
+ * @return The size of each mask in bytes
+ */
+size_t
+xi2mask_mask_size(const XI2Mask *mask)
+{
+ return mask->mask_size;
+}
+
+/**
+ * Set the mask for the given deviceid to the source mask.
+ * If the mask given is larger than the target memory, only the overlapping
+ * parts are copied.
+ */
+void
+xi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask,
+ size_t mask_size)
+{
+ BUG_WARN(deviceid < 0);
+ BUG_WARN(deviceid >= xi2mask->nmasks);
+
+ memcpy(xi2mask->masks[deviceid], mask, min(xi2mask->mask_size, mask_size));
+}
+
+/**
+ * Get a reference to the XI2mask for this particular device.
+ */
+const unsigned char *
+xi2mask_get_one_mask(const XI2Mask *mask, int deviceid)
+{
+ BUG_WARN(deviceid < 0);
+ BUG_WARN(deviceid >= mask->nmasks);
+
+ return mask->masks[deviceid];
+}