summaryrefslogtreecommitdiffstats
path: root/input
diff options
context:
space:
mode:
Diffstat (limited to 'input')
-rw-r--r--input/cmd.c44
-rw-r--r--input/cmd.h6
-rw-r--r--input/event.c15
-rw-r--r--input/event.h5
-rw-r--r--input/input.c388
-rw-r--r--input/input.h21
-rw-r--r--input/ipc-dummy.c6
-rw-r--r--input/ipc-unix.c151
-rw-r--r--input/ipc-win.c38
-rw-r--r--input/ipc.c205
-rw-r--r--input/keycodes.c35
-rw-r--r--input/keycodes.h14
-rw-r--r--input/meson.build20
-rw-r--r--input/pipe-win32.c110
-rw-r--r--input/sdl_gamepad.c14
15 files changed, 561 insertions, 511 deletions
diff --git a/input/cmd.c b/input/cmd.c
index 5a073d9fec..64232143f7 100644
--- a/input/cmd.c
+++ b/input/cmd.c
@@ -336,11 +336,34 @@ static int pctx_read_token(struct parse_ctx *ctx, bstr *out)
return -1;
}
if (!bstr_eatstart0(&ctx->str, "\"")) {
- MP_ERR(ctx, "Unterminated quotes: ...>%.*s<.\n", BSTR_P(start));
+ MP_ERR(ctx, "Unterminated double quote: ...>%.*s<.\n", BSTR_P(start));
return -1;
}
return 1;
}
+ if (bstr_eatstart0(&ctx->str, "'")) {
+ int next = bstrchr(ctx->str, '\'');
+ if (next < 0) {
+ MP_ERR(ctx, "Unterminated single quote: ...>%.*s<.\n", BSTR_P(start));
+ return -1;
+ }
+ *out = bstr_splice(ctx->str, 0, next);
+ ctx->str = bstr_cut(ctx->str, next+1);
+ return 1;
+ }
+ if (ctx->start.len > 1 && bstr_eatstart0(&ctx->str, "`")) {
+ char endquote[2] = {ctx->str.start[0], '`'};
+ ctx->str = bstr_cut(ctx->str, 1);
+ int next = bstr_find(ctx->str, (bstr){endquote, 2});
+ if (next < 0) {
+ MP_ERR(ctx, "Unterminated custom quote: ...>%.*s<.\n", BSTR_P(start));
+ return -1;
+ }
+ *out = bstr_splice(ctx->str, 0, next);
+ ctx->str = bstr_cut(ctx->str, next+2);
+ return 1;
+ }
+
return read_token(ctx->str, &ctx->str, out) ? 1 : 0;
}
@@ -544,6 +567,15 @@ mp_cmd_t *mp_cmd_clone(mp_cmd_t *cmd)
return ret;
}
+static int get_arg_count(const struct mp_cmd_def *cmd)
+{
+ for (int i = MP_CMD_DEF_MAX_ARGS - 1; i >= 0; i--) {
+ if (cmd->args[i].type)
+ return i + 1;
+ }
+ return 0;
+}
+
void mp_cmd_dump(struct mp_log *log, int msgl, char *header, struct mp_cmd *cmd)
{
if (!mp_msg_test(log, msgl))
@@ -555,7 +587,9 @@ void mp_cmd_dump(struct mp_log *log, int msgl, char *header, struct mp_cmd *cmd)
return;
}
mp_msg(log, msgl, "%s, flags=%d, args=[", cmd->name, cmd->flags);
+ int argc = get_arg_count(cmd->def);
for (int n = 0; n < cmd->nargs; n++) {
+ const char *argname = cmd->def->args[MPMIN(n, argc - 1)].name;
char *s = m_option_print(cmd->args[n].type, &cmd->args[n].v);
if (n)
mp_msg(log, msgl, ", ");
@@ -565,7 +599,7 @@ void mp_cmd_dump(struct mp_log *log, int msgl, char *header, struct mp_cmd *cmd)
};
char *esc = NULL;
json_write(&esc, &node);
- mp_msg(log, msgl, "%s", esc ? esc : "<error>");
+ mp_msg(log, msgl, "%s=%s", argname, esc ? esc : "<error>");
talloc_free(esc);
talloc_free(s);
}
@@ -574,8 +608,10 @@ void mp_cmd_dump(struct mp_log *log, int msgl, char *header, struct mp_cmd *cmd)
bool mp_input_is_repeatable_cmd(struct mp_cmd *cmd)
{
- return (cmd->def->allow_auto_repeat) || cmd->def == &mp_cmd_list ||
- (cmd->flags & MP_ALLOW_REPEAT);
+ if (cmd->def == &mp_cmd_list && cmd->args[0].v.p)
+ cmd = cmd->args[0].v.p; // list - only 1st cmd is considered
+
+ return (cmd->def->allow_auto_repeat) || (cmd->flags & MP_ALLOW_REPEAT);
}
bool mp_input_is_scalable_cmd(struct mp_cmd *cmd)
diff --git a/input/cmd.h b/input/cmd.h
index c22672b9d3..3d4b15fcc3 100644
--- a/input/cmd.h
+++ b/input/cmd.h
@@ -23,7 +23,7 @@
#include "misc/bstr.h"
#include "options/m_option.h"
-#define MP_CMD_DEF_MAX_ARGS 9
+#define MP_CMD_DEF_MAX_ARGS 11
#define MP_CMD_OPT_ARG M_OPT_OPTIONAL_PARAM
struct mp_log;
@@ -85,6 +85,7 @@ enum mp_cmd_flags {
struct mp_cmd_arg {
const struct m_option *type;
union {
+ bool b;
int i;
int64_t i64;
float f;
@@ -152,7 +153,4 @@ struct mp_cmd *mp_cmd_clone(struct mp_cmd *cmd);
extern const struct m_option_type m_option_type_cycle_dir;
-#define OPT_CYCLEDIR(...) \
- OPT_GENERAL(double, __VA_ARGS__, .type = &m_option_type_cycle_dir)
-
#endif
diff --git a/input/event.c b/input/event.c
index 266e0294e2..6c1e00409a 100644
--- a/input/event.c
+++ b/input/event.c
@@ -37,6 +37,21 @@ void mp_event_drop_files(struct input_ctx *ictx, int num_files, char **files,
};
mp_input_run_cmd(ictx, cmd);
}
+ } else if (action == DND_INSERT_NEXT) {
+ /* To insert the entries in the correct order, we iterate over them
+ backwards */
+ for (int i = num_files - 1; i >= 0; i--) {
+ const char *cmd[] = {
+ "osd-auto",
+ "loadfile",
+ files[i],
+ /* Since we're inserting in reverse, wait til the final item
+ is added to start playing */
+ (i > 0) ? "insert-next" : "insert-next-play",
+ NULL
+ };
+ mp_input_run_cmd(ictx, cmd);
+ }
} else {
for (int i = 0; i < num_files; i++) {
const char *cmd[] = {
diff --git a/input/event.h b/input/event.h
index 1e2149bb89..5f48bee00e 100644
--- a/input/event.h
+++ b/input/event.h
@@ -24,16 +24,17 @@ struct input_ctx;
enum mp_dnd_action {
DND_REPLACE,
DND_APPEND,
+ DND_INSERT_NEXT,
};
// Enqueue files for playback after drag and drop
void mp_event_drop_files(struct input_ctx *ictx, int num_files, char **files,
- enum mp_dnd_action append);
+ enum mp_dnd_action action);
// Drop data in a specific format (identified by the mimetype).
// Returns <0 on error, ==0 if data was ok but empty, >0 on success.
int mp_event_drop_mime_data(struct input_ctx *ictx, const char *mime_type,
- bstr data, enum mp_dnd_action append);
+ bstr data, enum mp_dnd_action action);
// Many drag & drop APIs support multiple mime types, and this function returns
// whether a type is preferred (higher integer score), or supported (scores
diff --git a/input/input.c b/input/input.c
index f9475648b0..b24e82fe50 100644
--- a/input/input.c
+++ b/input/input.c
@@ -28,7 +28,6 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
-#include <pthread.h>
#include <assert.h>
#include "osdep/io.h"
@@ -51,13 +50,13 @@
#include "common/common.h"
#if HAVE_COCOA
-#include "osdep/macosx_events.h"
+#include "osdep/mac/app_bridge.h"
#endif
-#define input_lock(ictx) pthread_mutex_lock(&ictx->mutex)
-#define input_unlock(ictx) pthread_mutex_unlock(&ictx->mutex)
+#define input_lock(ictx) mp_mutex_lock(&ictx->mutex)
+#define input_unlock(ictx) mp_mutex_unlock(&ictx->mutex)
-#define MP_MAX_KEY_DOWN 4
+#define MP_MAX_KEY_DOWN 16
struct cmd_bind {
int keys[MP_MAX_KEY_DOWN];
@@ -80,8 +79,6 @@ struct cmd_bind_section {
#define MP_MAX_SOURCES 10
-#define MAX_ACTIVE_SECTIONS 50
-
struct active_section {
char *name;
int flags;
@@ -97,7 +94,7 @@ struct wheel_state {
};
struct input_ctx {
- pthread_mutex_t mutex;
+ mp_mutex mutex;
struct mp_log *log;
struct mpv_global *global;
struct m_config_cache *opts_cache;
@@ -122,6 +119,7 @@ struct input_ctx {
// Mouse position on the consumer side (as command.c sees it)
int mouse_x, mouse_y;
+ int mouse_hover; // updated on mouse-enter/leave
char *mouse_section; // last section to receive mouse event
// Mouse position on the producer side (as the VO sees it)
@@ -142,7 +140,7 @@ struct input_ctx {
int num_sections;
// List currently active command sections
- struct active_section active_sections[MAX_ACTIVE_SECTIONS];
+ struct active_section *active_sections;
int num_active_sections;
unsigned int mouse_event_counter;
@@ -170,40 +168,40 @@ struct input_opts {
// Autorepeat config (be aware of mp_input_set_repeat_info())
int ar_delay;
int ar_rate;
- int use_alt_gr;
- int use_appleremote;
- int use_gamepad;
- int use_media_keys;
- int default_bindings;
- int enable_mouse_movements;
- int vo_key_input;
- int test;
- int allow_win_drag;
+ bool use_alt_gr;
+ bool use_gamepad;
+ bool use_media_keys;
+ bool default_bindings;
+ bool builtin_bindings;
+ bool enable_mouse_movements;
+ bool vo_key_input;
+ bool test;
+ bool allow_win_drag;
+ bool preprocess_wheel;
};
const struct m_sub_options input_config = {
.opts = (const m_option_t[]) {
- OPT_STRING("input-conf", config_file, M_OPT_FILE),
- OPT_INT("input-ar-delay", ar_delay, 0),
- OPT_INT("input-ar-rate", ar_rate, 0),
- OPT_PRINT("input-keylist", mp_print_key_list),
- OPT_PRINT("input-cmdlist", mp_print_cmd_list),
- OPT_FLAG("input-default-bindings", default_bindings, 0),
- OPT_FLAG("input-test", test, 0),
- OPT_INTRANGE("input-doubleclick-time", doubleclick_time, 0, 0, 1000),
- OPT_FLAG("input-right-alt-gr", use_alt_gr, 0),
- OPT_INTRANGE("input-key-fifo-size", key_fifo_size, 0, 2, 65000),
- OPT_FLAG("input-cursor", enable_mouse_movements, 0),
- OPT_FLAG("input-vo-keyboard", vo_key_input, 0),
- OPT_FLAG("input-media-keys", use_media_keys, 0),
+ {"input-conf", OPT_STRING(config_file), .flags = M_OPT_FILE},
+ {"input-ar-delay", OPT_INT(ar_delay)},
+ {"input-ar-rate", OPT_INT(ar_rate)},
+ {"input-keylist", OPT_PRINT(mp_print_key_list)},
+ {"input-cmdlist", OPT_PRINT(mp_print_cmd_list)},
+ {"input-default-bindings", OPT_BOOL(default_bindings)},
+ {"input-builtin-bindings", OPT_BOOL(builtin_bindings)},
+ {"input-test", OPT_BOOL(test)},
+ {"input-doubleclick-time", OPT_INT(doubleclick_time),
+ M_RANGE(0, 1000)},
+ {"input-right-alt-gr", OPT_BOOL(use_alt_gr)},
+ {"input-key-fifo-size", OPT_INT(key_fifo_size), M_RANGE(2, 65000)},
+ {"input-cursor", OPT_BOOL(enable_mouse_movements)},
+ {"input-vo-keyboard", OPT_BOOL(vo_key_input)},
+ {"input-media-keys", OPT_BOOL(use_media_keys)},
+ {"input-preprocess-wheel", OPT_BOOL(preprocess_wheel)},
#if HAVE_SDL2_GAMEPAD
- OPT_FLAG("input-gamepad", use_gamepad, 0),
-#endif
- OPT_FLAG("window-dragging", allow_win_drag, 0),
- OPT_REPLACED("input-x11-keyboard", "input-vo-keyboard"),
-#if HAVE_COCOA
- OPT_REMOVED("input-appleremote", "replaced by MediaPlayer support"),
+ {"input-gamepad", OPT_BOOL(use_gamepad)},
#endif
+ {"window-dragging", OPT_BOOL(allow_win_drag)},
{0}
},
.size = sizeof(struct input_opts),
@@ -212,18 +210,20 @@ const struct m_sub_options input_config = {
.doubleclick_time = 300,
.ar_delay = 200,
.ar_rate = 40,
- .use_alt_gr = 1,
- .enable_mouse_movements = 1,
- .use_media_keys = 1,
- .default_bindings = 1,
- .vo_key_input = 1,
- .allow_win_drag = 1,
+ .use_alt_gr = true,
+ .enable_mouse_movements = true,
+ .use_media_keys = true,
+ .default_bindings = true,
+ .builtin_bindings = true,
+ .vo_key_input = true,
+ .allow_win_drag = true,
+ .preprocess_wheel = true,
},
.change_flags = UPDATE_INPUT,
};
static const char builtin_input_conf[] =
-#include "input/input_conf.h"
+#include "etc/input.conf.inc"
;
static bool test_rect(struct mp_rect *rc, int x, int y)
@@ -275,6 +275,14 @@ static struct mp_cmd *queue_peek_tail(struct cmd_queue *queue)
return cur;
}
+static void queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd)
+{
+ if (!cmd)
+ return;
+ queue_add_tail(&ictx->cmd_queue, cmd);
+ mp_input_wakeup(ictx);
+}
+
static void append_bind_info(struct input_ctx *ictx, char **pmsg,
struct cmd_bind *bind)
{
@@ -508,7 +516,7 @@ static void update_mouse_section(struct input_ctx *ictx)
if (strcmp(old, ictx->mouse_section) != 0) {
MP_TRACE(ictx, "input: switch section %s -> %s\n",
old, ictx->mouse_section);
- mp_input_queue_cmd(ictx, get_cmd_from_keys(ictx, old, MP_KEY_MOUSE_LEAVE));
+ queue_cmd(ictx, get_cmd_from_keys(ictx, old, MP_KEY_MOUSE_LEAVE));
}
}
@@ -526,7 +534,7 @@ static void release_down_cmd(struct input_ctx *ictx, bool drop_current)
{
memset(ictx->key_history, 0, sizeof(ictx->key_history));
ictx->current_down_cmd->is_up = true;
- mp_input_queue_cmd(ictx, ictx->current_down_cmd);
+ queue_cmd(ictx, ictx->current_down_cmd);
} else {
talloc_free(ictx->current_down_cmd);
}
@@ -590,7 +598,7 @@ static void interpret_key(struct input_ctx *ictx, int code, double scale,
ictx->current_down_cmd = mp_cmd_clone(cmd);
}
ictx->last_key_down = code;
- ictx->last_key_down_time = mp_time_us();
+ ictx->last_key_down_time = mp_time_ns();
ictx->ar_state = 0;
mp_input_wakeup(ictx); // possibly start timer for autorepeat
} else if (state == MP_KEY_STATE_UP) {
@@ -622,7 +630,7 @@ static void interpret_key(struct input_ctx *ictx, int code, double scale,
if (mp_input_is_scalable_cmd(cmd)) {
cmd->scale = scale;
cmd->scale_units = scale_units;
- mp_input_queue_cmd(ictx, cmd);
+ queue_cmd(ictx, cmd);
} else {
// Non-scalable commands won't understand cmd->scale, so synthesize
// multiple commands with cmd->scale = 1
@@ -631,9 +639,9 @@ static void interpret_key(struct input_ctx *ictx, int code, double scale,
// Avoid spamming the player with too many commands
scale_units = MPMIN(scale_units, 20);
for (int i = 0; i < scale_units - 1; i++)
- mp_input_queue_cmd(ictx, mp_cmd_clone(cmd));
+ queue_cmd(ictx, mp_cmd_clone(cmd));
if (scale_units)
- mp_input_queue_cmd(ictx, cmd);
+ queue_cmd(ictx, cmd);
}
}
@@ -703,7 +711,7 @@ static bool process_wheel(struct input_ctx *ictx, int code, double *scale,
return true;
}
-static void mp_input_feed_key(struct input_ctx *ictx, int code, double scale,
+static void feed_key(struct input_ctx *ictx, int code, double scale,
bool force_mouse)
{
struct input_opts *opts = ictx->opts;
@@ -718,8 +726,13 @@ static void mp_input_feed_key(struct input_ctx *ictx, int code, double scale,
if (!opts->enable_mouse_movements && MP_KEY_IS_MOUSE(unmod) && !force_mouse)
return;
if (unmod == MP_KEY_MOUSE_LEAVE || unmod == MP_KEY_MOUSE_ENTER) {
+ ictx->mouse_hover = unmod == MP_KEY_MOUSE_ENTER;
update_mouse_section(ictx);
- mp_input_queue_cmd(ictx, get_cmd_from_keys(ictx, NULL, code));
+
+ mp_cmd_t *cmd = get_cmd_from_keys(ictx, NULL, code);
+ if (!cmd) // queue dummy cmd so that mouse-pos can notify observers
+ cmd = mp_input_parse_cmd(ictx, bstr0("ignore"), "<internal>");
+ queue_cmd(ictx, cmd);
return;
}
double now = mp_time_sec();
@@ -727,18 +740,23 @@ static void mp_input_feed_key(struct input_ctx *ictx, int code, double scale,
if (!force_mouse && opts->doubleclick_time && MP_KEY_IS_MOUSE_BTN_DBL(unmod))
return;
int units = 1;
- if (MP_KEY_IS_WHEEL(unmod) && !process_wheel(ictx, unmod, &scale, &units))
+ if (MP_KEY_IS_WHEEL(unmod) && opts->preprocess_wheel && !process_wheel(ictx, unmod, &scale, &units))
return;
interpret_key(ictx, code, scale, units);
if (code & MP_KEY_STATE_DOWN) {
code &= ~MP_KEY_STATE_DOWN;
if (ictx->last_doubleclick_key_down == code &&
- now - ictx->last_doubleclick_time < opts->doubleclick_time / 1000.0)
+ now - ictx->last_doubleclick_time < opts->doubleclick_time / 1000.0 &&
+ code >= MP_MBTN_LEFT && code <= MP_MBTN_RIGHT)
{
- if (code >= MP_MBTN_LEFT && code <= MP_MBTN_RIGHT) {
- interpret_key(ictx, code - MP_MBTN_BASE + MP_MBTN_DBL_BASE,
- 1, 1);
- }
+ now = 0;
+ interpret_key(ictx, code - MP_MBTN_BASE + MP_MBTN_DBL_BASE,
+ 1, 1);
+ } else if (code == MP_MBTN_LEFT) {
+ // This is a mouse left botton down event which isn't part of a doubleclick.
+ // Initialize vo dragging in this case.
+ mp_cmd_t *cmd = mp_input_parse_cmd(ictx, bstr0("begin-vo-dragging"), "<internal>");
+ queue_cmd(ictx, cmd);
}
ictx->last_doubleclick_key_down = code;
ictx->last_doubleclick_time = now;
@@ -748,25 +766,31 @@ static void mp_input_feed_key(struct input_ctx *ictx, int code, double scale,
void mp_input_put_key(struct input_ctx *ictx, int code)
{
input_lock(ictx);
- mp_input_feed_key(ictx, code, 1, false);
+ feed_key(ictx, code, 1, false);
input_unlock(ictx);
}
-void mp_input_put_key_artificial(struct input_ctx *ictx, int code)
+void mp_input_put_key_artificial(struct input_ctx *ictx, int code, double value)
{
+ if (value == 0.0)
+ return;
input_lock(ictx);
- mp_input_feed_key(ictx, code, 1, true);
+ feed_key(ictx, code, value, true);
input_unlock(ictx);
}
void mp_input_put_key_utf8(struct input_ctx *ictx, int mods, struct bstr t)
{
+ if (!t.len)
+ return;
+ input_lock(ictx);
while (t.len) {
int code = bstr_decode_utf8(t, &t);
if (code < 0)
break;
- mp_input_put_key(ictx, code | mods);
+ feed_key(ictx, code | mods, 1, false);
}
+ input_unlock(ictx);
}
void mp_input_put_wheel(struct input_ctx *ictx, int direction, double value)
@@ -774,7 +798,7 @@ void mp_input_put_wheel(struct input_ctx *ictx, int direction, double value)
if (value == 0.0)
return;
input_lock(ictx);
- mp_input_feed_key(ictx, direction, value, false);
+ feed_key(ictx, direction, value, false);
input_unlock(ictx);
}
@@ -808,21 +832,11 @@ bool mp_input_vo_keyboard_enabled(struct input_ctx *ictx)
return r;
}
-void mp_input_set_mouse_pos(struct input_ctx *ictx, int x, int y)
+static void set_mouse_pos(struct input_ctx *ictx, int x, int y)
{
- input_lock(ictx);
- if (ictx->opts->enable_mouse_movements)
- mp_input_set_mouse_pos_artificial(ictx, x, y);
- input_unlock(ictx);
-}
-
-void mp_input_set_mouse_pos_artificial(struct input_ctx *ictx, int x, int y)
-{
- input_lock(ictx);
MP_TRACE(ictx, "mouse move %d/%d\n", x, y);
if (ictx->mouse_vo_x == x && ictx->mouse_vo_y == y) {
- input_unlock(ictx);
return;
}
@@ -860,10 +874,62 @@ void mp_input_set_mouse_pos_artificial(struct input_ctx *ictx, int x, int y)
queue_remove(&ictx->cmd_queue, tail);
talloc_free(tail);
}
- mp_input_queue_cmd(ictx, cmd);
+ queue_cmd(ictx, cmd);
+ }
+ }
+}
+
+void mp_input_set_mouse_pos_artificial(struct input_ctx *ictx, int x, int y)
+{
+ input_lock(ictx);
+ set_mouse_pos(ictx, x, y);
+ input_unlock(ictx);
+}
+
+void mp_input_set_mouse_pos(struct input_ctx *ictx, int x, int y)
+{
+ input_lock(ictx);
+ if (ictx->opts->enable_mouse_movements)
+ set_mouse_pos(ictx, x, y);
+ input_unlock(ictx);
+}
+
+static bool test_mouse(struct input_ctx *ictx, int x, int y, int rej_flags)
+{
+ bool res = false;
+ for (int i = 0; i < ictx->num_active_sections; i++) {
+ struct active_section *as = &ictx->active_sections[i];
+ if (as->flags & rej_flags)
+ continue;
+ struct cmd_bind_section *s = get_bind_section(ictx, bstr0(as->name));
+ if (s->mouse_area_set && test_rect(&s->mouse_area, x, y)) {
+ res = true;
+ break;
}
}
+ return res;
+}
+
+static bool test_mouse_active(struct input_ctx *ictx, int x, int y)
+{
+ return test_mouse(ictx, x, y, MP_INPUT_ALLOW_HIDE_CURSOR);
+}
+
+bool mp_input_test_mouse_active(struct input_ctx *ictx, int x, int y)
+{
+ input_lock(ictx);
+ bool res = test_mouse_active(ictx, x, y);
input_unlock(ictx);
+ return res;
+}
+
+bool mp_input_test_dragging(struct input_ctx *ictx, int x, int y)
+{
+ input_lock(ictx);
+ bool r = !ictx->opts->allow_win_drag ||
+ test_mouse(ictx, x, y, MP_INPUT_ALLOW_VO_DRAGGING);
+ input_unlock(ictx);
+ return r;
}
unsigned int mp_input_get_mouse_event_counter(struct input_ctx *ictx)
@@ -871,7 +937,7 @@ unsigned int mp_input_get_mouse_event_counter(struct input_ctx *ictx)
// Make the frontend always display the mouse cursor (as long as it's not
// forced invisible) if mouse input is desired.
input_lock(ictx);
- if (mp_input_test_mouse_active(ictx, ictx->mouse_x, ictx->mouse_y))
+ if (test_mouse_active(ictx, ictx->mouse_x, ictx->mouse_y))
ictx->mouse_event_counter++;
int ret = ictx->mouse_event_counter;
input_unlock(ictx);
@@ -890,11 +956,10 @@ static void adjust_max_wait_time(struct input_ctx *ictx, double *time)
int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd)
{
+ if (!cmd)
+ return 0;
input_lock(ictx);
- if (cmd) {
- queue_add_tail(&ictx->cmd_queue, cmd);
- mp_input_wakeup(ictx);
- }
+ queue_cmd(ictx, cmd);
input_unlock(ictx);
return 1;
}
@@ -910,19 +975,19 @@ static mp_cmd_t *check_autorepeat(struct input_ctx *ictx)
ictx->ar_state = -1; // disable
if (ictx->ar_state >= 0) {
- int64_t t = mp_time_us();
- if (ictx->last_ar + 2000000 < t)
+ int64_t t = mp_time_ns();
+ if (ictx->last_ar + MP_TIME_S_TO_NS(2) < t)
ictx->last_ar = t;
// First time : wait delay
if (ictx->ar_state == 0
- && (t - ictx->last_key_down_time) >= opts->ar_delay * 1000)
+ && (t - ictx->last_key_down_time) >= MP_TIME_MS_TO_NS(opts->ar_delay))
{
ictx->ar_state = 1;
- ictx->last_ar = ictx->last_key_down_time + opts->ar_delay * 1000;
+ ictx->last_ar = ictx->last_key_down_time + MP_TIME_MS_TO_NS(opts->ar_delay);
// Then send rate / sec event
} else if (ictx->ar_state == 1
- && (t - ictx->last_ar) >= 1000000 / opts->ar_rate) {
- ictx->last_ar += 1000000 / opts->ar_rate;
+ && (t - ictx->last_ar) >= 1e9 / opts->ar_rate) {
+ ictx->last_ar += 1e9 / opts->ar_rate;
} else {
return NULL;
}
@@ -961,11 +1026,12 @@ mp_cmd_t *mp_input_read_cmd(struct input_ctx *ictx)
return ret;
}
-void mp_input_get_mouse_pos(struct input_ctx *ictx, int *x, int *y)
+void mp_input_get_mouse_pos(struct input_ctx *ictx, int *x, int *y, int *hover)
{
input_lock(ictx);
*x = ictx->mouse_x;
*y = ictx->mouse_y;
+ *hover = ictx->mouse_hover;
input_unlock(ictx);
}
@@ -977,9 +1043,8 @@ static char *normalize_section(struct input_ctx *ictx, char *name)
return get_bind_section(ictx, bstr0(name))->section;
}
-void mp_input_disable_section(struct input_ctx *ictx, char *name)
+static void disable_section(struct input_ctx *ictx, char *name)
{
- input_lock(ictx);
name = normalize_section(ictx, name);
// Remove old section, or make sure it's on top if re-enabled
@@ -990,6 +1055,12 @@ void mp_input_disable_section(struct input_ctx *ictx, char *name)
ictx->num_active_sections, i);
}
}
+}
+
+void mp_input_disable_section(struct input_ctx *ictx, char *name)
+{
+ input_lock(ictx);
+ disable_section(ictx, name);
input_unlock(ictx);
}
@@ -998,24 +1069,20 @@ void mp_input_enable_section(struct input_ctx *ictx, char *name, int flags)
input_lock(ictx);
name = normalize_section(ictx, name);
- mp_input_disable_section(ictx, name);
+ disable_section(ictx, name);
MP_TRACE(ictx, "enable section '%s'\n", name);
- if (ictx->num_active_sections < MAX_ACTIVE_SECTIONS) {
- int top = ictx->num_active_sections;
- if (!(flags & MP_INPUT_ON_TOP)) {
- // insert before the first top entry
- for (top = 0; top < ictx->num_active_sections; top++) {
- if (ictx->active_sections[top].flags & MP_INPUT_ON_TOP)
- break;
- }
- for (int n = ictx->num_active_sections; n > top; n--)
- ictx->active_sections[n] = ictx->active_sections[n - 1];
+ int top = ictx->num_active_sections;
+ if (!(flags & MP_INPUT_ON_TOP)) {
+ // insert before the first top entry
+ for (top = 0; top < ictx->num_active_sections; top++) {
+ if (ictx->active_sections[top].flags & MP_INPUT_ON_TOP)
+ break;
}
- ictx->active_sections[top] = (struct active_section){name, flags};
- ictx->num_active_sections++;
}
+ MP_TARRAY_INSERT_AT(ictx, ictx->active_sections, ictx->num_active_sections,
+ top, (struct active_section){name, flags});
MP_TRACE(ictx, "active section stack:\n");
for (int n = 0; n < ictx->num_active_sections; n++) {
@@ -1043,38 +1110,6 @@ void mp_input_set_section_mouse_area(struct input_ctx *ictx, char *name,
input_unlock(ictx);
}
-static bool test_mouse(struct input_ctx *ictx, int x, int y, int rej_flags)
-{
- input_lock(ictx);
- bool res = false;
- for (int i = 0; i < ictx->num_active_sections; i++) {
- struct active_section *as = &ictx->active_sections[i];
- if (as->flags & rej_flags)
- continue;
- struct cmd_bind_section *s = get_bind_section(ictx, bstr0(as->name));
- if (s->mouse_area_set && test_rect(&s->mouse_area, x, y)) {
- res = true;
- break;
- }
- }
- input_unlock(ictx);
- return res;
-}
-
-bool mp_input_test_mouse_active(struct input_ctx *ictx, int x, int y)
-{
- return test_mouse(ictx, x, y, MP_INPUT_ALLOW_HIDE_CURSOR);
-}
-
-bool mp_input_test_dragging(struct input_ctx *ictx, int x, int y)
-{
- input_lock(ictx);
- bool r = !ictx->opts->allow_win_drag ||
- test_mouse(ictx, x, y, MP_INPUT_ALLOW_VO_DRAGGING);
- input_unlock(ictx);
- return r;
-}
-
static void bind_dealloc(struct cmd_bind *bind)
{
talloc_free(bind->cmd);
@@ -1115,7 +1150,7 @@ void mp_input_define_section(struct input_ctx *ictx, char *name, char *location,
parse_config(ictx, builtin, bstr0(contents), location, name);
} else {
// Disable:
- mp_input_disable_section(ictx, name);
+ disable_section(ictx, name);
}
input_unlock(ictx);
}
@@ -1126,7 +1161,7 @@ void mp_input_remove_sections_by_owner(struct input_ctx *ictx, char *owner)
for (int n = 0; n < ictx->num_sections; n++) {
struct cmd_bind_section *bs = ictx->sections[n];
if (bs->owner && owner && strcmp(bs->owner, owner) == 0) {
- mp_input_disable_section(ictx, bs->section);
+ disable_section(ictx, bs->section);
remove_binds(bs, false);
remove_binds(bs, true);
}
@@ -1268,9 +1303,9 @@ static int parse_config(struct input_ctx *ictx, bool builtin, bstr data,
return n_binds;
}
-static int parse_config_file(struct input_ctx *ictx, char *file, bool warn)
+static bool parse_config_file(struct input_ctx *ictx, char *file)
{
- int r = 0;
+ bool r = false;
void *tmp = talloc_new(NULL);
stream_t *s = NULL;
@@ -1287,7 +1322,7 @@ static int parse_config_file(struct input_ctx *ictx, char *file, bool warn)
MP_VERBOSE(ictx, "Parsing input config file %s\n", file);
int num = parse_config(ictx, false, data, file, NULL);
MP_VERBOSE(ictx, "Input config file %s parsed: %d binds\n", file, num);
- r = 1;
+ r = true;
} else {
MP_ERR(ictx, "Error reading input config file %s\n", file);
}
@@ -1312,11 +1347,12 @@ struct input_ctx *mp_input_init(struct mpv_global *global,
.opts_cache = m_config_cache_alloc(ictx, global, &input_config),
.wakeup_cb = wakeup_cb,
.wakeup_ctx = wakeup_ctx,
+ .active_sections = talloc_array(ictx, struct active_section, 0),
};
ictx->opts = ictx->opts_cache->opts;
- mpthread_mutex_init_recursive(&ictx->mutex);
+ mp_mutex_init(&ictx->mutex);
// Setup default section, so that it does nothing.
mp_input_enable_section(ictx, NULL, MP_INPUT_ALLOW_VO_DRAGGING |
@@ -1359,7 +1395,7 @@ void mp_input_load_config(struct input_ctx *ictx)
// "Uncomment" the default key bindings in etc/input.conf and add them.
// All lines that do not start with '# ' are parsed.
bstr builtin = bstr0(builtin_input_conf);
- while (builtin.len) {
+ while (ictx->opts->builtin_bindings && builtin.len) {
bstr line = bstr_getline(builtin, &builtin);
bstr_eatstart0(&line, "#");
if (!bstr_startswith0(line, " "))
@@ -1368,31 +1404,33 @@ void mp_input_load_config(struct input_ctx *ictx)
bool config_ok = false;
if (ictx->opts->config_file && ictx->opts->config_file[0])
- config_ok = parse_config_file(ictx, ictx->opts->config_file, true);
+ config_ok = parse_config_file(ictx, ictx->opts->config_file);
if (!config_ok) {
// Try global conf dir
void *tmp = talloc_new(NULL);
char **files = mp_find_all_config_files(tmp, ictx->global, "input.conf");
for (int n = 0; files && files[n]; n++)
- parse_config_file(ictx, files[n], false);
+ parse_config_file(ictx, files[n]);
talloc_free(tmp);
}
-#if HAVE_WIN32_PIPES
- char *ifile;
- mp_read_option_raw(ictx->global, "input-file", &m_option_type_string, &ifile);
- if (ifile && ifile[0])
- mp_input_pipe_add(ictx, ifile);
- talloc_free(ifile);
-#endif
+ bool use_gamepad = ictx->opts->use_gamepad;
+ input_unlock(ictx);
#if HAVE_SDL2_GAMEPAD
- if (ictx->opts->use_gamepad) {
+ if (use_gamepad)
mp_input_sdl_gamepad_add(ictx);
- }
+#else
+ (void)use_gamepad;
#endif
+}
+bool mp_input_load_config_file(struct input_ctx *ictx, char *file)
+{
+ input_lock(ictx);
+ bool result = parse_config_file(ictx, file);
input_unlock(ictx);
+ return result;
}
static void clear_queue(struct cmd_queue *queue)
@@ -1416,7 +1454,7 @@ void mp_input_uninit(struct input_ctx *ictx)
close_input_sources(ictx);
clear_queue(&ictx->cmd_queue);
talloc_free(ictx->current_down_cmd);
- pthread_mutex_destroy(&ictx->mutex);
+ mp_mutex_destroy(&ictx->mutex);
talloc_free(ictx);
}
@@ -1444,11 +1482,14 @@ struct mp_cmd *mp_input_parse_cmd(struct input_ctx *ictx, bstr str,
void mp_input_run_cmd(struct input_ctx *ictx, const char **cmd)
{
- mp_input_queue_cmd(ictx, mp_input_parse_cmd_strv(ictx->log, cmd));
+ input_lock(ictx);
+ queue_cmd(ictx, mp_input_parse_cmd_strv(ictx->log, cmd));
+ input_unlock(ictx);
}
void mp_input_bind_key(struct input_ctx *ictx, int key, bstr command)
{
+ input_lock(ictx);
struct cmd_bind_section *bs = get_bind_section(ictx, (bstr){0});
struct cmd_bind *bind = NULL;
@@ -1483,6 +1524,7 @@ void mp_input_bind_key(struct input_ctx *ictx, int key, bstr command)
bind->cmd, bind->location);
talloc_free(s);
}
+ input_unlock(ictx);
}
struct mpv_node mp_input_get_bindings(struct input_ctx *ictx)
@@ -1536,7 +1578,7 @@ struct mpv_node mp_input_get_bindings(struct input_ctx *ictx)
}
struct mp_input_src_internal {
- pthread_t thread;
+ mp_thread thread;
bool thread_running;
bool init_done;
@@ -1545,7 +1587,7 @@ struct mp_input_src_internal {
bool drop;
};
-static struct mp_input_src *mp_input_add_src(struct input_ctx *ictx)
+static struct mp_input_src *input_add_src(struct input_ctx *ictx)
{
input_lock(ictx);
if (ictx->num_sources == MP_MAX_SOURCES) {
@@ -1569,7 +1611,7 @@ static struct mp_input_src *mp_input_add_src(struct input_ctx *ictx)
return src;
}
-static void mp_inp