mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 00:00:28 +01:00
util: add a helper struct for an evdev mask
Allows to keep track of a set of evdev masks, or at least the subset we care about. The EV_KEY range is split into two masks to save some memory. The future use of this is for the plugins to use those masks and some of those will set BTN_TOOL_PEN and friends. This would immediately create an 81 byte mask of zeroes just to keep that one bit. Splitting it into a key/btn mask with the latter starting at BTN_MISC means we duplicate the infmask struct (2x16 bytes) but instead only use 8 bytes for the mask itself to keep the BTN_TOOL_PEN bits. Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1271>
This commit is contained in:
parent
d45f4493f1
commit
f04b276ac1
2 changed files with 166 additions and 0 deletions
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/input.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "util-bits.h"
|
||||
#include "util-input-event.h"
|
||||
#include "util-mem.h"
|
||||
#include "util-newtype.h"
|
||||
|
|
@ -652,3 +653,121 @@ evdev_frame_clone(struct evdev_frame *frame)
|
|||
|
||||
return clone;
|
||||
}
|
||||
|
||||
struct evdev_mask {
|
||||
bitmask_t ev;
|
||||
bitmask_t rel;
|
||||
bitmask_t sw;
|
||||
infmask_t key; /* < BTN_MISC */
|
||||
infmask_t btn; /* >= BTN_MISC */
|
||||
infmask_t abs;
|
||||
};
|
||||
|
||||
static_assert(sizeof(bitmask_t) * 8 >= EV_MAX, "bitmask size too small");
|
||||
static_assert(sizeof(bitmask_t) * 8 >= EV_REL, "bitmask size too small");
|
||||
static_assert(sizeof(bitmask_t) * 8 >= EV_SW, "bitmask size too small");
|
||||
|
||||
static inline void
|
||||
evdev_mask_reset(struct evdev_mask *mask)
|
||||
{
|
||||
mask->ev = bitmask_new();
|
||||
mask->rel = bitmask_new();
|
||||
mask->sw = bitmask_new();
|
||||
infmask_reset(&mask->key);
|
||||
infmask_reset(&mask->btn);
|
||||
infmask_reset(&mask->abs);
|
||||
}
|
||||
|
||||
static inline struct evdev_mask *
|
||||
evdev_mask_new(void)
|
||||
{
|
||||
struct evdev_mask *mask = zalloc(sizeof(*mask));
|
||||
evdev_mask_reset(mask);
|
||||
return mask;
|
||||
}
|
||||
|
||||
static inline void
|
||||
evdev_mask_destroy(struct evdev_mask *mask)
|
||||
{
|
||||
if (mask) {
|
||||
evdev_mask_reset(mask);
|
||||
free(mask);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_DESTROY_CLEANUP_FUNC(evdev_mask);
|
||||
|
||||
static inline void
|
||||
evdev_mask_set_usage(struct evdev_mask *mask, evdev_usage_t usage)
|
||||
{
|
||||
unsigned int type = evdev_usage_type(usage);
|
||||
unsigned int code = evdev_usage_code(usage);
|
||||
|
||||
if (type >= EV_MAX)
|
||||
return;
|
||||
|
||||
bitmask_set_bit(&mask->ev, type);
|
||||
|
||||
switch (type) {
|
||||
case EV_ABS:
|
||||
if (code <= ABS_MAX)
|
||||
infmask_set_bit(&mask->abs, code);
|
||||
break;
|
||||
case EV_KEY:
|
||||
if (code < BTN_MISC)
|
||||
infmask_set_bit(&mask->key, code);
|
||||
else if (code <= KEY_MAX)
|
||||
infmask_set_bit(&mask->btn, code - BTN_MISC);
|
||||
break;
|
||||
case EV_REL:
|
||||
if (code <= REL_MAX)
|
||||
bitmask_set_bit(&mask->rel, code);
|
||||
break;
|
||||
case EV_SW:
|
||||
if (code <= SW_MAX)
|
||||
bitmask_set_bit(&mask->sw, code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
evdev_mask_set_enum(struct evdev_mask *mask, enum evdev_usage usage)
|
||||
{
|
||||
evdev_mask_set_usage(mask, evdev_usage_from(usage));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
evdev_mask_is_set(const struct evdev_mask *mask, evdev_usage_t usage)
|
||||
{
|
||||
unsigned int type = evdev_usage_type(usage);
|
||||
unsigned int code = evdev_usage_code(usage);
|
||||
|
||||
if (type >= EV_MAX)
|
||||
return false;
|
||||
|
||||
if (!bitmask_bit_is_set(mask->ev, type))
|
||||
return false;
|
||||
|
||||
bool isset = false;
|
||||
switch (type) {
|
||||
case EV_ABS:
|
||||
isset = infmask_bit_is_set(&mask->abs, code);
|
||||
break;
|
||||
case EV_KEY:
|
||||
if (code < BTN_MISC)
|
||||
isset = infmask_bit_is_set(&mask->key, code);
|
||||
else
|
||||
isset = infmask_bit_is_set(&mask->btn, code - BTN_MISC);
|
||||
break;
|
||||
case EV_REL:
|
||||
isset = bitmask_bit_is_set(mask->rel, code);
|
||||
break;
|
||||
case EV_SW:
|
||||
isset = bitmask_bit_is_set(mask->sw, code);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return isset;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3150,6 +3150,51 @@ START_TEST(infmask_test)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(evdev_mask_test)
|
||||
{
|
||||
_destroy_(evdev_mask) *mask = evdev_mask_new();
|
||||
|
||||
evdev_mask_reset(mask);
|
||||
|
||||
litest_assert(bitmask_is_empty(mask->ev));
|
||||
litest_assert(bitmask_is_empty(mask->rel));
|
||||
litest_assert(bitmask_is_empty(mask->sw));
|
||||
litest_assert(infmask_is_empty(&mask->key));
|
||||
litest_assert(infmask_is_empty(&mask->btn));
|
||||
litest_assert(infmask_is_empty(&mask->abs));
|
||||
|
||||
evdev_mask_set_enum(mask, EVDEV_BTN_TOOL_PEN);
|
||||
evdev_mask_set_enum(mask, EVDEV_BTN_TOOL_AIRBRUSH);
|
||||
|
||||
litest_assert(bitmask_bit_is_set(mask->ev, EV_KEY));
|
||||
|
||||
/* Verify these are in btn, not key */
|
||||
litest_assert(!infmask_is_empty(&mask->btn));
|
||||
litest_assert(infmask_is_empty(&mask->key));
|
||||
|
||||
litest_assert(evdev_mask_is_set(mask, evdev_usage_from(EVDEV_BTN_TOOL_PEN)));
|
||||
litest_assert(
|
||||
!evdev_mask_is_set(mask, evdev_usage_from(EVDEV_BTN_TOOL_RUBBER)));
|
||||
litest_assert(
|
||||
evdev_mask_is_set(mask, evdev_usage_from(EVDEV_BTN_TOOL_AIRBRUSH)));
|
||||
|
||||
/* Test regular key (should go into key field) */
|
||||
evdev_mask_set_enum(mask, EVDEV_KEY_ESC);
|
||||
litest_assert(!infmask_is_empty(&mask->key));
|
||||
litest_assert(evdev_mask_is_set(mask, evdev_usage_from(EVDEV_KEY_ESC)));
|
||||
|
||||
evdev_mask_set_enum(mask, EVDEV_REL_X);
|
||||
litest_assert(bitmask_bit_is_set(mask->ev, EV_REL));
|
||||
litest_assert(bitmask_bit_is_set(mask->rel, REL_X));
|
||||
litest_assert(evdev_mask_is_set(mask, evdev_usage_from(EVDEV_REL_X)));
|
||||
|
||||
evdev_mask_set_enum(mask, EVDEV_ABS_X);
|
||||
litest_assert(bitmask_bit_is_set(mask->ev, EV_ABS));
|
||||
litest_assert(!infmask_is_empty(&mask->abs));
|
||||
litest_assert(evdev_mask_is_set(mask, evdev_usage_from(EVDEV_ABS_X)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
|
@ -3238,6 +3283,8 @@ main(void)
|
|||
|
||||
ADD_TEST(infmask_test);
|
||||
|
||||
ADD_TEST(evdev_mask_test);
|
||||
|
||||
enum litest_runner_result result = litest_runner_run_tests(runner);
|
||||
litest_runner_destroy(runner);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue