Skip to content

Commit

Permalink
input: trigger mouse_leave key bindings if mouse leaves mouse area
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
wm4 committed Jun 29, 2013
1 parent fc422f5 commit 831a7cf
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 14 deletions.
62 changes: 50 additions & 12 deletions core/input/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
};
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand All @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions core/input/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions core/input/keycodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down
1 change: 1 addition & 0 deletions etc/input.conf
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ JOY_BTN3 add volume -1

# Mostly for internal purposes
MOUSE_MOVE ignore
MOUSE_LEAVE ignore

#
# Not assigned by default
Expand Down
7 changes: 5 additions & 2 deletions video/out/x11_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 831a7cf

Please sign in to comment.