1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-11 08:37:59 +00:00

input: trigger mouse_leave key bindings if mouse leaves mouse area

Also, implement mouse leave events for X11. But evne on other
platforms, these events will be generated if mouse crosses a section's
mouse area boundaries within the mpv window.
This commit is contained in:
wm4 2013-06-19 18:19:45 +02:00
parent fc422f5aeb
commit 831a7cf3ee
5 changed files with 58 additions and 14 deletions

View File

@ -438,8 +438,9 @@ static const struct key_name key_names[] = {
{ MP_KEY_PREV, "XF86_PREV" },
{ MP_KEY_NEXT, "XF86_NEXT" },
{ MP_KEY_CLOSE_WIN, "CLOSE_WIN" },
{ MP_KEY_MOUSE_MOVE, "MOUSE_MOVE" },
{ MP_KEY_CLOSE_WIN, "CLOSE_WIN" },
{ MP_KEY_MOUSE_MOVE, "MOUSE_MOVE" },
{ MP_KEY_MOUSE_LEAVE, "MOUSE_LEAVE" },
{ 0, NULL }
};
@ -517,6 +518,7 @@ struct input_ctx {
// Mouse position on the consumer side (as command.c sees it)
int mouse_x, mouse_y;
char *mouse_section; // last section to receive mouse event
// Mouse position on the producer side (as the VO sees it)
// Unlike mouse_x/y, this can be used to resolve mouse click bindings.
@ -1202,8 +1204,21 @@ static struct cmd_bind_section *get_bind_section(struct input_ctx *ictx,
}
static struct cmd_bind *find_any_bind_for_key(struct input_ctx *ictx,
char *force_section,
int n, int *keys)
{
if (force_section) {
for (int b = 0; b < 2; b++) {
bool builtin = !!b;
struct cmd_bind_section *bs = get_bind_section(ictx, builtin,
bstr0(force_section));
struct cmd_bind *cmd = find_bind_for_key(bs->cmd_binds, n, keys);
if (cmd)
return cmd;
}
return NULL;
}
for (int i = ictx->num_active_sections - 1; i >= 0; i--) {
struct active_section *as = &ictx->active_sections[i];
bstr name = bstr0(as->name);
@ -1226,19 +1241,21 @@ static struct cmd_bind *find_any_bind_for_key(struct input_ctx *ictx,
if (as->flags & MP_INPUT_EXCLUSIVE)
break;
}
return NULL;
}
static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, int n, int *keys)
static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, char *force_section,
int n, int *keys)
{
if (ictx->test)
return handle_test(ictx, n, keys);
struct cmd_bind *cmd = find_any_bind_for_key(ictx, n, keys);
struct cmd_bind *cmd = find_any_bind_for_key(ictx, force_section, n, keys);
if (cmd == NULL && n > 1) {
// Hitting two keys at once, and if there's no binding for this
// combination, the key hit last should be checked.
cmd = find_any_bind_for_key(ictx, 1, (int[]){keys[n - 1]});
cmd = find_any_bind_for_key(ictx, force_section, 1, (int[]){keys[n - 1]});
}
if (cmd == NULL) {
@ -1249,7 +1266,9 @@ static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, int n, int *keys)
return NULL;
}
mp_cmd_t *ret = mp_input_parse_cmd(bstr0(cmd->cmd), cmd->location);
if (!ret) {
if (ret) {
ret->input_section = cmd->owner->section;
} else {
char *key_buf = get_key_combo_name(keys, n);
mp_tmsg(MSGT_INPUT, MSGL_ERR,
"Invalid command for bound key '%s': '%s'\n", key_buf, cmd->cmd);
@ -1276,9 +1295,6 @@ static mp_cmd_t *interpret_key(struct input_ctx *ictx, int code)
unsigned int j;
mp_cmd_t *ret;
if (code == MP_KEY_MOUSE_MOVE)
return get_cmd_from_keys(ictx, 1, (int[]){code});
/* On normal keyboards shift changes the character code of non-special
* keys, so don't count the modifier separately for those. In other words
* we want to have "a" and "A" instead of "a" and "Shift+A"; but a separate
@ -1307,7 +1323,7 @@ static mp_cmd_t *interpret_key(struct input_ctx *ictx, int code)
ictx->num_key_down++;
ictx->last_key_down = mp_time_us();
ictx->ar_state = 0;
ictx->current_down_cmd = get_cmd_from_keys(ictx, ictx->num_key_down,
ictx->current_down_cmd = get_cmd_from_keys(ictx, NULL, ictx->num_key_down,
ictx->key_down);
if (ictx->current_down_cmd && (code & MP_KEY_EMIT_ON_UP))
ictx->current_down_cmd->key_up_follows = true;
@ -1344,7 +1360,7 @@ static mp_cmd_t *interpret_key(struct input_ctx *ictx, int code)
// Interpret only maximal point of multibutton event
ret = NULL;
if (emit_key)
ret = get_cmd_from_keys(ictx, ictx->num_key_down, ictx->key_down);
ret = get_cmd_from_keys(ictx, NULL, ictx->num_key_down, ictx->key_down);
if (doubleclick) {
ictx->key_down[j] = code - MP_MOUSE_BTN0_DBL + MP_MOUSE_BTN0;
return ret;
@ -1435,12 +1451,34 @@ void mp_input_feed_key(struct input_ctx *ictx, int code)
add_key_cmd(ictx, cmd);
}
static void trigger_mouse_leave(struct input_ctx *ictx, char *new_section)
{
if (!new_section)
new_section = "default";
char *old = ictx->mouse_section;
ictx->mouse_section = new_section;
if (old && strcmp(old, ictx->mouse_section) != 0) {
struct mp_cmd *cmd =
get_cmd_from_keys(ictx, old, 1, (int[]){MP_KEY_MOUSE_LEAVE});
if (cmd)
add_key_cmd(ictx, cmd);
}
}
void mp_input_set_mouse_pos(struct input_ctx *ictx, int x, int y)
{
ictx->mouse_event_counter++;
ictx->mouse_vo_x = x;
ictx->mouse_vo_y = y;
struct mp_cmd *cmd = interpret_key(ictx, MP_KEY_MOUSE_MOVE);
struct mp_cmd *cmd =
get_cmd_from_keys(ictx, NULL, 1, (int[]){MP_KEY_MOUSE_MOVE});
trigger_mouse_leave(ictx, cmd ? cmd->input_section : NULL);
if (!cmd)
return;
cmd->mouse_move = true;

View File

@ -138,6 +138,7 @@ typedef struct mp_cmd {
bool raw_args;
enum mp_on_osd on_osd;
bstr original;
char *input_section;
bool key_up_follows;
bool mouse_move;
int mouse_x, mouse_y;

View File

@ -206,6 +206,7 @@
#define MP_KEY_CLOSE_WIN (MP_KEY_INTERN+0)
// Generated by input.c (VOs use mp_input_set_mouse_pos())
#define MP_KEY_MOUSE_MOVE ((MP_KEY_INTERN+1)|MP_NO_REPEAT_KEY)
#define MP_KEY_MOUSE_LEAVE ((MP_KEY_INTERN+2)|MP_NO_REPEAT_KEY)
#define MP_KEY_DEPENDS_ON_MOUSE_POS(code) \

View File

@ -176,6 +176,7 @@ JOY_BTN3 add volume -1
# Mostly for internal purposes
MOUSE_MOVE ignore
MOUSE_LEAVE ignore
#
# Not assigned by default

View File

@ -756,6 +756,9 @@ int vo_x11_check_events(struct vo *vo)
case MotionNotify:
vo_mouse_movement(vo, Event.xmotion.x, Event.xmotion.y);
break;
case LeaveNotify:
mplayer_put_key(vo->key_fifo, MP_KEY_MOUSE_LEAVE);
break;
case ButtonPress:
mplayer_put_key(vo->key_fifo,
(MP_MOUSE_BTN0 + Event.xbutton.button - 1)
@ -987,10 +990,10 @@ static void vo_x11_map_window(struct vo *vo, int x, int y, int w, int h)
vo_x11_decoration(vo, 0);
// map window
vo_x11_selectinput_witherr(vo, x11->display, x11->window,
StructureNotifyMask |
StructureNotifyMask | ExposureMask |
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | ExposureMask);
PointerMotionMask | LeaveWindowMask);
XMapWindow(x11->display, x11->window);
vo_x11_clearwindow(vo, x11->window);
}