From 831a7cf3eea1015a76f4accba4f4d237a5336f7b Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 19 Jun 2013 18:19:45 +0200 Subject: 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. --- core/input/input.c | 62 ++++++++++++++++++++++++++++++++++++++++---------- core/input/input.h | 1 + core/input/keycodes.h | 1 + etc/input.conf | 1 + video/out/x11_common.c | 7 ++++-- 5 files changed, 58 insertions(+), 14 deletions(-) diff --git a/core/input/input.c b/core/input/input.c index 5b9a31866c..ba35efd0e6 100644 --- a/core/input/input.c +++ b/core/input/input.c @@ -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; diff --git a/core/input/input.h b/core/input/input.h index 551ba80db6..071efe5def 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -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; diff --git a/core/input/keycodes.h b/core/input/keycodes.h index b086d82809..80e2561514 100644 --- a/core/input/keycodes.h +++ b/core/input/keycodes.h @@ -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) \ diff --git a/etc/input.conf b/etc/input.conf index d2a39aca30..91382d58a5 100644 --- a/etc/input.conf +++ b/etc/input.conf @@ -176,6 +176,7 @@ JOY_BTN3 add volume -1 # Mostly for internal purposes MOUSE_MOVE ignore +MOUSE_LEAVE ignore # # Not assigned by default diff --git a/video/out/x11_common.c b/video/out/x11_common.c index 9d2db30924..bbb6fca997 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -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); } -- cgit v1.2.3