From 2b96799a05c747e68200c266f0a9a1c9eec304d3 Mon Sep 17 00:00:00 2001 From: Jens Peters Date: Fri, 1 Dec 2023 22:12:00 +0100 Subject: [PATCH] input: add drawing tablet setup and event listeners Co-authored-by: Consolatis <35009135+Consolatis@users.noreply.github.com> --- include/input/drawing_tablet.h | 25 +++++++ src/input/drawing_tablet.c | 115 +++++++++++++++++++++++++++++++++ src/input/meson.build | 1 + 3 files changed, 141 insertions(+) create mode 100644 include/input/drawing_tablet.h create mode 100644 src/input/drawing_tablet.c diff --git a/include/input/drawing_tablet.h b/include/input/drawing_tablet.h new file mode 100644 index 00000000..8043e7a5 --- /dev/null +++ b/include/input/drawing_tablet.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef LABWC_DRAWING_TABLET_H +#define LABWC_DRAWING_TABLET_H + +#include +struct seat; +struct wlr_device; +struct wlr_input_device; + +struct drawing_tablet { + struct seat *seat; + struct wlr_tablet *tablet; + double x, y; + struct { + struct wl_listener axis; + struct wl_listener tip; + struct wl_listener button; + struct wl_listener destroy; + // no interest in proximity events + } handlers; +}; + +void drawing_tablet_setup_handlers(struct seat *seat, struct wlr_input_device *wlr_input_device); + +#endif /* LABWC_DRAWING_TABLET_H */ diff --git a/src/input/drawing_tablet.c b/src/input/drawing_tablet.c new file mode 100644 index 00000000..540642bc --- /dev/null +++ b/src/input/drawing_tablet.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include +#include +#include "common/macros.h" +#include "common/mem.h" +#include "config/rcxml.h" +#include "input/cursor.h" +#include "input/drawing_tablet.h" + +#include "config/rcxml.h" + +static void +handle_axis(struct wl_listener *listener, void *data) +{ + struct wlr_tablet_tool_axis_event *ev = data; + struct drawing_tablet *tablet = ev->tablet->data; + if (ev->updated_axes & (WLR_TABLET_TOOL_AXIS_X | WLR_TABLET_TOOL_AXIS_Y)) { + if (ev->updated_axes & WLR_TABLET_TOOL_AXIS_X) { + tablet->x = ev->x; + } + if (ev->updated_axes & WLR_TABLET_TOOL_AXIS_Y) { + tablet->y = ev->y; + } + + double x = tablet->x; + double y = tablet->y; + cursor_emulate_move_absolute(tablet->seat, &ev->tablet->base, x, y, ev->time_msec); + } + // Ignore other events +} + +static void +handle_tip(struct wl_listener *listener, void *data) +{ + struct wlr_tablet_tool_tip_event *ev = data; + struct drawing_tablet *tablet = ev->tablet->data; + + cursor_emulate_button(tablet->seat, + BTN_LEFT, + ev->state == WLR_TABLET_TOOL_TIP_DOWN + ? WLR_BUTTON_PRESSED + : WLR_BUTTON_RELEASED, + ev->time_msec); +} + +static void +handle_button(struct wl_listener *listener, void *data) +{ + struct wlr_tablet_tool_button_event *ev = data; + struct drawing_tablet *tablet = ev->tablet->data; + + uint32_t button; + switch (ev->button) { + case BTN_STYLUS: + button = BTN_RIGHT; + break; + case BTN_STYLUS2: + button = BTN_MIDDLE; + break; + default: + wlr_log(WLR_DEBUG, "no button map target"); + return; + } + + cursor_emulate_button(tablet->seat, button, ev->state, ev->time_msec); +} + +static void +handle_destroy(struct wl_listener *listener, void *data) +{ + struct drawing_tablet *tablet = + wl_container_of(listener, tablet, handlers.destroy); + free(tablet); +} + +static void +setup_pad(struct seat *seat, struct wlr_input_device *wlr_device) +{ + wlr_log(WLR_INFO, "not setting up pad"); +} + +static void +setup_pen(struct seat *seat, struct wlr_input_device *wlr_device) +{ + wlr_log(WLR_DEBUG, "setting up tablet"); + struct drawing_tablet *tablet = znew(*tablet); + tablet->seat = seat; + tablet->tablet = wlr_tablet_from_input_device(wlr_device); + tablet->tablet->data = tablet; + tablet->x = 0.0; + tablet->y = 0.0; + CONNECT_SIGNAL(tablet->tablet, &tablet->handlers, axis); + CONNECT_SIGNAL(tablet->tablet, &tablet->handlers, tip); + CONNECT_SIGNAL(tablet->tablet, &tablet->handlers, button); + CONNECT_SIGNAL(wlr_device, &tablet->handlers, destroy); +} + +void +drawing_tablet_setup_handlers(struct seat *seat, struct wlr_input_device *device) +{ + switch (device->type) { + case WLR_INPUT_DEVICE_TABLET_PAD: + setup_pad(seat, device); + break; + case WLR_INPUT_DEVICE_TABLET_TOOL: + setup_pen(seat, device); + break; + default: + assert(false && "tried to add non-tablet as tablet"); + } +} diff --git a/src/input/meson.build b/src/input/meson.build index cfdd3cd0..91d897a9 100644 --- a/src/input/meson.build +++ b/src/input/meson.build @@ -1,5 +1,6 @@ labwc_sources += files( 'cursor.c', + 'drawing_tablet.c', 'gestures.c', 'input.c', 'keyboard.c',