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,