diff --git a/input/input.c b/input/input.c index 307b3416f6..412c6db319 100644 --- a/input/input.c +++ b/input/input.c @@ -78,6 +78,7 @@ struct cmd_bind_section { }; #define MP_MAX_SOURCES 10 +#define MP_MAX_TABLET_PAD_BUTTONS 10 struct active_section { bstr name; @@ -159,12 +160,15 @@ struct input_ctx { int num_touch_points; int tablet_x, tablet_y; - // Indicates tablet tools in proximity + // Indicates tablet tools in proximity / close to tablet surface 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; + bool tablet_pad_focus; + bool tablet_pad_buttons_pressed[MP_MAX_TABLET_PAD_BUTTONS]; + int tablet_pad_buttons; unsigned int mouse_event_counter; @@ -1162,6 +1166,38 @@ void mp_input_tablet_tool_button(struct input_ctx *ictx, int button, int state) input_unlock(ictx); } +void mp_input_set_tablet_pad_focus(struct input_ctx *ictx, bool focus, int buttons) +{ + MP_TRACE(ictx, "tablet pad focus %s\n", focus ? "enter" : "leave"); + + input_lock(ictx); + ictx->tablet_pad_focus = focus; + if (!focus) { + for (int i = 0; i < ictx->tablet_pad_buttons; i++) + ictx->tablet_pad_buttons_pressed[i] = false; + } + ictx->tablet_pad_buttons = buttons; + notify_tablet_update(ictx); + input_unlock(ictx); +} + +void mp_input_tablet_pad_button(struct input_ctx *ictx, int button, int state) +{ + MP_TRACE(ictx, "tablet pad button %d %s%s \n", + button, + (state & MP_KEY_STATE_DOWN) ? "pressed" : "", + (state & MP_KEY_STATE_UP) ? "released" : ""); + + input_lock(ictx); + if (button < MP_MAX_TABLET_PAD_BUTTONS) + ictx->tablet_pad_buttons_pressed[button] = state == MP_KEY_STATE_DOWN; + else + MP_WARN(ictx, "Tablet pad button %d outside of range!\n", button); + + 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); @@ -1180,7 +1216,10 @@ 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) + bool *tool_stylus_btn3_pressed, + bool *pad_focus, + bool **pad_buttons_pressed, + int *pad_buttons) { input_lock(ictx); *x = ictx->tablet_x; @@ -1190,6 +1229,9 @@ void mp_input_get_tablet_pos(struct input_ctx *ictx, int *x, int *y, *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; + *pad_focus = ictx->tablet_pad_focus; + *pad_buttons_pressed = ictx->tablet_pad_buttons_pressed; + *pad_buttons = ictx->tablet_pad_buttons; input_unlock(ictx); } diff --git a/input/input.h b/input/input.h index 8f89683445..01b0d0c0b9 100644 --- a/input/input.h +++ b/input/input.h @@ -117,6 +117,8 @@ void mp_input_set_tablet_tool_in_proximity(struct input_ctx *ictx, bool in_proxi 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); +void mp_input_set_tablet_pad_focus(struct input_ctx *ictx, bool focus, int buttons); +void mp_input_tablet_pad_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); @@ -126,7 +128,10 @@ void mp_input_get_tablet_pos(struct input_ctx *ictx, int *x, int *y, bool *tool_down, bool *tool_stylus_btn1_pressed, bool *tool_stylus_btn2_pressed, - bool *tool_stylus_btn3_pressed); + bool *tool_stylus_btn3_pressed, + bool *pad_focus, + bool **pad_buttons_pressed, + int *pad_buttons); // Return whether we want/accept mouse input. bool mp_input_mouse_enabled(struct input_ctx *ictx); diff --git a/player/command.c b/player/command.c index 085eafe56d..999e74d4d7 100644 --- a/player/command.c +++ b/player/command.c @@ -3141,8 +3141,12 @@ static int mp_property_tablet_pos(void *ctx, struct m_property *prop, bool tool_stylus_btn1_pressed; bool tool_stylus_btn2_pressed; bool tool_stylus_btn3_pressed; + bool pad_focus; + bool *pad_buttons_pressed; + int pad_buttons; 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); + &tool_stylus_btn1_pressed, &tool_stylus_btn2_pressed, &tool_stylus_btn3_pressed, + &pad_focus, &pad_buttons_pressed, &pad_buttons); struct mpv_node node; node_init(&node, MPV_FORMAT_NODE_MAP, NULL); @@ -3153,6 +3157,14 @@ static int mp_property_tablet_pos(void *ctx, struct m_property *prop, 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"); + node_map_add_flag(&node, "pad-focus", pad_focus); + + struct mpv_node *args = node_map_add(&node, "pad-btns", MPV_FORMAT_NODE_MAP); + for (int i = 0; i < pad_buttons; i++) { + char *name = mp_tprintf(2, "%d", i + 1); + node_map_add_string(args, name, pad_buttons_pressed[i] ? "pressed" : "released"); + } + *(struct mpv_node *)arg = node; return M_PROPERTY_OK; } diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 33ff3ee364..960433e544 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -248,6 +248,7 @@ struct vo_wayland_tablet_pad { struct vo_wayland_state *wl; struct vo_wayland_seat *seat; struct zwp_tablet_pad_v2 *tablet_pad; + uint32_t buttons; // number of buttons on pad struct wl_list tablet_pad_group_list; struct wl_list link; }; @@ -943,6 +944,11 @@ static void tablet_pad_handle_buttons(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t buttons) { + struct vo_wayland_tablet_pad *tablet_pad = data; + struct vo_wayland_state *wl = tablet_pad->wl; + + MP_VERBOSE(wl, " %i buttons\n", buttons); + tablet_pad->buttons = buttons; } static void tablet_pad_handle_done(void *data, @@ -956,6 +962,14 @@ static void tablet_pad_handle_button(void *data, uint32_t button, uint32_t state) { + struct vo_wayland_tablet_pad *tablet_pad = data; + struct vo_wayland_state *wl = tablet_pad->wl; + + state = state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED + ? MP_KEY_STATE_DOWN + : MP_KEY_STATE_UP; + + mp_input_tablet_pad_button(wl->vo->input_ctx, button, state); } static void tablet_pad_handle_enter(void *data, @@ -964,6 +978,9 @@ static void tablet_pad_handle_enter(void *data, struct zwp_tablet_v2 *tablet, struct wl_surface *surface) { + struct vo_wayland_tablet_pad *tablet_pad = data; + struct vo_wayland_state *wl = tablet_pad->wl; + mp_input_set_tablet_pad_focus(wl->vo->input_ctx, true, tablet_pad->buttons); } static void tablet_pad_handle_leave(void *data, @@ -971,6 +988,9 @@ static void tablet_pad_handle_leave(void *data, uint32_t serial, struct wl_surface *surface) { + struct vo_wayland_tablet_pad *tablet_pad = data; + struct vo_wayland_state *wl = tablet_pad->wl; + mp_input_set_tablet_pad_focus(wl->vo->input_ctx, false, 0); } static void tablet_pad_handle_removed(void *data,