2
* Copyright Ā© 2008 Daniel Stone
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
* DEALINGS IN THE SOFTWARE.
23
* Author: Daniel Stone <daniel@fooishbar.org>
26
#ifdef HAVE_DIX_CONFIG_H
27
#include "dix-config.h"
31
#include "exglobals.h"
38
#include "inpututils.h"
40
#include "scrnintstr.h"
41
#include "optionstr.h"
43
/* Check if a button map change is okay with the device.
44
* Returns -1 for BadValue, as it collides with MappingBusy. */
46
check_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, CARD32 *errval_out,
51
if (!dev || !dev->button) {
52
client->errorValue = (dev) ? dev->id : 0;
56
ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
58
client->errorValue = dev->id;
62
for (i = 0; i < len; i++) {
63
if (dev->button->map[i + 1] != map[i] &&
64
button_is_down(dev, i + 1, BUTTON_PROCESSED))
72
do_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
75
xEvent core_mn = { .u.u.type = MappingNotify };
76
deviceMappingNotify xi_mn;
78
/* The map in ButtonClassRec refers to button numbers, whereas the
79
* protocol is zero-indexed. Sigh. */
80
memcpy(&(dev->button->map[1]), map, len);
82
core_mn.u.mappingNotify.request = MappingPointer;
84
/* 0 is the server client. */
85
for (i = 1; i < currentMaxClients; i++) {
86
/* Don't send irrelevant events to naĆÆve clients. */
87
if (!clients[i] || clients[i]->clientState != ClientStateRunning)
90
if (!XIShouldNotify(clients[i], dev))
93
WriteEventsToClient(clients[i], 1, &core_mn);
96
xi_mn = (deviceMappingNotify) {
97
.type = DeviceMappingNotify,
98
.request = MappingPointer,
100
.time = GetTimeInMillis()
103
SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1);
107
* Does what it says on the box, both for core and Xi.
109
* Faithfully reports any errors encountered while trying to apply the map
110
* to the requested device, faithfully ignores any errors encountered while
111
* trying to apply the map to its master/slaves.
114
ApplyPointerMapping(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
118
/* If we can't perform the change on the requested device, bail out. */
119
ret = check_butmap_change(dev, map, len, &client->errorValue, client);
122
do_butmap_change(dev, map, len, client);
127
/* Check if a modifier map change is okay with the device.
128
* Returns -1 for BadValue, as it collides with MappingBusy; this particular
129
* caveat can be removed with LegalModifier, as we have no other reason to
130
* set MappingFailed. Sigh. */
132
check_modmap_change(ClientPtr client, DeviceIntPtr dev, KeyCode *modmap)
137
ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
143
xkb = dev->key->xkbInfo->desc;
145
for (i = 0; i < MAP_LENGTH; i++) {
149
/* Check that all the new modifiers fall within the advertised
151
if (i < xkb->min_key_code || i > xkb->max_key_code) {
152
client->errorValue = i;
156
/* Make sure the mapping is okay with the DDX. */
157
if (!LegalModifier(i, dev)) {
158
client->errorValue = i;
159
return MappingFailed;
162
/* None of the new modifiers may be down while we change the
164
if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
165
client->errorValue = i;
170
/* None of the old modifiers may be down while we change the map,
172
for (i = xkb->min_key_code; i < xkb->max_key_code; i++) {
173
if (!xkb->map->modmap[i])
175
if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
176
client->errorValue = i;
185
check_modmap_change_slave(ClientPtr client, DeviceIntPtr master,
186
DeviceIntPtr slave, CARD8 *modmap)
188
XkbDescPtr master_xkb, slave_xkb;
191
if (!slave->key || !master->key)
194
master_xkb = master->key->xkbInfo->desc;
195
slave_xkb = slave->key->xkbInfo->desc;
197
/* Ignore devices with a clearly different keymap. */
198
if (slave_xkb->min_key_code != master_xkb->min_key_code ||
199
slave_xkb->max_key_code != master_xkb->max_key_code)
202
for (i = 0; i < MAP_LENGTH; i++) {
206
/* If we have different symbols for any modifier on an
207
* extended keyboard, ignore the whole remap request. */
209
j < XkbKeyNumSyms(slave_xkb, i) &&
210
j < XkbKeyNumSyms(master_xkb, i); j++)
211
if (XkbKeySymsPtr(slave_xkb, i)[j] !=
212
XkbKeySymsPtr(master_xkb, i)[j])
216
if (check_modmap_change(client, slave, modmap) != Success)
222
/* Actually change the modifier map, and send notifications. Cannot fail. */
224
do_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap)
226
XkbApplyMappingChange(dev, NULL, 0, 0, modmap, serverClient);
229
/* Rebuild modmap (key -> mod) from map (mod -> key). */
231
build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap,
232
int max_keys_per_mod)
234
int i, len = max_keys_per_mod * 8;
236
memset(modmap, 0, MAP_LENGTH);
238
for (i = 0; i < len; i++) {
242
if (modkeymap[i] >= MAP_LENGTH)
245
if (modmap[modkeymap[i]])
248
modmap[modkeymap[i]] = 1 << (i / max_keys_per_mod);
255
change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap,
256
int max_keys_per_mod)
259
CARD8 modmap[MAP_LENGTH];
262
ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod);
266
/* If we can't perform the change on the requested device, bail out. */
267
ret = check_modmap_change(client, dev, modmap);
270
do_modmap_change(client, dev, modmap);
272
/* Change any attached masters/slaves. */
274
for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
275
if (!IsMaster(tmp) && GetMaster(tmp, MASTER_KEYBOARD) == dev)
276
if (check_modmap_change_slave(client, dev, tmp, modmap))
277
do_modmap_change(client, tmp, modmap);
280
else if (!IsFloating(dev) &&
281
GetMaster(dev, MASTER_KEYBOARD)->lastSlave == dev) {
282
/* If this fails, expect the results to be weird. */
283
if (check_modmap_change(client, dev->master, modmap))
284
do_modmap_change(client, dev->master, modmap);
291
generate_modkeymap(ClientPtr client, DeviceIntPtr dev,
292
KeyCode **modkeymap_out, int *max_keys_per_mod_out)
294
CARD8 keys_per_mod[8];
295
int max_keys_per_mod;
296
KeyCode *modkeymap = NULL;
299
ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
306
/* Count the number of keys per modifier to determine how wide we
307
* should make the map. */
308
max_keys_per_mod = 0;
309
for (i = 0; i < 8; i++)
311
for (i = 8; i < MAP_LENGTH; i++) {
312
for (j = 0; j < 8; j++) {
313
if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
314
if (++keys_per_mod[j] > max_keys_per_mod)
315
max_keys_per_mod = keys_per_mod[j];
320
if (max_keys_per_mod != 0) {
321
modkeymap = calloc(max_keys_per_mod * 8, sizeof(KeyCode));
325
for (i = 0; i < 8; i++)
328
for (i = 8; i < MAP_LENGTH; i++) {
329
for (j = 0; j < 8; j++) {
330
if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
331
modkeymap[(j * max_keys_per_mod) + keys_per_mod[j]] = i;
338
*max_keys_per_mod_out = max_keys_per_mod;
339
*modkeymap_out = modkeymap;
345
* Duplicate the InputAttributes in the most obvious way.
346
* No special memory handling is used to give drivers the maximum
347
* flexibility with the data. Drivers should be able to call realloc on the
348
* product string if needed and perform similar operations.
351
DuplicateInputAttributes(InputAttributes * attrs)
353
InputAttributes *new_attr;
355
char **tags, **new_tags;
360
if (!(new_attr = calloc(1, sizeof(InputAttributes))))
363
if (attrs->product && !(new_attr->product = strdup(attrs->product)))
365
if (attrs->vendor && !(new_attr->vendor = strdup(attrs->vendor)))
367
if (attrs->device && !(new_attr->device = strdup(attrs->device)))
369
if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id)))
371
if (attrs->usb_id && !(new_attr->usb_id = strdup(attrs->usb_id)))
374
new_attr->flags = attrs->flags;
376
if ((tags = attrs->tags)) {
380
new_attr->tags = calloc(ntags + 1, sizeof(char *));
385
new_tags = new_attr->tags;
388
*new_tags = strdup(*tags);
400
FreeInputAttributes(new_attr);
405
FreeInputAttributes(InputAttributes * attrs)
412
free(attrs->product);
418
if ((tags = attrs->tags))
427
* Alloc a valuator mask large enough for num_valuators.
430
valuator_mask_new(int num_valuators)
432
/* alloc a fixed size mask for now and ignore num_valuators. in the
433
* flying-car future, when we can dynamically alloc the masks and are
434
* not constrained by signals, we can start using num_valuators */
435
ValuatorMask *mask = calloc(1, sizeof(ValuatorMask));
445
valuator_mask_free(ValuatorMask **mask)
452
* Sets a range of valuators between first_valuator and num_valuators with
453
* the data in the valuators array. All other values are set to 0.
456
valuator_mask_set_range(ValuatorMask *mask, int first_valuator,
457
int num_valuators, const int *valuators)
461
valuator_mask_zero(mask);
463
for (i = first_valuator;
464
i < min(first_valuator + num_valuators, MAX_VALUATORS); i++)
465
valuator_mask_set(mask, i, valuators[i - first_valuator]);
469
* Reset mask to zero.
472
valuator_mask_zero(ValuatorMask *mask)
474
memset(mask, 0, sizeof(*mask));
479
* Returns the current size of the mask (i.e. the highest number of
480
* valuators currently set + 1).
483
valuator_mask_size(const ValuatorMask *mask)
485
return mask->last_bit + 1;
489
* Returns the number of valuators set in the given mask.
492
valuator_mask_num_valuators(const ValuatorMask *mask)
494
return CountBits(mask->mask, min(mask->last_bit + 1, MAX_VALUATORS));
498
* Return true if the valuator is set in the mask, or false otherwise.
501
valuator_mask_isset(const ValuatorMask *mask, int valuator)
503
return mask->last_bit >= valuator && BitIsOn(mask->mask, valuator);
507
* Set the valuator to the given floating-point data.
510
valuator_mask_set_double(ValuatorMask *mask, int valuator, double data)
512
mask->last_bit = max(valuator, mask->last_bit);
513
SetBit(mask->mask, valuator);
514
mask->valuators[valuator] = data;
518
* Set the valuator to the given integer data.
521
valuator_mask_set(ValuatorMask *mask, int valuator, int data)
523
valuator_mask_set_double(mask, valuator, data);
527
* Return the requested valuator value as a double. If the mask bit is not
528
* set for the given valuator, the returned value is undefined.
531
valuator_mask_get_double(const ValuatorMask *mask, int valuator)
533
return mask->valuators[valuator];
537
* Return the requested valuator value as an integer, rounding towards zero.
538
* If the mask bit is not set for the given valuator, the returned value is
542
valuator_mask_get(const ValuatorMask *mask, int valuator)
544
return trunc(valuator_mask_get_double(mask, valuator));
548
* Set value to the requested valuator. If the mask bit is set for this
549
* valuator, value contains the requested valuator value and TRUE is
551
* If the mask bit is not set for this valuator, value is unchanged and
555
valuator_mask_fetch_double(const ValuatorMask *mask, int valuator,
558
if (valuator_mask_isset(mask, valuator)) {
559
*value = valuator_mask_get_double(mask, valuator);
567
* Set value to the requested valuator. If the mask bit is set for this
568
* valuator, value contains the requested valuator value and TRUE is
570
* If the mask bit is not set for this valuator, value is unchanged and
574
valuator_mask_fetch(const ValuatorMask *mask, int valuator, int *value)
576
if (valuator_mask_isset(mask, valuator)) {
577
*value = valuator_mask_get(mask, valuator);
585
* Remove the valuator from the mask.
588
valuator_mask_unset(ValuatorMask *mask, int valuator)
590
if (mask->last_bit >= valuator) {
593
ClearBit(mask->mask, valuator);
594
mask->valuators[valuator] = 0.0;
596
for (i = 0; i <= mask->last_bit; i++)
597
if (valuator_mask_isset(mask, i))
598
lastbit = max(lastbit, i);
599
mask->last_bit = lastbit;
604
valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src)
607
memcpy(dest, src, sizeof(*dest));
609
valuator_mask_zero(dest);
613
CountBits(const uint8_t * mask, int len)
618
for (i = 0; i < len; i++)
619
if (BitIsOn(mask, i))
626
* Verifies sanity of the event. If the event is not an internal event,
627
* memdumps the first 32 bytes of event to the log, a backtrace, then kill
631
verify_internal_event(const InternalEvent *ev)
633
if (ev && ev->any.header != ET_Internal) {
635
const unsigned char *data = (const unsigned char *) ev;
637
ErrorF("dix: invalid event type %d\n", ev->any.header);
639
for (i = 0; i < sizeof(xEvent); i++, data++) {
640
ErrorF("%02hhx ", *data);
647
FatalError("Wrong event type %d. Aborting server\n", ev->any.header);
652
* Initializes the given event to zero (or default values), for the given
656
init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms)
658
memset(event, 0, sizeof(DeviceEvent));
659
event->header = ET_Internal;
660
event->length = sizeof(DeviceEvent);
662
event->deviceid = dev->id;
663
event->sourceid = dev->id;
667
event_get_corestate(DeviceIntPtr mouse, DeviceIntPtr kbd)
671
/* core state needs to be assembled BEFORE the device is updated. */
673
kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->
675
corestate |= (mouse && mouse->button) ? (mouse->button->state) : 0;
676
corestate |= (mouse && mouse->touch) ? (mouse->touch->state) : 0;
682
event_set_state(DeviceIntPtr mouse, DeviceIntPtr kbd, DeviceEvent *event)
686
for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
687
if (BitIsOn(mouse->button->down, i))
688
SetBit(event->buttons, mouse->button->map[i]);
690
if (mouse && mouse->touch && mouse->touch->buttonsDown > 0)
691
SetBit(event->buttons, mouse->button->map[1]);
693
if (kbd && kbd->key) {
696
/* we need the state before the event happens */
697
if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
698
state = &kbd->key->xkbInfo->prev_state;
700
state = &kbd->key->xkbInfo->state;
702
event->mods.base = state->base_mods;
703
event->mods.latched = state->latched_mods;
704
event->mods.locked = state->locked_mods;
705
event->mods.effective = state->mods;
707
event->group.base = state->base_group;
708
event->group.latched = state->latched_group;
709
event->group.locked = state->locked_group;
710
event->group.effective = state->group;
715
* Return the event filter mask for the given device and the given core or
719
event_get_filter_from_type(DeviceIntPtr dev, int evtype)
721
return event_filters[dev ? dev->id : 0][evtype];
725
* Return the event filter mask for the given device and the given core or
729
event_get_filter_from_xi2type(int evtype)
731
return (1 << (evtype % 8));
735
point_on_screen(ScreenPtr pScreen, int x, int y)
737
return x >= pScreen->x && x < pScreen->x + pScreen->width &&
738
y >= pScreen->y && y < pScreen->y + pScreen->height;
742
* Update desktop dimensions on the screenInfo struct.
745
update_desktop_dimensions(void)
748
int x1 = INT_MAX, y1 = INT_MAX; /* top-left */
749
int x2 = INT_MIN, y2 = INT_MIN; /* bottom-right */
751
for (i = 0; i < screenInfo.numScreens; i++) {
752
ScreenPtr screen = screenInfo.screens[i];
754
x1 = min(x1, screen->x);
755
y1 = min(y1, screen->y);
756
x2 = max(x2, screen->x + screen->width);
757
y2 = max(y2, screen->y + screen->height);
762
screenInfo.width = x2 - x1;
763
screenInfo.height = y2 - y1;
767
* Delete the element with the key from the list, freeing all memory
768
* associated with the element..
771
input_option_free(InputOption *o)
775
free(o->opt_comment);
780
* Create a new InputOption with the key/value pair provided.
781
* If a list is provided, the new options is added to the list and the list
784
* If a new option is added to a list that already contains that option, the
785
* previous option is overwritten.
787
* @param list The list to add to.
788
* @param key Option key, will be copied.
789
* @param value Option value, will be copied.
791
* @return If list is not NULL, the list with the new option added. If list
792
* is NULL, a new option list with one element. On failure, NULL is
796
input_option_new(InputOption *list, const char *key, const char *value)
798
InputOption *opt = NULL;
804
nt_list_for_each_entry(opt, list, list.next) {
805
if (strcmp(input_option_get_key(opt), key) == 0) {
806
input_option_set_value(opt, value);
812
opt = calloc(1, sizeof(InputOption));
816
nt_list_init(opt, list.next);
817
input_option_set_key(opt, key);
818
input_option_set_value(opt, value);
821
nt_list_append(opt, list, InputOption, list.next);
830
input_option_free_element(InputOption *list, const char *key)
832
InputOption *element;
834
nt_list_for_each_entry(element, list, list.next) {
835
if (strcmp(input_option_get_key(element), key) == 0) {
836
nt_list_del(element, list, InputOption, list.next);
838
input_option_free(element);
846
* Free the list pointed at by opt.
849
input_option_free_list(InputOption **opt)
851
InputOption *element, *tmp;
853
nt_list_for_each_entry_safe(element, tmp, *opt, list.next) {
854
nt_list_del(element, *opt, InputOption, list.next);
856
input_option_free(element);
862
* Find the InputOption with the given option name.
864
* @return The InputOption or NULL if not present.
867
input_option_find(InputOption *list, const char *key)
869
InputOption *element;
871
nt_list_for_each_entry(element, list, list.next) {
872
if (strcmp(input_option_get_key(element), key) == 0)
880
input_option_get_key(const InputOption *opt)
882
return opt->opt_name;
886
input_option_get_value(const InputOption *opt)
892
input_option_set_key(InputOption *opt, const char *key)
896
opt->opt_name = strdup(key);
900
input_option_set_value(InputOption *opt, const char *value)
904
opt->opt_val = strdup(value);
907
/* FP1616/FP3232 conversion functions.
908
* Fixed point types are encoded as signed integral and unsigned frac. So any
909
* negative number -n.m is encoded as floor(n) + (1 - 0.m).
912
fp1616_to_double(FP1616 in)
914
return pixman_fixed_to_double(in);
918
fp3232_to_double(FP3232 in)
922
ret = (double) in.integral;
923
ret += (double) in.frac * (1.0 / (1ULL << 32)); /* Optimized: ldexp((double)in.frac, -32); */
928
double_to_fp1616(double in)
930
return pixman_double_to_fixed(in);
934
double_to_fp3232(double in)
942
integral = (int32_t) tmp;
944
tmp = (in - integral) * (1ULL << 32); /* Optimized: ldexp(in - integral, 32) */
945
frac_d = (uint32_t) tmp;
947
ret.integral = integral;
953
* DO NOT USE THIS FUNCTION. It only exists for the test cases. Use
954
* xi2mask_new() instead to get the standard sized masks.
956
* @param nmasks The number of masks (== number of devices)
957
* @param size The size of the masks in bytes
958
* @return The new mask or NULL on allocation error.
961
xi2mask_new_with_size(size_t nmasks, size_t size)
965
unsigned char *cursor;
968
alloc_size = sizeof(struct _XI2Mask)
969
+ nmasks * sizeof(unsigned char *)
972
mask = calloc(1, alloc_size);
977
mask->nmasks = nmasks;
978
mask->mask_size = size;
980
mask->masks = (unsigned char **)(mask + 1);
981
cursor = (unsigned char *)(mask + 1) + nmasks * sizeof(unsigned char *);
983
for (i = 0; i < nmasks; i++) {
984
mask->masks[i] = cursor;
991
* Create a new XI2 mask of the standard size, i.e. for all devices + fake
992
* devices and for the highest supported XI2 event type.
994
* @return The new mask or NULL on allocation error.
999
return xi2mask_new_with_size(EMASKSIZE, XI2MASKSIZE);
1003
* Frees memory associated with mask and resets mask to NULL.
1006
xi2mask_free(XI2Mask **mask)
1016
* Test if the bit for event type is set for this device only.
1018
* @return TRUE if the bit is set, FALSE otherwise
1021
xi2mask_isset_for_device(XI2Mask *mask, const DeviceIntPtr dev, int event_type)
1023
BUG_WARN(dev->id < 0);
1024
BUG_WARN(dev->id >= mask->nmasks);
1025
BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size);
1027
return BitIsOn(mask->masks[dev->id], event_type);
1031
* Test if the bit for event type is set for this device, or the
1032
* XIAllDevices/XIAllMasterDevices (if applicable) is set.
1034
* @return TRUE if the bit is set, FALSE otherwise
1037
xi2mask_isset(XI2Mask *mask, const DeviceIntPtr dev, int event_type)
1041
if (xi2mask_isset_for_device(mask, inputInfo.all_devices, event_type))
1043
else if (xi2mask_isset_for_device(mask, dev, event_type))
1045
else if (IsMaster(dev) && xi2mask_isset_for_device(mask, inputInfo.all_master_devices, event_type))
1052
* Set the mask bit for this event type for this device.
1055
xi2mask_set(XI2Mask *mask, int deviceid, int event_type)
1057
BUG_WARN(deviceid < 0);
1058
BUG_WARN(deviceid >= mask->nmasks);
1059
BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size);
1061
SetBit(mask->masks[deviceid], event_type);
1065
* Zero out the xi2mask, for the deviceid given. If the deviceid is < 0, all
1069
xi2mask_zero(XI2Mask *mask, int deviceid)
1073
BUG_WARN(deviceid > 0 && deviceid >= mask->nmasks);
1076
memset(mask->masks[deviceid], 0, mask->mask_size);
1078
for (i = 0; i < mask->nmasks; i++)
1079
memset(mask->masks[i], 0, mask->mask_size);
1083
* Merge source into dest, i.e. dest |= source.
1084
* If the masks are of different size, only the overlapping section is merged.
1087
xi2mask_merge(XI2Mask *dest, const XI2Mask *source)
1091
for (i = 0; i < min(dest->nmasks, source->nmasks); i++)
1092
for (j = 0; j < min(dest->mask_size, source->mask_size); j++)
1093
dest->masks[i][j] |= source->masks[i][j];
1097
* @return The number of masks in mask
1100
xi2mask_num_masks(const XI2Mask *mask)
1102
return mask->nmasks;
1106
* @return The size of each mask in bytes
1109
xi2mask_mask_size(const XI2Mask *mask)
1111
return mask->mask_size;
1115
* Set the mask for the given deviceid to the source mask.
1116
* If the mask given is larger than the target memory, only the overlapping
1120
xi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask,
1123
BUG_WARN(deviceid < 0);
1124
BUG_WARN(deviceid >= xi2mask->nmasks);
1126
memcpy(xi2mask->masks[deviceid], mask, min(xi2mask->mask_size, mask_size));
1130
* Get a reference to the XI2mask for this particular device.
1132
const unsigned char *
1133
xi2mask_get_one_mask(const XI2Mask *mask, int deviceid)
1135
BUG_WARN(deviceid < 0);
1136
BUG_WARN(deviceid >= mask->nmasks);
1138
return mask->masks[deviceid];