From 252bd4eb41691d279957528c7aad8610cf242914 Mon Sep 17 00:00:00 2001 From: Lephe Date: Tue, 8 Nov 2022 22:22:21 +0100 Subject: [PATCH] keydev: add low-level filter for async keyboard handlers --- include/gint/drivers/keydev.h | 17 +++++++++++++++++ src/keysc/keydev.c | 13 +++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/gint/drivers/keydev.h b/include/gint/drivers/keydev.h index 39132cd..40defec 100644 --- a/include/gint/drivers/keydev.h +++ b/include/gint/drivers/keydev.h @@ -10,6 +10,7 @@ extern "C" { #endif #include +#include /* Size of the buffer event queue */ #define KEYBOARD_QUEUE_SIZE 32 @@ -128,6 +129,9 @@ typedef struct { } GPACKEDENUM keydev_transform_t; +/* keydev_async_filter_t: Low-level asynchronous event filter. */ +typedef bool (*keydev_async_filter_t)(key_event_t event); + /* keydev_t: Keyboard device This structure represents the state and settings of a keyboard device that @@ -159,6 +163,13 @@ typedef struct { /* Event transforms */ keydev_transform_t tr; + /* Asynchronous event filter. This is a low-level filter which is + called when events are generated to process and filter them. It + provides the unique ability to run keyboard-triggered code even if + the program's main thread is busy, for instance running some sort of + infinite loop. */ + keydev_async_filter_t async_filter; + // /* delayed_* is set when the delayed modifier is active (after a press/ @@ -250,6 +261,12 @@ key_event_t keydev_unqueue_event(keydev_t *d); must be terminated by a 0 keycode. */ bool keydev_idle(keydev_t *d, ...); +/* keydev_async_filter(): Obtain current async filter */ +keydev_async_filter_t keydev_async_filter(keydev_t const *d); + +/* keydev_set_async_filter(): Set low-level async filter */ +void keydev_set_async_filter(keydev_t *d, keydev_async_filter_t filter); + //--- // High-level API to read from the device //--- diff --git a/src/keysc/keydev.c b/src/keysc/keydev.c index 05052ba..4242ed2 100644 --- a/src/keysc/keydev.c +++ b/src/keysc/keydev.c @@ -31,6 +31,9 @@ static int standard_repeater(GUNUSED int key, GUNUSED int duration, int count) Returns false if the event cannot be pushed. */ bool keydev_queue_push(keydev_t *d, key_event_t ev) { + if(d->async_filter && !d->async_filter(ev)) + return true; + int next = (d->queue_end + 1) % KEYBOARD_QUEUE_SIZE; if(next == d->queue_next) { @@ -147,6 +150,16 @@ void keydev_tick(keydev_t *d, uint us) } } +keydev_async_filter_t keydev_async_filter(keydev_t const *d) +{ + return d->async_filter; +} + +void keydev_set_async_filter(keydev_t *d, keydev_async_filter_t filter) +{ + d->async_filter = filter; +} + //--- // Keyboard event generation //---