mirror of
https://github.com/mpv-player/mpv
synced 2025-01-01 20:32:13 +00:00
input: simplify by not tracking key up/down states
We only need to track key up/down for a single key. There may be some minor loss of robustness, but this can (probably) happen only if a VO or user sends strange or complicated sequences of events. In the normal case, what we do is more than enough. Most simplification comes from the fact that mpv is not a game console, and users normally execute only one action at once.
This commit is contained in:
parent
46e0ede228
commit
6b9ec41a43
@ -139,9 +139,8 @@ struct input_ctx {
|
|||||||
|
|
||||||
// history of key downs - the newest is in position 0
|
// history of key downs - the newest is in position 0
|
||||||
int key_history[MP_MAX_KEY_DOWN];
|
int key_history[MP_MAX_KEY_DOWN];
|
||||||
// these are the keys currently down
|
// key code of the last key that triggered MP_KEY_STATE_DOWN
|
||||||
int key_down[MP_MAX_KEY_DOWN];
|
int last_key_down;
|
||||||
unsigned int num_key_down;
|
|
||||||
int64_t last_key_down_time;
|
int64_t last_key_down_time;
|
||||||
bool current_down_cmd_need_release;
|
bool current_down_cmd_need_release;
|
||||||
struct mp_cmd *current_down_cmd;
|
struct mp_cmd *current_down_cmd;
|
||||||
@ -529,28 +528,17 @@ static void release_down_cmd(struct input_ctx *ictx, bool drop_current)
|
|||||||
}
|
}
|
||||||
ictx->current_down_cmd = NULL;
|
ictx->current_down_cmd = NULL;
|
||||||
ictx->current_down_cmd_need_release = false;
|
ictx->current_down_cmd_need_release = false;
|
||||||
|
ictx->last_key_down = 0;
|
||||||
ictx->last_key_down_time = 0;
|
ictx->last_key_down_time = 0;
|
||||||
ictx->ar_state = -1;
|
ictx->ar_state = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int find_key_down(struct input_ctx *ictx, int code)
|
static void release_all(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
code &= ~(MP_KEY_STATE_UP | MP_KEY_STATE_DOWN | MP_KEY_MODIFIER_MASK);
|
ictx->last_key_down = 0;
|
||||||
for (int j = 0; j < ictx->num_key_down; j++) {
|
ictx->last_key_down_time = 0;
|
||||||
if ((ictx->key_down[j] & ~MP_KEY_MODIFIER_MASK) == code)
|
release_down_cmd(ictx, false);
|
||||||
return j;
|
update_mouse_section(ictx);
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void remove_key_down(struct input_ctx *ictx, int code)
|
|
||||||
{
|
|
||||||
int index = find_key_down(ictx, code);
|
|
||||||
if (index >= 0) {
|
|
||||||
memmove(&ictx->key_down[index], &ictx->key_down[index + 1],
|
|
||||||
(ictx->num_key_down - (index + 1)) * sizeof(int));
|
|
||||||
ictx->num_key_down -= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whether a command shall be sent on both key down and key up events.
|
// Whether a command shall be sent on both key down and key up events.
|
||||||
@ -585,58 +573,49 @@ static void interpret_key(struct input_ctx *ictx, int code, double scale)
|
|||||||
if (unmod >= 32 && unmod < MP_KEY_BASE)
|
if (unmod >= 32 && unmod < MP_KEY_BASE)
|
||||||
code &= ~MP_KEY_MODIFIER_SHIFT;
|
code &= ~MP_KEY_MODIFIER_SHIFT;
|
||||||
|
|
||||||
if (mp_msg_test(ictx->log, MSGL_DEBUG)) {
|
int state = code & (MP_KEY_STATE_DOWN | MP_KEY_STATE_UP);
|
||||||
int noflags = code & ~(MP_KEY_STATE_DOWN | MP_KEY_STATE_UP);
|
code = code & ~(unsigned)state;
|
||||||
char *key = mp_input_get_key_name(noflags);
|
|
||||||
MP_DBG(ictx, "key code=%#x '%s'%s%s\n",
|
|
||||||
code, key, (code & MP_KEY_STATE_DOWN) ? " down" : "",
|
|
||||||
(code & MP_KEY_STATE_UP) ? " up" : "");
|
|
||||||
talloc_free(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(code & MP_KEY_STATE_UP) && ictx->num_key_down >= MP_MAX_KEY_DOWN) {
|
if (mp_msg_test(ictx->log, MSGL_DEBUG)) {
|
||||||
MP_ERR(ictx, "Too many key down events at the same time\n");
|
char *key = mp_input_get_key_name(code);
|
||||||
return;
|
MP_DBG(ictx, "key code=%#x '%s'%s%s\n",
|
||||||
|
code, key, (state & MP_KEY_STATE_DOWN) ? " down" : "",
|
||||||
|
(state & MP_KEY_STATE_UP) ? " up" : "");
|
||||||
|
talloc_free(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MP_KEY_DEPENDS_ON_MOUSE_POS(unmod))
|
if (MP_KEY_DEPENDS_ON_MOUSE_POS(unmod))
|
||||||
ictx->mouse_event_counter++;
|
ictx->mouse_event_counter++;
|
||||||
ictx->got_new_events = true;
|
ictx->got_new_events = true;
|
||||||
|
|
||||||
bool key_was_down = find_key_down(ictx, code) >= 0;
|
|
||||||
struct mp_cmd *cmd = NULL;
|
struct mp_cmd *cmd = NULL;
|
||||||
|
|
||||||
if (code & MP_KEY_STATE_DOWN) {
|
if (state == MP_KEY_STATE_DOWN) {
|
||||||
// Check if we don't already have this key as pushed
|
// Protect against VOs which send STATE_DOWN with autorepeat
|
||||||
if (key_was_down)
|
if (ictx->last_key_down == code)
|
||||||
return;
|
return;
|
||||||
// Cancel current down-event (there can be only one)
|
// Cancel current down-event (there can be only one)
|
||||||
release_down_cmd(ictx, true);
|
release_down_cmd(ictx, true);
|
||||||
ictx->key_down[ictx->num_key_down] = code & ~MP_KEY_STATE_DOWN;
|
|
||||||
ictx->num_key_down++;
|
|
||||||
update_mouse_section(ictx);
|
update_mouse_section(ictx);
|
||||||
ictx->last_key_down_time = mp_time_us();
|
cmd = get_cmd_from_keys(ictx, NULL, code);
|
||||||
ictx->ar_state = 0;
|
key_buf_add(ictx->key_history, code);
|
||||||
cmd = get_cmd_from_keys(ictx, NULL, code & ~MP_KEY_STATE_DOWN);
|
|
||||||
key_buf_add(ictx->key_history, code & ~MP_KEY_STATE_DOWN);
|
|
||||||
if (cmd && should_drop_cmd(ictx, cmd)) {
|
if (cmd && should_drop_cmd(ictx, cmd)) {
|
||||||
ictx->num_key_down--;
|
|
||||||
talloc_free(cmd);
|
talloc_free(cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ictx->last_key_down = code;
|
||||||
|
ictx->last_key_down_time = mp_time_us();
|
||||||
|
ictx->ar_state = 0;
|
||||||
if (cmd && (code & MP_KEY_EMIT_ON_UP))
|
if (cmd && (code & MP_KEY_EMIT_ON_UP))
|
||||||
cmd->key_up_follows = true;
|
cmd->key_up_follows = true;
|
||||||
ictx->current_down_cmd = mp_cmd_clone(cmd);
|
ictx->current_down_cmd = mp_cmd_clone(cmd);
|
||||||
ictx->current_down_cmd_need_release = false;
|
ictx->current_down_cmd_need_release = false;
|
||||||
} else if (code & MP_KEY_STATE_UP) {
|
} else if (state == MP_KEY_STATE_UP) {
|
||||||
if (key_was_down) {
|
// Most VOs send RELEASE_ALL anyway
|
||||||
remove_key_down(ictx, code & ~MP_KEY_STATE_DOWN);
|
release_all(ictx);
|
||||||
release_down_cmd(ictx, false);
|
|
||||||
}
|
|
||||||
update_mouse_section(ictx);
|
|
||||||
} else {
|
} else {
|
||||||
// Press of key with no separate down/up events
|
// Press of key with no separate down/up events
|
||||||
if (key_was_down) {
|
if (ictx->last_key_down == code) {
|
||||||
// Mixing press events and up/down with the same key is not allowed
|
// Mixing press events and up/down with the same key is not allowed
|
||||||
MP_WARN(ictx, "Mixing key presses and up/down.\n");
|
MP_WARN(ictx, "Mixing key presses and up/down.\n");
|
||||||
}
|
}
|
||||||
@ -671,9 +650,7 @@ static void mp_input_feed_key(struct input_ctx *ictx, int code, double scale)
|
|||||||
{
|
{
|
||||||
if (code == MP_INPUT_RELEASE_ALL) {
|
if (code == MP_INPUT_RELEASE_ALL) {
|
||||||
MP_DBG(ictx, "release all\n");
|
MP_DBG(ictx, "release all\n");
|
||||||
ictx->num_key_down = 0;
|
release_all(ictx);
|
||||||
release_down_cmd(ictx, false);
|
|
||||||
update_mouse_section(ictx);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (code == MP_KEY_MOUSE_LEAVE) {
|
if (code == MP_KEY_MOUSE_LEAVE) {
|
||||||
@ -1043,7 +1020,7 @@ static void input_wait_read(struct input_ctx *ictx, int time)
|
|||||||
*/
|
*/
|
||||||
static void read_events(struct input_ctx *ictx, int time)
|
static void read_events(struct input_ctx *ictx, int time)
|
||||||
{
|
{
|
||||||
if (ictx->num_key_down && ictx->ar_rate > 0) {
|
if (ictx->last_key_down && ictx->ar_rate > 0) {
|
||||||
time = FFMIN(time, 1000 / ictx->ar_rate);
|
time = FFMIN(time, 1000 / ictx->ar_rate);
|
||||||
time = FFMIN(time, ictx->ar_delay);
|
time = FFMIN(time, ictx->ar_delay);
|
||||||
}
|
}
|
||||||
@ -1088,8 +1065,8 @@ int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd)
|
|||||||
static mp_cmd_t *check_autorepeat(struct input_ctx *ictx)
|
static mp_cmd_t *check_autorepeat(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
// No input : autorepeat ?
|
// No input : autorepeat ?
|
||||||
if (ictx->ar_rate > 0 && ictx->ar_state >= 0 && ictx->num_key_down > 0
|
if (ictx->ar_rate > 0 && ictx->ar_state >= 0 && ictx->last_key_down
|
||||||
&& !(ictx->key_down[ictx->num_key_down - 1] & MP_NO_REPEAT_KEY)) {
|
&& !(ictx->last_key_down & MP_NO_REPEAT_KEY)) {
|
||||||
int64_t t = mp_time_us();
|
int64_t t = mp_time_us();
|
||||||
if (ictx->last_ar + 2000000 < t)
|
if (ictx->last_ar + 2000000 < t)
|
||||||
ictx->last_ar = t;
|
ictx->last_ar = t;
|
||||||
|
Loading…
Reference in New Issue
Block a user