mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-28 20:43:36 +01:00
keyboard: add custom repeat filters for full repeat control
This change introduces a new getkey_repeat_filter() function that can be used to individually accept, deny or delay repeat events for specific keys and timings.
This commit is contained in:
parent
a4d23ef7ad
commit
4288dc27d9
2 changed files with 70 additions and 5 deletions
|
@ -200,11 +200,13 @@ enum {
|
|||
/* Repeat arrow keys, or even all keys */
|
||||
GETKEY_REP_ARROWS = 0x10,
|
||||
GETKEY_REP_ALL = 0x20,
|
||||
/* Enable repeat event filtering; see getkey_repeat_filter() */
|
||||
GETKEY_REP_FILTER = 0x40,
|
||||
|
||||
/* No modifiers */
|
||||
GETKEY_NONE = 0x00,
|
||||
/* Default settings of getkey() */
|
||||
GETKEY_DEFAULT = 0x1f,
|
||||
GETKEY_DEFAULT = 0x5f,
|
||||
};
|
||||
|
||||
/* getkey_opt(): Enhanced getkey()
|
||||
|
@ -244,6 +246,33 @@ key_event_t getkey_opt(int options, volatile int *timeout);
|
|||
@next Delay between subsequent repeats (no more than one hour) */
|
||||
void getkey_repeat(int first, int next);
|
||||
|
||||
/* getkey_repeat_filter(): Set the repeat filter function
|
||||
|
||||
This function is called by getkey() and getkey_opt() every time a repeat
|
||||
event occurs when GETKEY_REPEAT_FILTER. The function can decide whether to
|
||||
keep, delay it or drop it entirely. It can also change the repeat delays
|
||||
with getkey_repeat() for fully custom repeat delay curves.
|
||||
|
||||
The time elapsed since the last accepted repeat is passed to the filter
|
||||
function; this time must be larger than the repeat time set with
|
||||
getkey_repeat() for getkey() and getkey_opt() to consider a repeat, but it
|
||||
can be much longer if some repeat events were previously filtered out.
|
||||
|
||||
@key Key that is about to be repeated
|
||||
@duration Duration since last accepted repeat
|
||||
@count Number of previous repeats
|
||||
|
||||
The repeat function must either return:
|
||||
* 0, in which case the even is accepted
|
||||
* A positive number of milliseconds, in which case the event is tentatively
|
||||
re-emitted after that time (the filter function will be called again)
|
||||
* A negative number, in which case the event is dropped and further repeats
|
||||
are denied.
|
||||
|
||||
By default the filter function is NULL, which accepts all repeat events.
|
||||
This behavior can be restored explicitly by calling with function=NULL. */
|
||||
void getkey_repeat_filter(int (*filter)(int key, int duration, int count));
|
||||
|
||||
//---
|
||||
// Key code functions
|
||||
//---
|
||||
|
|
|
@ -15,13 +15,16 @@ static int rep_first = 64;
|
|||
/* Delay between subsequent repeats, in scan intervals */
|
||||
static int rep_next = 8;
|
||||
|
||||
/* getkey() - wait for a pressed key */
|
||||
/* Repeat filter function */
|
||||
static int (*filter_function)(int key, int duration, int count) = NULL;
|
||||
|
||||
/* getkey(): Wait for a key press */
|
||||
key_event_t getkey(void)
|
||||
{
|
||||
return getkey_opt(GETKEY_DEFAULT, NULL);
|
||||
}
|
||||
|
||||
/* getkey_opt() - enhanced getkey() */
|
||||
/* getkey_opt(): Enhanced getkey() */
|
||||
key_event_t getkey_opt(int opt, volatile int *timeout)
|
||||
{
|
||||
key_event_t ev;
|
||||
|
@ -33,6 +36,8 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
|
|||
static int rep_count = 0;
|
||||
/* Keyboard time when the key was pressed */
|
||||
static int rep_time = 0;
|
||||
/* Additional repeat delay set by the filtering function */
|
||||
static int rep_delay = 0;
|
||||
|
||||
/* Reset the state if the repeated key went up while getkey() was not
|
||||
aware (this happens when different keyboard primitives are used) */
|
||||
|
@ -41,6 +46,7 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
|
|||
rep_key = 0;
|
||||
rep_count = 0;
|
||||
rep_time = 0;
|
||||
rep_delay = 0;
|
||||
}
|
||||
|
||||
while(1) switch((ev = pollevent()).type)
|
||||
|
@ -85,6 +91,7 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
|
|||
rep_key = key;
|
||||
rep_count = 0;
|
||||
rep_time = ev.time;
|
||||
rep_delay = 0;
|
||||
|
||||
ev.mod = 1;
|
||||
ev.shift = shift;
|
||||
|
@ -108,11 +115,33 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
|
|||
/* If the key is key pressed long enough, create a new event */
|
||||
int duration = (int16_t)(ev.time - rep_time);
|
||||
|
||||
int target = (rep_count) ? rep_next : rep_first;
|
||||
if(rep_delay < 0) break;
|
||||
int target = (rep_count ? rep_next : rep_first) + rep_delay;
|
||||
if(duration < target) break;
|
||||
|
||||
/* Filter out the event if repeat filtering is on */
|
||||
if(filter_function && (opt & GETKEY_REP_FILTER))
|
||||
{
|
||||
int s = filter_function(rep_key, duration, rep_count);
|
||||
/* Drop repeats forever */
|
||||
if(s < 0)
|
||||
{
|
||||
rep_delay = -1;
|
||||
break;
|
||||
}
|
||||
/* Delay repeat by set amount */
|
||||
if(s > 0)
|
||||
{
|
||||
s = (s * KEYBOARD_SCAN_FREQUENCY) / 1000;
|
||||
rep_delay += s;
|
||||
break;
|
||||
}
|
||||
/* Accepts repeat (fallthrough) */
|
||||
}
|
||||
|
||||
rep_time += target;
|
||||
rep_count++;
|
||||
rep_delay = 0;
|
||||
|
||||
ev.mod = 1;
|
||||
ev.shift = shift;
|
||||
|
@ -128,13 +157,20 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
|
|||
rep_key = 0;
|
||||
rep_count = 0;
|
||||
rep_time = 0;
|
||||
rep_delay = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* getkey_repeat() - set repeat delays for getkey() */
|
||||
/* getkey_repeat(): Set repeat delays for getkey() */
|
||||
void getkey_repeat(int first, int next)
|
||||
{
|
||||
rep_first = (first * KEYBOARD_SCAN_FREQUENCY) / 1000;
|
||||
rep_next = (next * KEYBOARD_SCAN_FREQUENCY) / 1000;
|
||||
}
|
||||
|
||||
/* getkey_repeat_filter(): Set the repeat filter function */
|
||||
void getkey_repeat_filter(int (*filter)(int key, int duration, int count))
|
||||
{
|
||||
filter_function = filter;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue