diff options
Diffstat (limited to 'input')
-rw-r--r-- | input/input.c | 111 | ||||
-rw-r--r-- | input/input.h | 10 | ||||
-rw-r--r-- | input/keycodes.h | 2 |
3 files changed, 123 insertions, 0 deletions
diff --git a/input/input.c b/input/input.c index b24e82fe50..9890a0252b 100644 --- a/input/input.c +++ b/input/input.c @@ -93,6 +93,11 @@ struct wheel_state { double unit_accum; }; +struct touch_point { + int id; + int x, y; +}; + struct input_ctx { mp_mutex mutex; struct mp_log *log; @@ -143,6 +148,10 @@ struct input_ctx { struct active_section *active_sections; int num_active_sections; + // List currently active touch points + struct touch_point *touch_points; + int num_touch_points; + unsigned int mouse_event_counter; struct mp_input_src *sources[MP_MAX_SOURCES]; @@ -178,6 +187,7 @@ struct input_opts { bool test; bool allow_win_drag; bool preprocess_wheel; + bool touch_emulate_mouse; }; const struct m_sub_options input_config = { @@ -198,6 +208,7 @@ const struct m_sub_options input_config = { {"input-vo-keyboard", OPT_BOOL(vo_key_input)}, {"input-media-keys", OPT_BOOL(use_media_keys)}, {"input-preprocess-wheel", OPT_BOOL(preprocess_wheel)}, + {"input-touch-emulate-mouse", OPT_BOOL(touch_emulate_mouse)}, #if HAVE_SDL2_GAMEPAD {"input-gamepad", OPT_BOOL(use_gamepad)}, #endif @@ -218,6 +229,7 @@ const struct m_sub_options input_config = { .vo_key_input = true, .allow_win_drag = true, .preprocess_wheel = true, + .touch_emulate_mouse = true, }, .change_flags = UPDATE_INPUT, }; @@ -723,6 +735,11 @@ static void feed_key(struct input_ctx *ictx, int code, double scale, release_down_cmd(ictx, false); return; } + if (code == MP_TOUCH_RELEASE_ALL) { + MP_TRACE(ictx, "release all touch\n"); + ictx->num_touch_points = 0; + return; + } if (!opts->enable_mouse_movements && MP_KEY_IS_MOUSE(unmod) && !force_mouse) return; if (unmod == MP_KEY_MOUSE_LEAVE || unmod == MP_KEY_MOUSE_ENTER) { @@ -894,6 +911,99 @@ void mp_input_set_mouse_pos(struct input_ctx *ictx, int x, int y) input_unlock(ictx); } +static int find_touch_point_index(struct input_ctx *ictx, int id) +{ + for (int i = 0; i < ictx->num_touch_points; i++) { + if (ictx->touch_points[i].id == id) + return i; + } + return -1; +} + +static void notify_touch_update(struct input_ctx *ictx) +{ + // queue dummy cmd so that touch-pos can notify observers + mp_cmd_t *cmd = mp_input_parse_cmd(ictx, bstr0("ignore"), "<internal>"); + queue_cmd(ictx, cmd); +} + +static void update_touch_point(struct input_ctx *ictx, int idx, int id, int x, int y) +{ + MP_TRACE(ictx, "Touch point %d update (id %d) %d/%d\n", + idx, id, x, y); + if (ictx->touch_points[idx].x == x && ictx->touch_points[idx].y == y) + return; + ictx->touch_points[idx].x = x; + ictx->touch_points[idx].y = y; + // Emulate mouse input from the primary touch point (the first one added) + if (ictx->opts->touch_emulate_mouse && idx == 0) + set_mouse_pos(ictx, x, y); + notify_touch_update(ictx); +} + +void mp_input_add_touch_point(struct input_ctx *ictx, int id, int x, int y) +{ + input_lock(ictx); + int idx = find_touch_point_index(ictx, id); + if (idx != -1) { + MP_WARN(ictx, "Touch point %d (id %d) already exists! Treat as update.\n", + idx, id); + update_touch_point(ictx, idx, id, x, y); + } else { + MP_TRACE(ictx, "Touch point %d add (id %d) %d/%d\n", + ictx->num_touch_points, id, x, y); + MP_TARRAY_APPEND(ictx, ictx->touch_points, ictx->num_touch_points, + (struct touch_point){id, x, y}); + // Emulate MBTN_LEFT down if this is the only touch point + if (ictx->opts->touch_emulate_mouse && ictx->num_touch_points == 1) { + set_mouse_pos(ictx, x, y); + feed_key(ictx, MP_MBTN_LEFT | MP_KEY_STATE_DOWN, 1, false); + } + notify_touch_update(ictx); + } + input_unlock(ictx); +} + +void mp_input_update_touch_point(struct input_ctx *ictx, int id, int x, int y) +{ + input_lock(ictx); + int idx = find_touch_point_index(ictx, id); + if (idx != -1) { + update_touch_point(ictx, idx, id, x, y); + } else { + MP_WARN(ictx, "Touch point id %d does not exist!\n", id); + } + input_unlock(ictx); +} + +void mp_input_remove_touch_point(struct input_ctx *ictx, int id) +{ + input_lock(ictx); + int idx = find_touch_point_index(ictx, id); + if (idx != -1) { + MP_TRACE(ictx, "Touch point %d remove (id %d)\n", idx, id); + MP_TARRAY_REMOVE_AT(ictx->touch_points, ictx->num_touch_points, idx); + // Emulate MBTN_LEFT up if there are no touch points left + if (ictx->opts->touch_emulate_mouse && ictx->num_touch_points == 0) + feed_key(ictx, MP_MBTN_LEFT | MP_KEY_STATE_UP, 1, false); + notify_touch_update(ictx); + } + input_unlock(ictx); +} + +int mp_input_get_touch_pos(struct input_ctx *ictx, int count, int *x, int *y, int *id) +{ + input_lock(ictx); + int num_touch_points = ictx->num_touch_points; + for (int i = 0; i < MPMIN(num_touch_points, count); i++) { + x[i] = ictx->touch_points[i].x; + y[i] = ictx->touch_points[i].y; + id[i] = ictx->touch_points[i].id; + } + input_unlock(ictx); + return num_touch_points; +} + static bool test_mouse(struct input_ctx *ictx, int x, int y, int rej_flags) { bool res = false; @@ -1348,6 +1458,7 @@ struct input_ctx *mp_input_init(struct mpv_global *global, .wakeup_cb = wakeup_cb, .wakeup_ctx = wakeup_ctx, .active_sections = talloc_array(ictx, struct active_section, 0), + .touch_points = talloc_array(ictx, struct touch_point, 0), }; ictx->opts = ictx->opts_cache->opts; diff --git a/input/input.h b/input/input.h index 7f6707eeca..aafabdb9cb 100644 --- a/input/input.h +++ b/input/input.h @@ -102,6 +102,16 @@ void mp_input_set_mouse_pos_artificial(struct input_ctx *ictx, int x, int y); void mp_input_get_mouse_pos(struct input_ctx *ictx, int *x, int *y, int *hover); +// Add/Update/Remove a touch point (in window coordinates). +void mp_input_add_touch_point(struct input_ctx *ictx, int id, int x, int y); +void mp_input_update_touch_point(struct input_ctx *ictx, int id, int x, int y); +void mp_input_remove_touch_point(struct input_ctx *ictx, int id); + +// Get the positions of the touch points. xs and ys are arrays of at least +// count elements. ids is an array of at least count elements to uniquely +// identify touch points. Return the current number of touch points. +int mp_input_get_touch_pos(struct input_ctx *ictx, int count, int *xs, int *ys, int *ids); + // Return whether we want/accept mouse input. bool mp_input_mouse_enabled(struct input_ctx *ictx); diff --git a/input/keycodes.h b/input/keycodes.h index 1a21a3c89f..2e63df344f 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -216,6 +216,8 @@ #define MP_KEY_ANY_UNICODE (MP_KEY_INTERN+5) // For mp_input_put_key(): release all keys that are down. #define MP_INPUT_RELEASE_ALL (MP_KEY_INTERN+6) +// For mp_input_put_key(): release all touch points. +#define MP_TOUCH_RELEASE_ALL (MP_KEY_INTERN+7) // Emit a command even on key-up (normally key-up is ignored). This means by // default they binding will be triggered on key-up instead of key-down. |