diff options
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/evdev-tablet-pad.c | 620 | ||||
-rw-r--r-- | src/evdev-tablet-pad.h | 69 | ||||
-rw-r--r-- | src/evdev.c | 28 | ||||
-rw-r--r-- | src/evdev.h | 13 | ||||
-rw-r--r-- | src/libinput.c | 6 |
6 files changed, 722 insertions, 15 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 343e75c7..a3df6c8f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,6 +20,7 @@ libinput_la_SOURCES = \ evdev-mt-touchpad-gestures.c \ evdev-tablet.c \ evdev-tablet.h \ + evdev-tablet-pad.c \ filter.c \ filter.h \ filter-private.h \ diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c new file mode 100644 index 00000000..ad6ead84 --- /dev/null +++ b/src/evdev-tablet-pad.c @@ -0,0 +1,620 @@ +/* + * Copyright © 2016 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" +#include "evdev-tablet-pad.h" + +#include <assert.h> +#include <stdbool.h> +#include <string.h> + +#define pad_set_status(pad_,s_) (pad_)->status |= (s_) +#define pad_unset_status(pad_,s_) (pad_)->status &= ~(s_) +#define pad_has_status(pad_,s_) (!!((pad_)->status & (s_))) + +static void +pad_get_buttons_pressed(struct pad_dispatch *pad, + struct button_state *buttons) +{ + struct button_state *state = &pad->button_state; + struct button_state *prev_state = &pad->prev_button_state; + unsigned int i; + + for (i = 0; i < sizeof(buttons->bits); i++) + buttons->bits[i] = state->bits[i] & ~(prev_state->bits[i]); +} + +static void +pad_get_buttons_released(struct pad_dispatch *pad, + struct button_state *buttons) +{ + struct button_state *state = &pad->button_state; + struct button_state *prev_state = &pad->prev_button_state; + unsigned int i; + + for (i = 0; i < sizeof(buttons->bits); i++) + buttons->bits[i] = prev_state->bits[i] & ~(state->bits[i]); +} + +static inline bool +pad_button_is_down(const struct pad_dispatch *pad, + uint32_t button) +{ + return bit_is_set(pad->button_state.bits, button); +} + +static inline bool +pad_any_button_down(const struct pad_dispatch *pad) +{ + const struct button_state *state = &pad->button_state; + unsigned int i; + + for (i = 0; i < sizeof(state->bits); i++) + if (state->bits[i] != 0) + return true; + + return false; +} + +static inline void +pad_button_set_down(struct pad_dispatch *pad, + uint32_t button, + bool is_down) +{ + struct button_state *state = &pad->button_state; + + if (is_down) { + set_bit(state->bits, button); + pad_set_status(pad, PAD_BUTTONS_PRESSED); + } else { + clear_bit(state->bits, button); + pad_set_status(pad, PAD_BUTTONS_RELEASED); + } +} + +static void +pad_process_absolute(struct pad_dispatch *pad, + struct evdev_device *device, + struct input_event *e, + uint64_t time) +{ + switch (e->code) { + case ABS_WHEEL: + pad->changed_axes |= PAD_AXIS_RING1; + pad_set_status(pad, PAD_AXES_UPDATED); + break; + case ABS_THROTTLE: + pad->changed_axes |= PAD_AXIS_RING2; + pad_set_status(pad, PAD_AXES_UPDATED); + break; + case ABS_RX: + pad->changed_axes |= PAD_AXIS_STRIP1; + pad_set_status(pad, PAD_AXES_UPDATED); + break; + case ABS_RY: + pad->changed_axes |= PAD_AXIS_STRIP2; + pad_set_status(pad, PAD_AXES_UPDATED); + break; + case ABS_MISC: + /* The wacom driver always sends a 0 axis event on finger + up, but we also get an ABS_MISC 15 on touch down and + ABS_MISC 0 on touch up, on top of the actual event. This + is kernel behavior for xf86-input-wacom backwards + compatibility after the 3.17 wacom HID move. + + We use that event to tell when we truly went a full + rotation around the wheel vs. a finger release. + + FIXME: On the Intuos5 and later the kernel merges all + states into that event, so if any finger is down on any + button, the wheel release won't trigger the ABS_MISC 0 + but still send a 0 event. We can't currently detect this. + */ + pad->have_abs_misc_terminator = true; + break; + default: + log_info(device->base.seat->libinput, + "Unhandled EV_ABS event code %#x\n", e->code); + break; + } +} + +static inline double +normalize_ring(const struct input_absinfo *absinfo) +{ + /* libinput has 0 as the ring's northernmost point in the device's + current logical rotation, increasing clockwise to 1. Wacom has + 0 on the left-most wheel position. + */ + double range = absinfo->maximum - absinfo->minimum + 1; + double value = (absinfo->value - absinfo->minimum) / range - 0.25; + + if (value < 0.0) + value += 1.0; + + return value; +} + +static inline double +normalize_strip(const struct input_absinfo *absinfo) +{ + /* strip axes don't use a proper value, they just shift the bit left + * for each position. 0 isn't a real value either, it's only sent on + * finger release */ + double min = 0, + max = log2(absinfo->maximum); + double range = max - min; + double value = (log2(absinfo->value) - min) / range; + + return value; +} + +static inline double +pad_handle_ring(struct pad_dispatch *pad, + struct evdev_device *device, + unsigned int code) +{ + const struct input_absinfo *absinfo; + double degrees; + + absinfo = libevdev_get_abs_info(device->evdev, code); + assert(absinfo); + + degrees = normalize_ring(absinfo) * 360; + + if (device->left_handed.enabled) + degrees = fmod(degrees + 180, 360); + + return degrees; +} + +static inline double +pad_handle_strip(struct pad_dispatch *pad, + struct evdev_device *device, + unsigned int code) +{ + const struct input_absinfo *absinfo; + double pos; + + absinfo = libevdev_get_abs_info(device->evdev, code); + assert(absinfo); + + if (absinfo->value == 0) + return 0.0; + + pos = normalize_strip(absinfo); + + if (device->left_handed.enabled) + pos = 1.0 - pos; + + return pos; +} + +static void +pad_check_notify_axes(struct pad_dispatch *pad, + struct evdev_device *device, + uint64_t time) +{ + struct libinput_device *base = &device->base; + double value; + bool send_finger_up = false; + + /* Suppress the reset to 0 on finger up. See the + comment in pad_process_absolute */ + if (pad->have_abs_misc_terminator && + libevdev_get_event_value(device->evdev, EV_ABS, ABS_MISC) == 0) + send_finger_up = true; + + if (pad->changed_axes & PAD_AXIS_RING1) { + value = pad_handle_ring(pad, device, ABS_WHEEL); + if (send_finger_up) + value = -1.0; + + tablet_pad_notify_ring(base, + time, + 0, + value, + LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER); + } + + if (pad->changed_axes & PAD_AXIS_RING2) { + value = pad_handle_ring(pad, device, ABS_THROTTLE); + if (send_finger_up) + value = -1.0; + + tablet_pad_notify_ring(base, + time, + 1, + value, + LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER); + } + + if (pad->changed_axes & PAD_AXIS_STRIP1) { + value = pad_handle_strip(pad, device, ABS_RX); + if (send_finger_up) + value = -1.0; + + tablet_pad_notify_strip(base, + time, + 0, + value, + LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER); + } + + if (pad->changed_axes & PAD_AXIS_STRIP2) { + value = pad_handle_strip(pad, device, ABS_RY); + if (send_finger_up) + value = -1.0; + + tablet_pad_notify_strip(base, + time, + 1, + value, + LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER); + } + + pad->changed_axes = PAD_AXIS_NONE; + pad->have_abs_misc_terminator = false; +} + +static void +pad_process_key(struct pad_dispatch *pad, + struct evdev_device *device, + struct input_event *e, + uint64_t time) +{ + uint32_t button = e->code; + uint32_t is_press = e->value != 0; + + pad_button_set_down(pad, button, is_press); +} + +static void +pad_notify_button_mask(struct pad_dispatch *pad, + struct evdev_device *device, + uint64_t time, + const struct button_state *buttons, + enum libinput_button_state state) +{ + struct libinput_device *base = &device->base; + int32_t code; + unsigned int i; + + for (i = 0; i < sizeof(buttons->bits); i++) { + unsigned char buttons_slice = buttons->bits[i]; + + code = i * 8; + while (buttons_slice) { + int enabled; + char map; + + code++; + enabled = (buttons_slice & 1); + buttons_slice >>= 1; + + if (!enabled) + continue; + + map = pad->button_map[code - 1]; + if (map != -1) + tablet_pad_notify_button(base, time, map, state); + } + } +} + +static void +pad_notify_buttons(struct pad_dispatch *pad, + struct evdev_device *device, + uint64_t time, + enum libinput_button_state state) +{ + struct button_state buttons; + + if (state == LIBINPUT_BUTTON_STATE_PRESSED) + pad_get_buttons_pressed(pad, &buttons); + else + pad_get_buttons_released(pad, &buttons); + + pad_notify_button_mask(pad, device, time, &buttons, state); +} + +static void +pad_change_to_left_handed(struct evdev_device *device) +{ + struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch; + + if (device->left_handed.enabled == device->left_handed.want_enabled) + return; + + if (pad_any_button_down(pad)) + return; + + device->left_handed.enabled = device->left_handed.want_enabled; +} + +static void +pad_flush(struct pad_dispatch *pad, + struct evdev_device *device, + uint64_t time) +{ + if (pad_has_status(pad, PAD_AXES_UPDATED)) { + pad_check_notify_axes(pad, device, time); + pad_unset_status(pad, PAD_AXES_UPDATED); + } + + if (pad_has_status(pad, PAD_BUTTONS_RELEASED)) { + pad_notify_buttons(pad, + device, + time, + LIBINPUT_BUTTON_STATE_RELEASED); + pad_unset_status(pad, PAD_BUTTONS_RELEASED); + + pad_change_to_left_handed(device); + } + + if (pad_has_status(pad, PAD_BUTTONS_PRESSED)) { + pad_notify_buttons(pad, + device, + time, + LIBINPUT_BUTTON_STATE_PRESSED); + pad_unset_status(pad, PAD_BUTTONS_PRESSED); + } + + /* Update state */ + memcpy(&pad->prev_button_state, + &pad->button_state, + sizeof(pad->button_state)); +} + +static void +pad_process(struct evdev_dispatch *dispatch, + struct evdev_device *device, + struct input_event *e, + uint64_t time) +{ + struct pad_dispatch *pad = (struct pad_dispatch *)dispatch; + + switch (e->type) { + case EV_ABS: + pad_process_absolute(pad, device, e, time); + break; + case EV_KEY: + pad_process_key(pad, device, e, time); + break; + case EV_SYN: + pad_flush(pad, device, time); + break; + default: + log_error(device->base.seat->libinput, + "Unexpected event type %s (%#x)\n", + libevdev_event_type_get_name(e->type), + e->type); + break; + } +} + +static void +pad_suspend(struct evdev_dispatch *dispatch, + struct evdev_device *device) +{ + struct pad_dispatch *pad = (struct pad_dispatch *)dispatch; + struct libinput *libinput = device->base.seat->libinput; + unsigned int code; + + for (code = KEY_ESC; code < KEY_CNT; code++) { + if (pad_button_is_down(pad, code)) + pad_button_set_down(pad, code, false); + } + + pad_flush(pad, device, libinput_now(libinput)); +} + +static void +pad_destroy(struct evdev_dispatch *dispatch) +{ + struct pad_dispatch *pad = (struct pad_dispatch*)dispatch; + + free(pad); +} + +static struct evdev_dispatch_interface pad_interface = { + pad_process, + pad_suspend, /* suspend */ + NULL, /* remove */ + pad_destroy, + NULL, /* device_added */ + NULL, /* device_removed */ + NULL, /* device_suspended */ + NULL, /* device_resumed */ + NULL, /* post_added */ +}; + +static void +pad_init_buttons(struct pad_dispatch *pad, + struct evdev_device *device) +{ + unsigned int code; + size_t i; + int map = 0; + + for (i = 0; i < ARRAY_LENGTH(pad->button_map); i++) + pad->button_map[i] = -1; + + /* we match wacom_report_numbered_buttons() from the kernel */ + for (code = BTN_0; code < BTN_0 + 10; code++) { + if (libevdev_has_event_code(device->evdev, EV_KEY, code)) + pad->button_map[code] = map++; + } + + for (code = BTN_A; code < BTN_A + 6; code++) { + if (libevdev_has_event_code(device->evdev, EV_KEY, code)) + pad->button_map[code] = map++; + } + + for (code = BTN_BASE; code < BTN_BASE + 2; code++) { + if (libevdev_has_event_code(device->evdev, EV_KEY, code)) + pad->button_map[code] = map++; + } + + pad->nbuttons = map; +} + +static void +pad_init_left_handed(struct evdev_device *device) +{ + if (evdev_tablet_has_left_handed(device)) + evdev_init_left_handed(device, + pad_change_to_left_handed); +} + +static int +pad_init(struct pad_dispatch *pad, struct evdev_device *device) +{ + pad->base.interface = &pad_interface; + pad->device = device; + pad->status = PAD_NONE; + pad->changed_axes = PAD_AXIS_NONE; + + pad_init_buttons(pad, device); + pad_init_left_handed(device); + + return 0; +} + +static uint32_t +pad_sendevents_get_modes(struct libinput_device *device) +{ + return LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; +} + +static enum libinput_config_status +pad_sendevents_set_mode(struct libinput_device *device, + enum libinput_config_send_events_mode mode) +{ + struct evdev_device *evdev = (struct evdev_device*)device; + struct pad_dispatch *pad = (struct pad_dispatch*)evdev->dispatch; + + if (mode == pad->sendevents.current_mode) + return LIBINPUT_CONFIG_STATUS_SUCCESS; + + switch(mode) { + case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED: + break; + case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED: + pad_suspend(evdev->dispatch, evdev); + break; + default: + return LIBINPUT_CONFIG_STATUS_UNSUPPORTED; + } + + pad->sendevents.current_mode = mode; + + return LIBINPUT_CONFIG_STATUS_SUCCESS; +} + +static enum libinput_config_send_events_mode +pad_sendevents_get_mode(struct libinput_device *device) +{ + struct evdev_device *evdev = (struct evdev_device*)device; + struct pad_dispatch *dispatch = (struct pad_dispatch*)evdev->dispatch; + + return dispatch->sendevents.current_mode; +} + +static enum libinput_config_send_events_mode +pad_sendevents_get_default_mode(struct libinput_device *device) +{ + return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; +} + +struct evdev_dispatch * +evdev_tablet_pad_create(struct evdev_device *device) +{ + struct pad_dispatch *pad; + + pad = zalloc(sizeof *pad); + if (!pad) + return NULL; + + if (pad_init(pad, device) != 0) { + pad_destroy(&pad->base); + return NULL; + } + + device->base.config.sendevents = &pad->sendevents.config; + pad->sendevents.current_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; + pad->sendevents.config.get_modes = pad_sendevents_get_modes; + pad->sendevents.config.set_mode = pad_sendevents_set_mode; + pad->sendevents.config.get_mode = pad_sendevents_get_mode; + pad->sendevents.config.get_default_mode = pad_sendevents_get_default_mode; + + return &pad->base; +} + +int +evdev_device_tablet_pad_get_num_buttons(struct evdev_device *device) +{ + struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch; + + if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD)) + return -1; + + return pad->nbuttons; +} + +int +evdev_device_tablet_pad_get_num_rings(struct evdev_device *device) +{ + int nrings = 0; + + if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD)) + return -1; + + if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_WHEEL)) { + nrings++; + if (libevdev_has_event_code(device->evdev, + EV_ABS, + ABS_THROTTLE)) + nrings++; + } + + return nrings; +} + +int +evdev_device_tablet_pad_get_num_strips(struct evdev_device *device) +{ + int nstrips = 0; + + if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD)) + return -1; + + if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_RX)) { + nstrips++; + if (libevdev_has_event_code(device->evdev, + EV_ABS, + ABS_RY)) + nstrips++; + } + + return nstrips; +} diff --git a/src/evdev-tablet-pad.h b/src/evdev-tablet-pad.h new file mode 100644 index 00000000..828ded8f --- /dev/null +++ b/src/evdev-tablet-pad.h @@ -0,0 +1,69 @@ +/* + * Copyright © 2015 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef EVDEV_BUTTONSET_WACOM_H +#define EVDEV_BUTTONSET_WACOM_H + +#include "evdev.h" + +#define LIBINPUT_BUTTONSET_AXIS_NONE 0 + +enum pad_status { + PAD_NONE = 0, + PAD_AXES_UPDATED = 1 << 0, + PAD_BUTTONS_PRESSED = 1 << 1, + PAD_BUTTONS_RELEASED = 1 << 2, +}; + +enum pad_axes { + PAD_AXIS_NONE = 0, + PAD_AXIS_RING1 = 1 << 0, + PAD_AXIS_RING2 = 1 << 1, + PAD_AXIS_STRIP1 = 1 << 2, + PAD_AXIS_STRIP2 = 1 << 3, +}; + +struct button_state { + unsigned char bits[NCHARS(KEY_CNT)]; +}; + +struct pad_dispatch { + struct evdev_dispatch base; + struct evdev_device *device; + unsigned char status; + uint32_t changed_axes; + + struct button_state button_state; + struct button_state prev_button_state; + + char button_map[KEY_CNT]; + unsigned int nbuttons; + + bool have_abs_misc_terminator; + + struct { + struct libinput_device_config_send_events config; + enum libinput_config_send_events_mode current_mode; + } sendevents; +}; + +#endif diff --git a/src/evdev.c b/src/evdev.c index 330ca6b9..7a28bf21 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -65,7 +65,7 @@ enum evdev_device_udev_tags { EVDEV_UDEV_TAG_TABLET = (1 << 5), EVDEV_UDEV_TAG_JOYSTICK = (1 << 6), EVDEV_UDEV_TAG_ACCELEROMETER = (1 << 7), - EVDEV_UDEV_TAG_BUTTONSET = (1 << 8), + EVDEV_UDEV_TAG_TABLET_PAD = (1 << 8), EVDEV_UDEV_TAG_POINTINGSTICK = (1 << 9), }; @@ -82,7 +82,7 @@ static const struct evdev_udev_tag_match evdev_udev_tag_matches[] = { {"ID_INPUT_TOUCHPAD", EVDEV_UDEV_TAG_TOUCHPAD}, {"ID_INPUT_TOUCHSCREEN", EVDEV_UDEV_TAG_TOUCHSCREEN}, {"ID_INPUT_TABLET", EVDEV_UDEV_TAG_TABLET}, - {"ID_INPUT_TABLET_PAD", EVDEV_UDEV_TAG_BUTTONSET}, + {"ID_INPUT_TABLET_PAD", EVDEV_UDEV_TAG_TABLET_PAD}, {"ID_INPUT_JOYSTICK", EVDEV_UDEV_TAG_JOYSTICK}, {"ID_INPUT_ACCELEROMETER", EVDEV_UDEV_TAG_ACCELEROMETER}, {"ID_INPUT_POINTINGSTICK", EVDEV_UDEV_TAG_POINTINGSTICK}, @@ -2049,7 +2049,7 @@ evdev_configure_device(struct evdev_device *device) udev_tags & EVDEV_UDEV_TAG_POINTINGSTICK ? " Pointingstick" : "", udev_tags & EVDEV_UDEV_TAG_JOYSTICK ? " Joystick" : "", udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : "", - udev_tags & EVDEV_UDEV_TAG_BUTTONSET ? " Buttonset" : ""); + udev_tags & EVDEV_UDEV_TAG_TABLET_PAD ? " TabletPad" : ""); if (udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER) { log_info(libinput, @@ -2067,14 +2067,6 @@ evdev_configure_device(struct evdev_device *device) return -1; } - /* libwacom assigns tablet _and_ tablet_pad to the pad devices */ - if (udev_tags & EVDEV_UDEV_TAG_BUTTONSET) { - log_info(libinput, - "input device '%s', %s is a buttonset, ignoring\n", - device->devname, devnode); - return -1; - } - if (evdev_reject_device(device) == -1) { log_info(libinput, "input device '%s', %s was rejected.\n", @@ -2110,7 +2102,17 @@ evdev_configure_device(struct evdev_device *device) tablet_tags = EVDEV_UDEV_TAG_TABLET | EVDEV_UDEV_TAG_TOUCHPAD | EVDEV_UDEV_TAG_TOUCHSCREEN; - if ((udev_tags & tablet_tags) == EVDEV_UDEV_TAG_TABLET) { + + /* libwacom assigns tablet _and_ tablet_pad to the pad devices */ + if (udev_tags & EVDEV_UDEV_TAG_TABLET_PAD) { + device->dispatch = evdev_tablet_pad_create(device); + device->seat_caps |= EVDEV_DEVICE_TABLET_PAD; + log_info(libinput, + "input device '%s', %s is a tablet pad\n", + device->devname, devnode); + return device->dispatch == NULL ? -1 : 0; + + } else if ((udev_tags & tablet_tags) == EVDEV_UDEV_TAG_TABLET) { device->dispatch = evdev_tablet_create(device); device->seat_caps |= EVDEV_DEVICE_TABLET; log_info(libinput, @@ -2539,6 +2541,8 @@ evdev_device_has_capability(struct evdev_device *device, return !!(device->seat_caps & EVDEV_DEVICE_GESTURE); case LIBINPUT_DEVICE_CAP_TABLET_TOOL: return !!(device->seat_caps & EVDEV_DEVICE_TABLET); + case LIBINPUT_DEVICE_CAP_TABLET_PAD: + return !!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD); default: return 0; } diff --git a/src/evdev.h b/src/evdev.h index 56f07dba..3ed077b4 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -61,6 +61,7 @@ enum evdev_device_seat_capability { EVDEV_DEVICE_KEYBOARD = (1 << 1), EVDEV_DEVICE_TOUCH = (1 << 2), EVDEV_DEVICE_TABLET = (1 << 3), + EVDEV_DEVICE_TABLET_PAD = (1 << 4), EVDEV_DEVICE_GESTURE = (1 << 5), }; @@ -319,6 +320,9 @@ evdev_mt_touchpad_create(struct evdev_device *device); struct evdev_dispatch * evdev_tablet_create(struct evdev_device *device); +struct evdev_dispatch * +evdev_tablet_pad_create(struct evdev_device *device); + void evdev_tag_touchpad(struct evdev_device *device, struct udev_device *udev_device); @@ -369,6 +373,15 @@ evdev_device_has_button(struct evdev_device *device, uint32_t code); int evdev_device_has_key(struct evdev_device *device, uint32_t code); +int +evdev_device_tablet_pad_get_num_buttons(struct evdev_device *device); + +int +evdev_device_tablet_pad_get_num_rings(struct evdev_device *device); + +int +evdev_device_tablet_pad_get_num_strips(struct evdev_device *device); + double evdev_device_transform_x(struct evdev_device *device, double x, diff --git a/src/libinput.c b/src/libinput.c index bd97fb0e..bcd0dcd0 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -2794,19 +2794,19 @@ libinput_device_keyboard_has_key(struct libinput_device *device, uint32_t code) LIBINPUT_EXPORT int libinput_device_tablet_pad_get_num_buttons(struct libinput_device *device) { - return 0; + return evdev_device_tablet_pad_get_num_buttons((struct evdev_device *)device); } LIBINPUT_EXPORT int libinput_device_tablet_pad_get_num_rings(struct libinput_device *device) { - return 0; + return evdev_device_tablet_pad_get_num_rings((struct evdev_device *)device); } LIBINPUT_EXPORT int libinput_device_tablet_pad_get_num_strips(struct libinput_device *device) { - return 0; + return evdev_device_tablet_pad_get_num_strips((struct evdev_device *)device); } LIBINPUT_EXPORT struct libinput_event * |