From 6ea2f991a3b61f51b492cc6fe07a6d0985990d50 Mon Sep 17 00:00:00 2001 From: Lephe Date: Sun, 24 Jul 2022 21:57:18 +0100 Subject: [PATCH] keysc: make repeat settings global instead of just for getkey() Having repeat settings only for getkey() meant that repeats that occur while getkey() is not running (i.e., all of them) would be lost. This is due to e57efb5e3 which replaced on-demand repeats with normal event generation. Now the settings are applied globally, which allows repeats to be enabled even when getkey() is not active. This also reduces the feature gap between getkey() and raw events, which reduces the risk of running into edges cases by using both. The previous API is retained for source compatibility until gint 3.0 but the changes are now applied globally so the semantics are slightly different. --- include/gint/drivers/keydev.h | 36 ++++++++++++-- include/gint/keyboard.h | 79 +++++++++++------------------- src/keysc/getkey.c | 92 +++++++++++++++++------------------ src/keysc/keydev.c | 15 ++++++ src/keysc/keysc.c | 6 ++- 5 files changed, 122 insertions(+), 106 deletions(-) diff --git a/include/gint/drivers/keydev.h b/include/gint/drivers/keydev.h index be56273..233d78f 100644 --- a/include/gint/drivers/keydev.h +++ b/include/gint/drivers/keydev.h @@ -100,6 +100,9 @@ enum { KEYDEV_TR_DELETE_RELEASES = 0x40, }; +/* keydev_repeat_profile_t: Function deciding when and how to repeat keys. */ +typedef int (*keydev_repeat_profile_t)(int key, int duration, int count); + /* keydev_transform_t: Full specification for transforms on the event stream */ typedef struct { /* List of enabled transforms. The order is cannot be changed because @@ -121,7 +124,7 @@ typedef struct { that the precision of the delay is limited by the speed at which the keyboard is scanned, which is nowhere near microsecond-level. By default (128 Hz) the precision is about 7.8 ms. */ - int (*repeater)(int key, int duration, int count); + keydev_repeat_profile_t repeater; } GPACKEDENUM keydev_transform_t; @@ -190,6 +193,9 @@ typedef struct { /* Event queue (circular buffer) */ key_event_t queue[KEYBOARD_QUEUE_SIZE]; + /* Parameters for the standard repeat function */ + int rep_standard_first, rep_standard_next; + } keydev_t; /* keydev_std(): Standard keyboard input device @@ -234,10 +240,9 @@ void keydev_tick(keydev_t *d, uint us); /* keydev_unqueue_event(): Retrieve the next keyboard event in queue - This source provides the queued KEYEV_UP and KEYEV_DOWN events generated - from the regular scans in chronological order. It does not generate the - KEYEV_HOLD events though, keyev_repeat_event() must be used to obtain these - at the end of every tick. */ + This source provides the queued KEYEV_UP, KEYEV_DOWN and KEYEV_HOLD events + generated from the regular scans in chronological order. It does not apply + transforms; to do this, use keydev_read(). */ key_event_t keydev_unqueue_event(keydev_t *d); /* keydev_idle(): Check if all keys are released @@ -258,6 +263,27 @@ keydev_transform_t keydev_transform(keydev_t *d); /* keydev_set_transform(): Set transform parameters */ void keydev_set_transform(keydev_t *d, keydev_transform_t tr); +/* keydev_set_standard_repeats(): Enable a simple repeater + + This function changes the [repeater] member of the devices's transform. It + loads the default repeat profile which applies one delay (in us) before the + first repeat, and then a second, usually shorter delay, between subsequent + repeats. + + The unit of the argument is in microseconds, but the granularity of the + delay is dependent on the keyboard scan frequency. In the default setting + (128 Hz scans), the possible repeat delays are approximately 8 ms, 16 ms, + 23 ms, 31 ms. The system default is (500 ms, 125 ms). With the 128 Hz + setting, this default is reached exactly without approximation. gint's + default is (400 ms, 40 ms) for more reactivity. + + Note: Due to a current API limitation, every input device uses the delays + for the physical keyboard. + + @first_us Delay between key press and first repeat (microseconds) + @next_us Delay between subsequent repeats (microseconds) */ +void keydev_set_standard_repeats(keydev_t *d, int first_us, int next_us); + /* keydev_read(): Retrieve the next transformed event */ key_event_t keydev_read(keydev_t *d); diff --git a/include/gint/keyboard.h b/include/gint/keyboard.h index 374c307..13af587 100644 --- a/include/gint/keyboard.h +++ b/include/gint/keyboard.h @@ -225,10 +225,6 @@ enum { GETKEY_DEFAULT = 0xdf, }; -/* getkey_profile_t: Custom repeat profile function - See getkey_set_repeat_profile() for details. */ -typedef int (*getkey_profile_t)(int key, int duration, int count); - /* getkey_feature_t: Custom feature function See getkey_set_feature_function() for details. */ typedef bool (*getkey_feature_t)(key_event_t event); @@ -260,53 +256,6 @@ typedef bool (*getkey_feature_t)(key_event_t event); Returns a key event of type KEYEV_DOWN or KEYEV_HOLD with [mod=1]. */ key_event_t getkey_opt(int options, volatile int *timeout); -/* getkey_repeat(): Set repeat delays for getkey() - - This function updates the repeat delays of getkey() and getkey_opt(). The - unit of the argument is in milliseconds, but the granularity of the delay is - dependent on the keyboard scan frequency. - - In the default setting (128 Hz scans), the possible repeat delays are - approximately 8 ms, 16 ms, 23 ms, 31 ms... the provided arguments will be - rounded to the closest feasible delays to ensure that repetitions are - perfectly regular, rather than approximating the requested frequency. - - The system default is (500 ms, 125 ms). With the 128 Hz setting, this - default is reached exactly without approximation. gint's default is (400 ms, - 40 ms) for more reactivity. - - @first Delay between key press and first repeat (no more than one hour) - @next Delay between subsequent repeats (no more than one hour) */ -void getkey_repeat(int first, int next); - -/* getkey_repeat_profile(): Get the current repeat profile function */ -getkey_profile_t getkey_repeat_profile(void); - -/* getkey_set_repeat_profile(): Set the repeat profile function - - The repeat profile is called by getkey() and getkey_opt() when a key is - pressed or held, and getkey() is planning to repeat it. The profile decides - whether such repetition is allowed, and if so, how long it shoud take. The - profile has access to the following information: - - @key Key for which a repetition is being considered - @duration Duration since the key was first pressed (us) - @count Number of previous repeats (0 on the first call) - - The profile function must either return a positive number of microseconds to - wait until the next repeat, or -1 to block the repeat indefinitely. Note - that the keyboard device typically updates every 7-8 ms, timings are tracked - in microseconds only to limit deviations. - - Setting a repeat profile overrides GETKEY_REP_ARROWS, GETKEY_REP_ALL, and - the repeat delays. Calling with profile=NULL restores this behavior. - - This mechanism replaces a "repeat filter" that existed until gint 2.4. The - main difference is that the repeat filter was called when the repeat event - arrived, whereas the repeat profile is called one repeat earlier to schedule - the repeat exactly when needed. */ -void getkey_set_repeat_profile(getkey_profile_t profile); - /* getkey_feature_function(): Get the current feature function */ getkey_feature_t getkey_feature_function(void); @@ -346,4 +295,32 @@ int keycode_digit(int keycode); } #endif +//--- +// Deprecated functions for repeat control +// +// The following types and functions have been deprecated. The handling of +// repeats is done inside the keyboard device (see ). +// Until gint 2.9, the device had repeats disabled by default and getkey() +// enabled them. The problem is that repeats usually occur while getkey() is +// not running, so repeats wouldn't work as expected. +// +// Thus, getkey()-specific APIs related to repeat settings are now deprecated +// in favor of the ones provided by , which apply +// globally instead of just when getkey() is being run. +//--- + +typedef void *getkey_profile_t; + +__attribute__((deprecated( + "Use keydev_set_standard_repeats(), which is permanent, instead"))) +void getkey_repeat(int first, int next); + +__attribute__((deprecated( + "Use keydev_transform(keydev_std()).repeater instead"))) +getkey_profile_t getkey_repeat_profile(void); + +__attribute__((deprecated( + "Set the [repeater] attribute with keydev_set_transform() instead"))) +void getkey_set_repeat_profile(getkey_profile_t profile); + #endif /* GINT_KEYBOARD */ diff --git a/src/keysc/getkey.c b/src/keysc/getkey.c index c3d2774..c1a28e4 100644 --- a/src/keysc/getkey.c +++ b/src/keysc/getkey.c @@ -11,25 +11,8 @@ #include #endif -/* Delay before first repeat and subsequent repeats, in milliseconds */ -static int rep_first = 400, rep_next = 40; -/* Repeat profile function */ -static getkey_profile_t repeat_profile = NULL; /* Feature function */ static getkey_feature_t feature_function = NULL; -/* Repeater specification */ -static enum { NONE, ALL, ARROWS, FILTER } repeat_mode; - -static int getkey_repeater(int key, int duration, int count) -{ - if(repeat_mode == NONE) return -1; - if(repeat_mode == FILTER) return repeat_profile(key, duration, count); - - if(repeat_mode == ARROWS && key != KEY_LEFT && key != KEY_RIGHT - && key != KEY_UP && key != KEY_DOWN) return -1; - - return (count ? rep_next : rep_first) * 1000; -} /* getkey(): Wait for a key press */ key_event_t getkey(void) @@ -41,71 +24,64 @@ key_event_t getkey(void) key_event_t getkey_opt(int opt, volatile int *timeout) { keydev_t *d = keydev_std(); - keydev_transform_t tr0 = keydev_transform(d); + keydev_transform_t tr = keydev_transform(d); key_event_t e; int o = KEYDEV_TR_REPEATS + KEYDEV_TR_DELETE_MODIFIERS + KEYDEV_TR_DELETE_RELEASES + (opt & (GETKEY_MOD_SHIFT + GETKEY_MOD_ALPHA)); - keydev_set_transform(d, (keydev_transform_t){ o, getkey_repeater }); - - repeat_mode = NONE; - if(opt & GETKEY_REP_ARROWS) repeat_mode = ARROWS; - if(opt & GETKEY_REP_ALL) repeat_mode = ALL; - if(opt & GETKEY_REP_PROFILE && repeat_profile) repeat_mode = FILTER; + keydev_set_transform(d, (keydev_transform_t){ o, tr.repeater }); while(1) { e = keydev_read(d); if(e.type == KEYEV_NONE && timeout && *timeout) break; + /* Skip repeat events that are not enabled by options */ + if(e.type == KEYEV_HOLD && !(opt & GETKEY_REP_ALL)) + { + if(!(opt & GETKEY_REP_ARROWS)) + continue; + if(e.key != KEY_LEFT && e.key != KEY_RIGHT && + e.key != KEY_UP && e.key != KEY_DOWN) + continue; + } + #ifdef FX9860G /* Backlight toggle */ - else if((opt & GETKEY_BACKLIGHT) && e.type == KEYEV_DOWN && + if((opt & GETKEY_BACKLIGHT) && e.type == KEYEV_DOWN && e.key == KEY_OPTN && e.shift && !e.alpha) + { t6k11_backlight(-1); + continue; + } #endif /* Return-to-menu */ - else if((opt & GETKEY_MENU) && e.type == KEYEV_DOWN && + if((opt & GETKEY_MENU) && e.type == KEYEV_DOWN && e.key == KEY_MENU && !e.shift && !e.alpha) + { gint_osmenu(); + continue; + } - else if(e.type == KEYEV_DOWN || e.type == KEYEV_HOLD) + if(e.type == KEYEV_DOWN || e.type == KEYEV_HOLD) { /* Custom global features */ bool accepted = false; if((opt & GETKEY_FEATURES) && feature_function) accepted = feature_function(e); - /* Return if the even has not been accepted yet */ + /* Return if the event has not been accepted yet */ if(!accepted) break; } } - keydev_set_transform(d, tr0); + /* Restore previous transform settings */ + keydev_set_transform(d, tr); return e; } -/* getkey_repeat(): Set repeat delays for getkey() */ -void getkey_repeat(int first, int next) -{ - rep_first = first; - rep_next = next; -} - -/* getkey_repeat_profile(): Get the current repeat profile function */ -getkey_profile_t getkey_repeat_profile(void) -{ - return repeat_profile; -} - -/* getkey_set_repeat_profile(): Set the repeat profile function */ -void getkey_set_repeat_profile(getkey_profile_t profile) -{ - repeat_profile = profile; -} - /* getkey_feature_function(): Get the current feature function */ getkey_feature_t getkey_feature_function(void) { @@ -117,3 +93,23 @@ void getkey_set_feature_function(getkey_feature_t function) { feature_function = function; } + +/* Deprecated repeat functions */ + +void getkey_repeat(int first, int next) +{ + keydev_set_standard_repeats(keydev_std(), first * 1000, next * 1000); +} + +getkey_profile_t getkey_repeat_profile(void) +{ + return keydev_transform(keydev_std()).repeater; +} + +/* getkey_set_repeat_profile(): Set the repeat profile function */ +void getkey_set_repeat_profile(getkey_profile_t profile) +{ + keydev_transform_t tr = keydev_transform(keydev_std()); + tr.repeater = profile; + keydev_set_transform(keydev_std(), tr); +} diff --git a/src/keysc/keydev.c b/src/keysc/keydev.c index 413d143..d797739 100644 --- a/src/keysc/keydev.c +++ b/src/keysc/keydev.c @@ -15,6 +15,13 @@ void keydev_init(keydev_t *d) memset(d, 0, sizeof *d); } +static int standard_repeater(GUNUSED int key, GUNUSED int duration, int count) +{ + /* FIXME: Do not use the delays from keydev_std() on every device */ + keydev_t *d = keydev_std(); + return count ? d->rep_standard_next : d->rep_standard_first; +} + //--- // Driver event generation //--- @@ -223,6 +230,14 @@ void keydev_set_transform(keydev_t *d, keydev_transform_t tr) d->tr = tr; } +/* keydev_set_standard_repeats(): Enable a simple repeater */ +void keydev_set_standard_repeats(keydev_t *d, int first, int next) +{ + d->rep_standard_first = first; + d->rep_standard_next = next; + d->tr.repeater = standard_repeater; +} + /* keydev_read(): Retrieve the next transformed event */ key_event_t keydev_read(keydev_t *d) { diff --git a/src/keysc/keysc.c b/src/keysc/keysc.c index d5ef2f6..b49d444 100644 --- a/src/keysc/keysc.c +++ b/src/keysc/keysc.c @@ -99,8 +99,10 @@ static void configure(void) { keydev_init(&keysc_dev); - /* Set the default repeat times (milliseconds) */ - getkey_repeat(400, 40); + /* Set the default repeat to 400/40 ms */ + keydev_t *d = keydev_std(); + keydev_set_transform(d, (keydev_transform_t){ KEYDEV_TR_REPEATS, NULL }); + keydev_set_standard_repeats(d, 400 * 1000, 40 * 1000); /* The timer will be stopped when the timer driver is unloaded */ keysc_tid = timer_configure(TIMER_ANY, keysc_scan_us,