mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-22 10:57:08 +00:00
wayland: move tablet tool handling to mpv input system
Upgrade tablet input to first class citizen similar like touch input, but more simple since use case for now is mouse emulation only. Keep state for coordinates and in-proximity. Introduce property for disabling tablet input. Introduce Client-API property `tablet-pos`.
This commit is contained in:
127
input/input.c
127
input/input.c
@@ -158,6 +158,14 @@ struct input_ctx {
|
||||
struct touch_point *touch_points;
|
||||
int num_touch_points;
|
||||
|
||||
int tablet_x, tablet_y;
|
||||
// Indicates tablet tools in proximity
|
||||
bool tablet_tool_in_proximity;
|
||||
bool tablet_tool_down;
|
||||
bool tablet_tool_stylus_btn1_pressed;
|
||||
bool tablet_tool_stylus_btn2_pressed;
|
||||
bool tablet_tool_stylus_btn3_pressed;
|
||||
|
||||
unsigned int mouse_event_counter;
|
||||
|
||||
struct mp_input_src *sources[MP_MAX_SOURCES];
|
||||
@@ -197,6 +205,7 @@ struct input_opts {
|
||||
bool allow_win_drag;
|
||||
bool preprocess_wheel;
|
||||
bool touch_emulate_mouse;
|
||||
bool tablet_emulate_mouse;
|
||||
};
|
||||
|
||||
const struct m_sub_options input_config = {
|
||||
@@ -219,6 +228,7 @@ const struct m_sub_options input_config = {
|
||||
{"input-media-keys", OPT_BOOL(use_media_keys)},
|
||||
{"input-preprocess-wheel", OPT_BOOL(preprocess_wheel)},
|
||||
{"input-touch-emulate-mouse", OPT_BOOL(touch_emulate_mouse)},
|
||||
{"input-tablet-emulate-mouse", OPT_BOOL(tablet_emulate_mouse)},
|
||||
{"input-dragging-deadzone", OPT_INT(dragging_deadzone)},
|
||||
#if HAVE_SDL2_GAMEPAD
|
||||
{"input-gamepad", OPT_BOOL(use_gamepad)},
|
||||
@@ -243,6 +253,7 @@ const struct m_sub_options input_config = {
|
||||
.allow_win_drag = true,
|
||||
.preprocess_wheel = true,
|
||||
.touch_emulate_mouse = true,
|
||||
.tablet_emulate_mouse = true,
|
||||
},
|
||||
.change_flags = UPDATE_INPUT,
|
||||
};
|
||||
@@ -1066,6 +1077,122 @@ int mp_input_get_touch_pos(struct input_ctx *ictx, int count, int *x, int *y, in
|
||||
return num_touch_points;
|
||||
}
|
||||
|
||||
static void notify_tablet_update(struct input_ctx *ictx)
|
||||
{
|
||||
// queue dummy cmd so that tablet-pos can notify observers
|
||||
mp_cmd_t *cmd = mp_input_parse_cmd(ictx, bstr0("ignore"), "<internal>");
|
||||
if (cmd)
|
||||
cmd->notify_event = true;
|
||||
queue_cmd(ictx, cmd);
|
||||
}
|
||||
|
||||
void mp_input_set_tablet_tool_in_proximity(struct input_ctx *ictx, bool in_proximity)
|
||||
{
|
||||
MP_TRACE(ictx, "tablet tool proximity %s\n", in_proximity ? "in" : "out");
|
||||
|
||||
input_lock(ictx);
|
||||
ictx->tablet_tool_in_proximity = in_proximity;
|
||||
if (!in_proximity) {
|
||||
ictx->tablet_tool_down = false;
|
||||
ictx->tablet_tool_stylus_btn1_pressed = false;
|
||||
ictx->tablet_tool_stylus_btn2_pressed = false;
|
||||
ictx->tablet_tool_stylus_btn3_pressed = false;
|
||||
}
|
||||
notify_tablet_update(ictx);
|
||||
input_unlock(ictx);
|
||||
}
|
||||
|
||||
void mp_input_tablet_tool_down(struct input_ctx *ictx)
|
||||
{
|
||||
MP_TRACE(ictx, "tablet tool down\n");
|
||||
|
||||
input_lock(ictx);
|
||||
ictx->tablet_tool_down = true;
|
||||
if (ictx->opts->tablet_emulate_mouse && ictx->tablet_tool_in_proximity)
|
||||
feed_key(ictx, MP_MBTN_LEFT | MP_KEY_STATE_DOWN, 1, false);
|
||||
|
||||
notify_tablet_update(ictx);
|
||||
input_unlock(ictx);
|
||||
}
|
||||
|
||||
void mp_input_tablet_tool_up(struct input_ctx *ictx)
|
||||
{
|
||||
MP_TRACE(ictx, "tablet tool up\n");
|
||||
|
||||
input_lock(ictx);
|
||||
ictx->tablet_tool_down = false;
|
||||
if (ictx->opts->tablet_emulate_mouse && ictx->tablet_tool_in_proximity)
|
||||
feed_key(ictx, MP_MBTN_LEFT | MP_KEY_STATE_UP, 1, false);
|
||||
|
||||
notify_tablet_update(ictx);
|
||||
input_unlock(ictx);
|
||||
}
|
||||
|
||||
void mp_input_tablet_tool_button(struct input_ctx *ictx, int button, int state)
|
||||
{
|
||||
char *key = mp_input_get_key_name(button);
|
||||
MP_TRACE(ictx, "tablet tool button %s %s%s \n",
|
||||
key,
|
||||
(state & MP_KEY_STATE_DOWN) ? "pressed" : "",
|
||||
(state & MP_KEY_STATE_UP) ? "released" : "");
|
||||
|
||||
input_lock(ictx);
|
||||
|
||||
switch (button) {
|
||||
case MP_KEY_TABLET_TOOL_STYLUS_BTN1:
|
||||
ictx->tablet_tool_stylus_btn1_pressed = state == MP_KEY_STATE_DOWN;
|
||||
button = MP_MBTN_MID;
|
||||
break;
|
||||
case MP_KEY_TABLET_TOOL_STYLUS_BTN2:
|
||||
ictx->tablet_tool_stylus_btn2_pressed = state == MP_KEY_STATE_DOWN;
|
||||
button = MP_MBTN_RIGHT;
|
||||
break;
|
||||
case MP_KEY_TABLET_TOOL_STYLUS_BTN3:
|
||||
ictx->tablet_tool_stylus_btn3_pressed = state == MP_KEY_STATE_DOWN;
|
||||
button = MP_MBTN_BACK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ictx->opts->tablet_emulate_mouse && ictx->tablet_tool_in_proximity && button)
|
||||
feed_key(ictx, button | state, 1, false);
|
||||
|
||||
notify_tablet_update(ictx);
|
||||
input_unlock(ictx);
|
||||
}
|
||||
|
||||
void mp_input_set_tablet_pos(struct input_ctx *ictx, int x, int y, bool quiet)
|
||||
{
|
||||
MP_TRACE(ictx, "tablet tool position %d/%d \n", x, y);
|
||||
|
||||
input_lock(ictx);
|
||||
ictx->tablet_x = x;
|
||||
ictx->tablet_y = y;
|
||||
if (ictx->opts->tablet_emulate_mouse && ictx->tablet_tool_in_proximity)
|
||||
set_mouse_pos(ictx, x, y, quiet);
|
||||
|
||||
notify_tablet_update(ictx);
|
||||
input_unlock(ictx);
|
||||
}
|
||||
|
||||
void mp_input_get_tablet_pos(struct input_ctx *ictx, int *x, int *y,
|
||||
bool *tool_in_proximity, bool *tool_down,
|
||||
bool *tool_stylus_btn1_pressed,
|
||||
bool *tool_stylus_btn2_pressed,
|
||||
bool *tool_stylus_btn3_pressed)
|
||||
{
|
||||
input_lock(ictx);
|
||||
*x = ictx->tablet_x;
|
||||
*y = ictx->tablet_y;
|
||||
*tool_in_proximity = ictx->tablet_tool_in_proximity;
|
||||
*tool_down = ictx->tablet_tool_down;
|
||||
*tool_stylus_btn1_pressed = ictx->tablet_tool_stylus_btn1_pressed;
|
||||
*tool_stylus_btn2_pressed = ictx->tablet_tool_stylus_btn2_pressed;
|
||||
*tool_stylus_btn3_pressed = ictx->tablet_tool_stylus_btn3_pressed;
|
||||
input_unlock(ictx);
|
||||
}
|
||||
|
||||
static bool test_mouse(struct input_ctx *ictx, int x, int y, int rej_flags)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
@@ -112,6 +112,22 @@ void mp_input_remove_touch_point(struct input_ctx *ictx, int id);
|
||||
// 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);
|
||||
|
||||
// Set tablet tool proximity and process tool tip down/up and buttons
|
||||
void mp_input_set_tablet_tool_in_proximity(struct input_ctx *ictx, bool in_proximity);
|
||||
void mp_input_tablet_tool_down(struct input_ctx *ictx);
|
||||
void mp_input_tablet_tool_up(struct input_ctx *ictx);
|
||||
void mp_input_tablet_tool_button(struct input_ctx *ictx, int button, int state);
|
||||
|
||||
// Update tablet position (in window coordinates).
|
||||
void mp_input_set_tablet_pos(struct input_ctx *ictx, int x, int y, bool quiet);
|
||||
|
||||
void mp_input_get_tablet_pos(struct input_ctx *ictx, int *x, int *y,
|
||||
bool *tool_in_proximity,
|
||||
bool *tool_down,
|
||||
bool *tool_stylus_btn1_pressed,
|
||||
bool *tool_stylus_btn2_pressed,
|
||||
bool *tool_stylus_btn3_pressed);
|
||||
|
||||
// Return whether we want/accept mouse input.
|
||||
bool mp_input_mouse_enabled(struct input_ctx *ictx);
|
||||
|
||||
|
||||
@@ -127,6 +127,11 @@ static const struct key_name key_names[] = {
|
||||
{ MP_MBTN_MID_DBL, "MBTN_MID_DBL" },
|
||||
{ MP_MBTN_RIGHT_DBL, "MBTN_RIGHT_DBL" },
|
||||
|
||||
{ MP_KEY_TABLET_TOOL_TIP, "TABLET_TOOL_TIP" },
|
||||
{ MP_KEY_TABLET_TOOL_STYLUS_BTN1, "TABLET_TOOL_STYLUS_BTN1" },
|
||||
{ MP_KEY_TABLET_TOOL_STYLUS_BTN2, "TABLET_TOOL_STYLUS_BTN2" },
|
||||
{ MP_KEY_TABLET_TOOL_STYLUS_BTN3, "TABLET_TOOL_STYLUS_BTN3" },
|
||||
|
||||
{ MP_KEY_GAMEPAD_ACTION_DOWN, "GAMEPAD_ACTION_DOWN" },
|
||||
{ MP_KEY_GAMEPAD_ACTION_RIGHT, "GAMEPAD_ACTION_RIGHT" },
|
||||
{ MP_KEY_GAMEPAD_ACTION_LEFT, "GAMEPAD_ACTION_LEFT" },
|
||||
|
||||
@@ -161,6 +161,13 @@
|
||||
|
||||
#define MP_KEY_MOUSE_BTN_COUNT (MP_MBTN_END - MP_MBTN_BASE)
|
||||
|
||||
/* tablet buttons */
|
||||
#define MP_KEY_TABLET (MP_KEY_BASE+0xD0)
|
||||
#define MP_KEY_TABLET_TOOL_TIP (MP_KEY_TABLET+1)
|
||||
#define MP_KEY_TABLET_TOOL_STYLUS_BTN1 (MP_KEY_TABLET+2)
|
||||
#define MP_KEY_TABLET_TOOL_STYLUS_BTN2 (MP_KEY_TABLET+3)
|
||||
#define MP_KEY_TABLET_TOOL_STYLUS_BTN3 (MP_KEY_TABLET+4)
|
||||
|
||||
/* game controller keys */
|
||||
#define MP_KEY_GAMEPAD (MP_KEY_BASE+0xF0)
|
||||
#define MP_KEY_GAMEPAD_ACTION_DOWN (MP_KEY_GAMEPAD+0)
|
||||
|
||||
@@ -3124,6 +3124,43 @@ static int mp_property_touch_pos(void *ctx, struct m_property *prop,
|
||||
get_touch_pos, (void *)pos);
|
||||
}
|
||||
|
||||
static int mp_property_tablet_pos(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
{
|
||||
MPContext *mpctx = ctx;
|
||||
|
||||
switch (action) {
|
||||
case M_PROPERTY_GET_TYPE:
|
||||
*(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_NODE};
|
||||
return M_PROPERTY_OK;
|
||||
|
||||
case M_PROPERTY_GET: {
|
||||
int xs, ys;
|
||||
bool tool_in_proximity;
|
||||
bool tool_down;
|
||||
bool tool_stylus_btn1_pressed;
|
||||
bool tool_stylus_btn2_pressed;
|
||||
bool tool_stylus_btn3_pressed;
|
||||
mp_input_get_tablet_pos(mpctx->input, &xs, &ys, &tool_in_proximity, &tool_down,
|
||||
&tool_stylus_btn1_pressed, &tool_stylus_btn2_pressed, &tool_stylus_btn3_pressed);
|
||||
|
||||
struct mpv_node node;
|
||||
node_init(&node, MPV_FORMAT_NODE_MAP, NULL);
|
||||
node_map_add_int64(&node, "x", xs);
|
||||
node_map_add_int64(&node, "y", ys);
|
||||
node_map_add_flag(&node, "tool-in-proximity", tool_in_proximity);
|
||||
node_map_add_string(&node, "tool-tip", tool_down ? "down" : "up");
|
||||
node_map_add_string(&node, "tool-stylus-btn1", tool_stylus_btn1_pressed ? "pressed" : "released");
|
||||
node_map_add_string(&node, "tool-stylus-btn2", tool_stylus_btn2_pressed ? "pressed" : "released");
|
||||
node_map_add_string(&node, "tool-stylus-btn3", tool_stylus_btn3_pressed ? "pressed" : "released");
|
||||
*(struct mpv_node *)arg = node;
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/// Video fps (RO)
|
||||
static int mp_property_fps(void *ctx, struct m_property *prop,
|
||||
int action, void *arg)
|
||||
@@ -4416,6 +4453,7 @@ static const struct m_property mp_properties_base[] = {
|
||||
|
||||
{"mouse-pos", mp_property_mouse_pos},
|
||||
{"touch-pos", mp_property_touch_pos},
|
||||
{"tablet-pos", mp_property_tablet_pos},
|
||||
|
||||
// Subs
|
||||
{"sid", mp_property_switch_track, .priv = (void *)(const int[]){0, STREAM_SUB}},
|
||||
@@ -4553,7 +4591,7 @@ static const char *const *const mp_event_property_change[] = {
|
||||
E(MP_EVENT_CHANGE_PLAYLIST, "playlist", "playlist-pos", "playlist-pos-1",
|
||||
"playlist-count", "playlist/count", "playlist-current-pos",
|
||||
"playlist-playing-pos"),
|
||||
E(MP_EVENT_INPUT_PROCESSED, "mouse-pos", "touch-pos"),
|
||||
E(MP_EVENT_INPUT_PROCESSED, "mouse-pos", "touch-pos", "tablet-pos"),
|
||||
E(MP_EVENT_CORE_IDLE, "core-idle", "eof-reached"),
|
||||
};
|
||||
#undef E
|
||||
|
||||
@@ -698,11 +698,14 @@ static void tablet_tool_handle_proximity_in(void *data,
|
||||
struct vo_wayland_tablet_tool *tablet_tool = data;
|
||||
tablet_tool->proximity_serial = serial;
|
||||
set_cursor_visibility(tablet_tool->seat, true);
|
||||
mp_input_set_tablet_tool_in_proximity(tablet_tool->wl->vo->input_ctx, true);
|
||||
}
|
||||
|
||||
static void tablet_tool_handle_proximity_out(void *data,
|
||||
struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2)
|
||||
{
|
||||
struct vo_wayland_tablet_tool *tablet_tool = data;
|
||||
mp_input_set_tablet_tool_in_proximity(tablet_tool->wl->vo->input_ctx, false);
|
||||
}
|
||||
|
||||
static void tablet_tool_handle_down(void *data,
|
||||
@@ -724,7 +727,7 @@ static void tablet_tool_handle_down(void *data,
|
||||
|
||||
tablet_tool->seat->pointer_button_serial = serial;
|
||||
wl->last_button_seat = tablet_tool->seat;
|
||||
mp_input_put_key(tablet_tool->wl->vo->input_ctx, MP_MBTN_LEFT | MP_KEY_STATE_DOWN | tablet_tool->seat->mpmod);
|
||||
mp_input_tablet_tool_down(tablet_tool->wl->vo->input_ctx);
|
||||
}
|
||||
|
||||
static void tablet_tool_handle_up(void *data,
|
||||
@@ -732,7 +735,7 @@ static void tablet_tool_handle_up(void *data,
|
||||
{
|
||||
struct vo_wayland_tablet_tool *tablet_tool = data;
|
||||
tablet_tool->seat->wl->last_button_seat = NULL;
|
||||
mp_input_put_key(tablet_tool->wl->vo->input_ctx, MP_MBTN_LEFT | MP_KEY_STATE_UP | tablet_tool->seat->mpmod);
|
||||
mp_input_tablet_tool_up(tablet_tool->wl->vo->input_ctx);
|
||||
}
|
||||
|
||||
static void tablet_tool_handle_motion(void *data,
|
||||
@@ -746,7 +749,7 @@ static void tablet_tool_handle_motion(void *data,
|
||||
wl->mouse_x = handle_round(wl->scaling, wl_fixed_to_int(x));
|
||||
wl->mouse_y = handle_round(wl->scaling, wl_fixed_to_int(y));
|
||||
|
||||
mp_input_set_mouse_pos(wl->vo->input_ctx, wl->mouse_x, wl->mouse_y,
|
||||
mp_input_set_tablet_pos(wl->vo->input_ctx, wl->mouse_x, wl->mouse_y,
|
||||
wl->toplevel_configured);
|
||||
wl->toplevel_configured = false;
|
||||
}
|
||||
@@ -799,26 +802,25 @@ static void tablet_tool_handle_button(void *data,
|
||||
tablet_tool->seat->last_serial = serial;
|
||||
|
||||
switch (button) {
|
||||
case BTN_STYLUS:
|
||||
button = MP_MBTN_MID;
|
||||
break;
|
||||
case BTN_STYLUS2:
|
||||
button = MP_MBTN_RIGHT;
|
||||
break;
|
||||
case BTN_STYLUS3:
|
||||
button = MP_MBTN_BACK;
|
||||
break;
|
||||
default:
|
||||
button = 0;
|
||||
break;
|
||||
case BTN_STYLUS:
|
||||
button = MP_KEY_TABLET_TOOL_STYLUS_BTN1;
|
||||
break;
|
||||
case BTN_STYLUS2:
|
||||
button = MP_KEY_TABLET_TOOL_STYLUS_BTN2;
|
||||
break;
|
||||
case BTN_STYLUS3:
|
||||
button = MP_KEY_TABLET_TOOL_STYLUS_BTN3;
|
||||
break;
|
||||
default:
|
||||
button = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
state = state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_PRESSED
|
||||
? MP_KEY_STATE_DOWN
|
||||
: MP_KEY_STATE_UP;
|
||||
|
||||
if (button)
|
||||
mp_input_put_key(tablet_tool->wl->vo->input_ctx, button | state | tablet_tool->seat->mpmod);
|
||||
mp_input_tablet_tool_button(tablet_tool->wl->vo->input_ctx, button, state);
|
||||
}
|
||||
|
||||
static void tablet_tool_handle_frame(void *data,
|
||||
|
||||
Reference in New Issue
Block a user