diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 91511f474..b5959fac0 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -213,6 +213,9 @@ void handle_libinput_event(struct wlr_libinput_backend *backend, case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: handle_tablet_tool_button(event, &dev->tablet); break; + case LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS: + handle_tablet_tool_scroll_continuous(event, &dev->tablet); + break; case LIBINPUT_EVENT_TABLET_PAD_BUTTON: handle_tablet_pad_button(event, &dev->tablet_pad); break; diff --git a/backend/libinput/tablet_tool.c b/backend/libinput/tablet_tool.c index cc9e60968..f0f641392 100644 --- a/backend/libinput/tablet_tool.c +++ b/backend/libinput/tablet_tool.c @@ -275,3 +275,53 @@ void handle_tablet_tool_button(struct libinput_event *event, } wl_signal_emit_mutable(&wlr_tablet->events.button, &wlr_event); } + +void handle_tablet_tool_scroll_continuous(struct libinput_event *event, + struct wlr_tablet *wlr_tablet) { + struct libinput_event_tablet_tool *tevent = + libinput_event_get_tablet_tool_event(event); + struct wlr_libinput_input_device *dev = device_from_tablet(wlr_tablet); + struct tablet_tool *tool = + get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent)); + + struct wlr_tablet_tool_axis_scroll_event wlr_event = { + .tablet = wlr_tablet, + .tool = &tool->wlr_tool, + .time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)), + }; + + switch (libinput_event_tablet_tool_get_axis_source(tevent)) { + case LIBINPUT_TABLET_TOOL_AXIS_SOURCE_CONTINUOUS: + wlr_event.source = WL_POINTER_AXIS_SOURCE_CONTINUOUS; + break; + default: + // FIXME + return; + } + + const enum libinput_pointer_axis axes[] = { + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + }; + for (size_t i = 0; i < sizeof(axes) / sizeof(axes[0]); ++i) { + if (!libinput_event_tablet_tool_has_axis(tevent, axes[i])) { + continue; + } + + switch (axes[i]) { + case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: + wlr_event.orientation = WL_POINTER_AXIS_VERTICAL_SCROLL; + break; + case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: + wlr_event.orientation = WL_POINTER_AXIS_HORIZONTAL_SCROLL; + break; + } + wlr_event.delta = + libinput_event_tablet_tool_get_scroll_value(tevent, axes[i]); + wlr_event.relative_direction = WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL; + if (libinput_device_config_scroll_get_natural_scroll_enabled(libinput_event_get_device(event))) { + wlr_event.relative_direction = WL_POINTER_AXIS_RELATIVE_DIRECTION_INVERTED; + } + wl_signal_emit_mutable(&wlr_tablet->events.axis_scroll, &wlr_event); + } +} diff --git a/include/backend/libinput.h b/include/backend/libinput.h index bf5a306f3..6c0f042da 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -124,6 +124,8 @@ void handle_tablet_tool_tip(struct libinput_event *event, struct wlr_tablet *tablet); void handle_tablet_tool_button(struct libinput_event *event, struct wlr_tablet *tablet); +void handle_tablet_tool_scroll_continuous(struct libinput_event *event, + struct wlr_tablet *tablet); void init_device_tablet_pad(struct wlr_libinput_input_device *dev); void finish_device_tablet_pad(struct wlr_libinput_input_device *dev); diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 57d6e508d..75508a139 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -73,6 +73,7 @@ struct wlr_cursor { struct wl_signal tablet_tool_proximity; struct wl_signal tablet_tool_tip; struct wl_signal tablet_tool_button; + struct wl_signal tablet_tool_axis_scroll; } events; void *data; diff --git a/include/wlr/types/wlr_tablet_tool.h b/include/wlr/types/wlr_tablet_tool.h index e71c92344..e4f55aece 100644 --- a/include/wlr/types/wlr_tablet_tool.h +++ b/include/wlr/types/wlr_tablet_tool.h @@ -12,6 +12,7 @@ #include #include #include +#include /* * Copy+Paste from libinput, but this should neither use libinput, nor @@ -72,6 +73,7 @@ struct wlr_tablet { struct wl_signal proximity; struct wl_signal tip; struct wl_signal button; + struct wl_signal axis_scroll; } events; struct wl_array paths; // char * @@ -145,6 +147,16 @@ struct wlr_tablet_tool_button_event { enum wlr_button_state state; }; +struct wlr_tablet_tool_axis_scroll_event { + struct wlr_tablet *tablet; + struct wlr_tablet_tool *tool; + uint32_t time_msec; + enum wl_pointer_axis_source source; + enum wl_pointer_axis orientation; + enum wl_pointer_axis_relative_direction relative_direction; + double delta; +}; + /** * Get a struct wlr_tablet from a struct wlr_input_device. * diff --git a/include/wlr/types/wlr_tablet_v2.h b/include/wlr/types/wlr_tablet_v2.h index d3a659494..3f5197717 100644 --- a/include/wlr/types/wlr_tablet_v2.h +++ b/include/wlr/types/wlr_tablet_v2.h @@ -179,6 +179,11 @@ void wlr_send_tablet_v2_tablet_tool_button( struct wlr_tablet_v2_tablet_tool *tool, uint32_t button, enum zwp_tablet_pad_v2_button_state state); +void wlr_send_tablet_v2_tablet_tool_axis_scroll( + struct wlr_tablet_v2_tablet_tool *tool, uint32_t time_msec, + enum wl_pointer_axis orientation, double value, + enum wl_pointer_axis_source source, + enum wl_pointer_axis_relative_direction relative_direction); void wlr_tablet_v2_tablet_tool_notify_proximity_in( @@ -217,6 +222,12 @@ void wlr_tablet_v2_tablet_tool_notify_button( struct wlr_tablet_v2_tablet_tool *tool, uint32_t button, enum zwp_tablet_pad_v2_button_state state); +void wlr_tablet_v2_tablet_tool_notify_scroll( + struct wlr_tablet_v2_tablet_tool *tool, uint32_t time_msec, + enum wl_pointer_axis orientation, double value, + enum wl_pointer_axis_source source, + enum wl_pointer_axis_relative_direction relative_direction); + struct wlr_tablet_tool_v2_grab_interface { void (*proximity_in)( @@ -246,6 +257,13 @@ struct wlr_tablet_tool_v2_grab_interface { void (*button)( struct wlr_tablet_tool_v2_grab *grab, uint32_t button, enum zwp_tablet_pad_v2_button_state state); + + void (*axis_scroll)( + struct wlr_tablet_tool_v2_grab *grab, uint32_t time_msec, + enum wl_pointer_axis orientation, double value, + enum wl_pointer_axis_source source, + enum wl_pointer_axis_relative_direction relative_direction); + void (*cancel)(struct wlr_tablet_tool_v2_grab *grab); }; diff --git a/types/tablet_v2/wlr_tablet_v2_tool.c b/types/tablet_v2/wlr_tablet_v2_tool.c index 9700e9043..9c6956cee 100644 --- a/types/tablet_v2/wlr_tablet_v2_tool.c +++ b/types/tablet_v2/wlr_tablet_v2_tool.c @@ -490,6 +490,17 @@ void wlr_send_tablet_v2_tablet_tool_button( } } +void wlr_send_tablet_v2_tablet_tool_axis_scroll( + struct wlr_tablet_v2_tablet_tool *tool, uint32_t time_msec, + enum wl_pointer_axis orientation, double value, + enum wl_pointer_axis_source source, + enum wl_pointer_axis_relative_direction relative_direction) { + if (tool->current_client) { + zwp_tablet_tool_v2_send_axis_scroll(tool->current_client->resource, time_msec, orientation, value); + queue_tool_frame(tool->current_client); + } +} + void wlr_send_tablet_v2_tablet_tool_wheel( struct wlr_tablet_v2_tablet_tool *tool, double degrees, int32_t clicks) { if (tool->current_client) { @@ -616,6 +627,16 @@ void wlr_tablet_v2_tablet_tool_notify_button( } } +void wlr_tablet_v2_tablet_tool_notify_scroll( + struct wlr_tablet_v2_tablet_tool *tool, uint32_t time_msec, + enum wl_pointer_axis orientation, double value, + enum wl_pointer_axis_source source, + enum wl_pointer_axis_relative_direction relative_direction) { + if (tool->grab->interface->axis_scroll) { + tool->grab->interface->axis_scroll(tool->grab, time_msec, orientation, value, source, relative_direction); + } +} + void wlr_tablet_tool_v2_start_grab(struct wlr_tablet_v2_tablet_tool *tool, struct wlr_tablet_tool_v2_grab *grab) { wlr_tablet_tool_v2_end_grab(tool); @@ -689,6 +710,14 @@ static void default_tool_button( wlr_send_tablet_v2_tablet_tool_button(grab->tool, button, state); } +static void default_tool_axis_scroll(struct wlr_tablet_tool_v2_grab *grab, + uint32_t time_msec, + enum wl_pointer_axis orientation, double value, + enum wl_pointer_axis_source source, + enum wl_pointer_axis_relative_direction relative_direction) { + wlr_send_tablet_v2_tablet_tool_axis_scroll(grab->tool, time_msec, orientation, value, source, relative_direction); +} + static void default_tool_cancel(struct wlr_tablet_tool_v2_grab *grab) { /* Do nothing. Default grab can't be canceled */ } @@ -707,6 +736,7 @@ static const struct wlr_tablet_tool_v2_grab_interface .wheel = default_tool_wheel, .proximity_out = default_tool_proximity_out, .button = default_tool_button, + .axis_scroll = default_tool_axis_scroll, .cancel = default_tool_cancel, }; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 77ab2fb70..cdd678dfa 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -50,6 +50,7 @@ struct wlr_cursor_device { struct wl_listener tablet_tool_proximity; struct wl_listener tablet_tool_tip; struct wl_listener tablet_tool_button; + struct wl_listener tablet_tool_axis_scroll; struct wl_listener destroy; }; @@ -142,6 +143,7 @@ struct wlr_cursor *wlr_cursor_create(void) { wl_signal_init(&cur->events.tablet_tool_tip); wl_signal_init(&cur->events.tablet_tool_axis); wl_signal_init(&cur->events.tablet_tool_button); + wl_signal_init(&cur->events.tablet_tool_axis_scroll); wl_signal_init(&cur->events.tablet_tool_proximity); wl_list_init(&cur->state->surface_destroy.link); @@ -212,6 +214,7 @@ static void cursor_device_destroy(struct wlr_cursor_device *c_device) { wl_list_remove(&c_device->tablet_tool_proximity.link); wl_list_remove(&c_device->tablet_tool_tip.link); wl_list_remove(&c_device->tablet_tool_button.link); + wl_list_remove(&c_device->tablet_tool_axis_scroll.link); break; default: abort(); // unreachable @@ -921,6 +924,15 @@ static void handle_tablet_tool_button(struct wl_listener *listener, wl_signal_emit_mutable(&device->cursor->events.tablet_tool_button, event); } +static void handle_tablet_tool_axis_scroll(struct wl_listener *listener, + void *data) { + struct wlr_tablet_tool_axis_scroll_event *event = data; + struct wlr_cursor_device *device; + device = wl_container_of(listener, device, tablet_tool_axis_scroll); + + wl_signal_emit_mutable(&device->cursor->events.tablet_tool_axis_scroll, event); +} + static void handle_tablet_tool_proximity(struct wl_listener *listener, void *data) { struct wlr_tablet_tool_proximity_event *event = data; @@ -1036,6 +1048,10 @@ static struct wlr_cursor_device *cursor_device_create( wl_signal_add(&tablet->events.button, &c_device->tablet_tool_button); c_device->tablet_tool_button.notify = handle_tablet_tool_button; + wl_signal_add(&tablet->events.axis_scroll, + &c_device->tablet_tool_axis_scroll); + c_device->tablet_tool_axis_scroll.notify = handle_tablet_tool_axis_scroll; + break; default: diff --git a/types/wlr_tablet_tool.c b/types/wlr_tablet_tool.c index 77f4631e8..87f4d20d4 100644 --- a/types/wlr_tablet_tool.c +++ b/types/wlr_tablet_tool.c @@ -24,6 +24,7 @@ void wlr_tablet_init(struct wlr_tablet *tablet, wl_signal_init(&tablet->events.proximity); wl_signal_init(&tablet->events.tip); wl_signal_init(&tablet->events.button); + wl_signal_init(&tablet->events.axis_scroll); wl_array_init(&tablet->paths); }