diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2011-11-03 13:39:59 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2011-12-09 14:56:23 +1000 |
commit | b8b90cd1610331ff12fa3f70bf372670af7795ec (patch) | |
tree | 6a17496ecde536666f4ce92cc55d8a000a04ccdb | |
parent | 4bc2761ad5ec2d0668aec639780ffb136605fbc8 (diff) |
Add a new XI2Mask struct and a few helper functions.
The current XI2 mask handling is handy for copying (fixed size arrays) but a
pain to deal with otherwise. Add a struct for XI2 masks and the required
accessors.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Chase Douglas <chase.douglas@canonical.com>
-rw-r--r-- | dix/inpututils.c | 180 | ||||
-rw-r--r-- | include/input.h | 1 | ||||
-rw-r--r-- | include/inputstr.h | 6 | ||||
-rw-r--r-- | include/inpututils.h | 12 | ||||
-rw-r--r-- | test/xi2/Makefile.am | 5 | ||||
-rw-r--r-- | test/xi2/xi2.c | 129 |
6 files changed, 332 insertions, 1 deletions
diff --git a/dix/inpututils.c b/dix/inpututils.c index c152b2d8b..05d4c7ce1 100644 --- a/dix/inpututils.c +++ b/dix/inpututils.c @@ -892,3 +892,183 @@ double_to_fp3232(double in) 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; + + if (dev->id < 0 || dev->id >= mask->nmasks || event_type >= mask->mask_size) + return 0; + + 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) +{ + if (deviceid < 0 || deviceid >= mask->nmasks || event_type >= mask->mask_size) + return; + + 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; + + if (deviceid > 0 && deviceid >= mask->nmasks) + return; + + 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) +{ + if (deviceid < 0 || deviceid >= xi2mask->nmasks) + return; + + 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) +{ + if (deviceid < 0 || deviceid >= mask->nmasks) + return NULL; + + return mask->masks[deviceid]; +} diff --git a/include/input.h b/include/input.h index 8e7b47a4c..8b0c18e70 100644 --- a/include/input.h +++ b/include/input.h @@ -205,6 +205,7 @@ extern _X_EXPORT KeybdCtrl defaultKeyboardControl; extern _X_EXPORT PtrCtrl defaultPointerControl; typedef struct _InputOption InputOption; +typedef struct _XI2Mask XI2Mask; typedef struct _InputAttributes { char *product; diff --git a/include/inputstr.h b/include/inputstr.h index f9cb8fe0f..a73ace830 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -622,4 +622,10 @@ static inline WindowPtr DeepestSpriteWin(SpritePtr sprite) return sprite->spriteTrace[sprite->spriteTraceGood - 1]; } +struct _XI2Mask { + unsigned char **masks; /* event mask in masks[deviceid][event type byte] */ + size_t nmasks; /* number of masks */ + size_t mask_size; /* size of each mask in bytes */ +}; + #endif /* INPUTSTRUCT_H */ diff --git a/include/inpututils.h b/include/inpututils.h index 2832ed5b1..5f9dfecc3 100644 --- a/include/inpututils.h +++ b/include/inpututils.h @@ -46,4 +46,16 @@ FP1616 double_to_fp1616(double in); double fp1616_to_double(FP1616 in); double fp3232_to_double(FP3232 in); + +XI2Mask* xi2mask_new(void); +XI2Mask* xi2mask_new_with_size(size_t, size_t); /* don't use it */ +void xi2mask_free(XI2Mask** mask); +Bool xi2mask_isset(XI2Mask* mask, const DeviceIntPtr dev, int event_type); +void xi2mask_set(XI2Mask *mask, int deviceid, int event_type); +void xi2mask_zero(XI2Mask *mask, int deviceid); +void xi2mask_merge(XI2Mask *dest, const XI2Mask *source); +size_t xi2mask_num_masks(const XI2Mask *mask); +size_t xi2mask_mask_size(const XI2Mask *mask); +void xi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask, size_t mask_size); +const unsigned char* xi2mask_get_one_mask(const XI2Mask *xi2mask, int deviceid); #endif diff --git a/test/xi2/Makefile.am b/test/xi2/Makefile.am index c6e93e78f..913ba0f8b 100644 --- a/test/xi2/Makefile.am +++ b/test/xi2/Makefile.am @@ -10,7 +10,8 @@ noinst_PROGRAMS = \ protocol-xipassivegrabdevice \ protocol-xiquerypointer \ protocol-xiwarppointer \ - protocol-eventconvert + protocol-eventconvert \ + xi2 TESTS=$(noinst_PROGRAMS) TESTS_ENVIRONMENT = $(XORG_MALLOC_DEBUG_ENV) @@ -34,6 +35,7 @@ protocol_xiquerypointer_LDADD=$(TEST_LDADD) protocol_xipassivegrabdevice_LDADD=$(TEST_LDADD) protocol_xiwarppointer_LDADD=$(TEST_LDADD) protocol_eventconvert_LDADD=$(TEST_LDADD) +xi2_LDADD=$(TEST_LDADD) protocol_xiqueryversion_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient protocol_xiquerydevice_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient @@ -44,6 +46,7 @@ protocol_xigetclientpointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-w protocol_xipassivegrabdevice_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,GrabButton -Wl,-wrap,dixLookupWindow -Wl,-wrap,WriteToClient protocol_xiquerypointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupWindow protocol_xiwarppointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupWindow +xi2_LDFLAGS=$(AM_LDFLAGS) protocol_xiqueryversion_SOURCES=$(COMMON_SOURCES) protocol-xiqueryversion.c protocol_xiquerydevice_SOURCES=$(COMMON_SOURCES) protocol-xiquerydevice.c diff --git a/test/xi2/xi2.c b/test/xi2/xi2.c new file mode 100644 index 000000000..5143caff8 --- /dev/null +++ b/test/xi2/xi2.c @@ -0,0 +1,129 @@ +/** + * Copyright © 2011 Red Hat, Inc. + * + * 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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdint.h> +#include "inpututils.h" +#include "inputstr.h" +#include "assert.h" + +static void xi2mask_test(void) +{ + XI2Mask *xi2mask = NULL, + *mergemask = NULL; + unsigned char *mask; + DeviceIntRec dev; + int i; + + /* size >= nmasks * 2 for the test cases below */ + xi2mask = xi2mask_new_with_size(MAXDEVICES + 2, (MAXDEVICES + 2) * 2); + assert(xi2mask); + assert(xi2mask->nmasks > 0); + assert(xi2mask->mask_size > 0); + + assert(xi2mask_mask_size(xi2mask) == xi2mask->mask_size); + assert(xi2mask_num_masks(xi2mask) == xi2mask->nmasks); + + mask = calloc(1, xi2mask_mask_size(xi2mask)); + /* ensure zeros */ + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) { + const unsigned char *m = xi2mask_get_one_mask(xi2mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + } + + /* set various bits */ + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) { + const unsigned char *m; + xi2mask_set(xi2mask, i, i); + + dev.id = i; + assert(xi2mask_isset(xi2mask, &dev, i)); + + m = xi2mask_get_one_mask(xi2mask, i); + SetBit(mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + ClearBit(mask, i); + } + + /* ensure zeros one-by-one */ + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) { + const unsigned char *m = xi2mask_get_one_mask(xi2mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) != 0); + xi2mask_zero(xi2mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + } + + /* re-set, zero all */ + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) + xi2mask_set(xi2mask, i, i); + xi2mask_zero(xi2mask, -1); + + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) { + const unsigned char *m = xi2mask_get_one_mask(xi2mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + } + + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) { + const unsigned char *m; + SetBit(mask, i); + xi2mask_set_one_mask(xi2mask, i, mask, xi2mask_mask_size(xi2mask)); + m = xi2mask_get_one_mask(xi2mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + ClearBit(mask, i); + } + + mergemask = xi2mask_new_with_size(MAXDEVICES + 2, (MAXDEVICES + 2) * 2); + for (i = 0; i < xi2mask_num_masks(mergemask); i++) { + dev.id = i; + xi2mask_set(mergemask, i, i * 2); + } + + /* xi2mask still has all i bits set, should now also have all i * 2 bits */ + xi2mask_merge(xi2mask, mergemask); + for (i = 0; i < xi2mask_num_masks(mergemask); i++) { + const unsigned char *m = xi2mask_get_one_mask(xi2mask, i); + SetBit(mask, i); + SetBit(mask, i * 2); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + ClearBit(mask, i); + ClearBit(mask, i * 2); + } + + xi2mask_free(&xi2mask); + assert(xi2mask == NULL); + + xi2mask_free(&mergemask); + assert(mergemask == NULL); + free(mask); +} + + +int main(int argc, char** argv) +{ + xi2mask_test(); + + return 0; +} |