fix: repair Wayland key lifecycle
This commit is contained in:
107
wayland_state.c
Normal file
107
wayland_state.c
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "wayland_state.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
enum {
|
||||
Downforward = 1,
|
||||
Downeaten = 2,
|
||||
};
|
||||
|
||||
void
|
||||
wlstateinit(Wlstate *s)
|
||||
{
|
||||
memset(s, 0, sizeof *s);
|
||||
}
|
||||
|
||||
void
|
||||
wlstatecancelrepeat(Wlstate *s)
|
||||
{
|
||||
s->repeating = 0;
|
||||
s->repeatkey = 0;
|
||||
s->repeatat = 0;
|
||||
}
|
||||
|
||||
void
|
||||
wlstateclear(Wlstate *s)
|
||||
{
|
||||
memset(s->down, 0, sizeof s->down);
|
||||
wlstatecancelrepeat(s);
|
||||
}
|
||||
|
||||
void
|
||||
wlstaterepeatinfo(Wlstate *s, int rate, int delay)
|
||||
{
|
||||
/* Settings changes end the old schedule; a later press starts a new one. */
|
||||
wlstatecancelrepeat(s);
|
||||
s->rate = rate > 0 ? rate : 0;
|
||||
s->delay = delay > 0 ? delay : 0;
|
||||
}
|
||||
|
||||
int
|
||||
wlstatepress(Wlstate *s, uint32_t key, int eaten, int repeatable,
|
||||
uint64_t now)
|
||||
{
|
||||
uint64_t delay;
|
||||
|
||||
if(key >= Wlkeymax)
|
||||
return 0;
|
||||
s->down[key] = eaten ? Downeaten : Downforward;
|
||||
wlstatecancelrepeat(s);
|
||||
if(eaten && repeatable && s->rate > 0){
|
||||
delay = s->delay;
|
||||
if(UINT64_MAX - now < delay)
|
||||
s->repeatat = UINT64_MAX;
|
||||
else
|
||||
s->repeatat = now + delay;
|
||||
s->repeatkey = key;
|
||||
s->repeating = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
wlstaterelease(Wlstate *s, uint32_t key)
|
||||
{
|
||||
int forward;
|
||||
|
||||
if(key >= Wlkeymax)
|
||||
return 1;
|
||||
forward = s->down[key] != Downeaten;
|
||||
s->down[key] = 0;
|
||||
if(s->repeating && s->repeatkey == key)
|
||||
wlstatecancelrepeat(s);
|
||||
return forward;
|
||||
}
|
||||
|
||||
int
|
||||
wlstatetimeout(Wlstate *s, uint64_t now)
|
||||
{
|
||||
uint64_t d;
|
||||
|
||||
if(!s->repeating)
|
||||
return -1;
|
||||
if(now >= s->repeatat)
|
||||
return 0;
|
||||
d = s->repeatat - now;
|
||||
return d > INT_MAX ? INT_MAX : (int)d;
|
||||
}
|
||||
|
||||
int
|
||||
wlstaterepeat(Wlstate *s, uint64_t now, uint32_t *key)
|
||||
{
|
||||
uint64_t step;
|
||||
|
||||
if(!s->repeating || now < s->repeatat)
|
||||
return 0;
|
||||
if(key != 0)
|
||||
*key = s->repeatkey;
|
||||
step = 1000 / s->rate;
|
||||
if(step == 0)
|
||||
step = 1;
|
||||
if(UINT64_MAX - now < step)
|
||||
s->repeatat = UINT64_MAX;
|
||||
else
|
||||
s->repeatat = now + step;
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user