On Wed, Oct 25, 2017 at 10:24 PM, Peter Hutterer <peter.hutte...@who-t.net> wrote: > Some of wacom's tablets, notably the Bamboo series, have a non-predictable > scheme of mapping the buttons to numeric button numbers in libwacom. Since we > promise sequential button numbers, we need to have those identical to > libwacom, otherwise it's impossible to map the two together. > > Most tablets have a predictable mapping, so this does not affect the majority > of devices. > > For the old-style bamboos, this swaps the buttons around with the buttons > being ordered in a vertical order.
This language gives me pause because I know under the covers the order ultimately comes down to whatever the libwacom SVGs specify. Still, it looks like all the Bamboo SVGs do indeed use a vertical order so you can leave it as-is if you'd like. > > Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> > --- > meson.build | 9 +++ > src/evdev-tablet-pad.c | 74 +++++++++++++++++++-- > test/test-pad.c | 171 > ++++++++++++++++++++++++++++++++++++++++++++----- > 3 files changed, 233 insertions(+), 21 deletions(-) > > diff --git a/meson.build b/meson.build > index f93cde70..72bd90b0 100644 > --- a/meson.build > +++ b/meson.build > @@ -66,6 +66,15 @@ if have_libwacom > name : 'libwacom_get_paired_device check', > dependencies : dep_libwacom) > config_h.set10('HAVE_LIBWACOM_GET_PAIRED_DEVICE', result) > + > + code = ''' > + #include <libwacom/libwacom.h> > + int main(void) { libwacom_get_button_evdev_code(NULL, 'A'); } > + ''' > + result = cc.links(code, > + name : 'libwacom_get_button_evdev_code check', > + dependencies : dep_libwacom) > + config_h.set10('HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE', result) > else > dep_libwacom = declare_dependency() > endif > diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c > index 82604d70..2e85f7ac 100644 > --- a/src/evdev-tablet-pad.c > +++ b/src/evdev-tablet-pad.c > @@ -27,6 +27,10 @@ > #include <stdbool.h> > #include <string.h> > > +#if HAVE_LIBWACOM > +#include <libwacom/libwacom.h> > +#endif > + > #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_))) > @@ -517,17 +521,61 @@ static struct evdev_dispatch_interface pad_interface = { > .get_switch_state = NULL, > }; > > +static bool > +pad_init_buttons_from_libwacom(struct pad_dispatch *pad, > + struct evdev_device *device) > +{ > + bool rc = false; > +#if HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE > + WacomDeviceDatabase *db = NULL; > + WacomDevice *tablet = NULL; > + int num_buttons; > + int map = 0; > + > + db = libwacom_database_new(); > + if (!db) { > + evdev_log_info(device, > + "Failed to initialize libwacom context.\n"); > + goto out; > + } > + > + tablet = libwacom_new_from_usbid(db, > + evdev_device_get_id_vendor(device), > + evdev_device_get_id_product(device), > + NULL); > + if (!tablet) > + goto out; > + > + num_buttons = libwacom_get_num_buttons(tablet); > + for (int i = 0; i < num_buttons; i++) { > + unsigned int code; > + > + code = libwacom_get_button_evdev_code(tablet, 'A' + i); > + if (code == 0) > + continue; > + > + pad->button_map[code] = map++; > + } > + > + pad->nbuttons = map; > + > + rc = true; > +out: > + if (tablet) > + libwacom_destroy(tablet); > + if (db) > + libwacom_database_destroy(db); > +#endif > + return rc; > +} > + > static void > -pad_init_buttons(struct pad_dispatch *pad, > - struct evdev_device *device) > +pad_init_buttons_from_kernel(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)) > @@ -553,6 +601,20 @@ pad_init_buttons(struct pad_dispatch *pad, > } > > static void > +pad_init_buttons(struct pad_dispatch *pad, > + struct evdev_device *device) > +{ > + size_t i; > + > + for (i = 0; i < ARRAY_LENGTH(pad->button_map); i++) > + pad->button_map[i] = -1; > + > + if (!pad_init_buttons_from_libwacom(pad, device)) > + pad_init_buttons_from_kernel(pad, device); > + > +} > + > +static void > pad_init_left_handed(struct evdev_device *device) > { > if (evdev_tablet_has_left_handed(device)) > diff --git a/test/test-pad.c b/test/test-pad.c > index 085d6c58..3383c60f 100644 > --- a/test/test-pad.c > +++ b/test/test-pad.c > @@ -29,6 +29,10 @@ > #include <unistd.h> > #include <stdbool.h> > > +#if HAVE_LIBWACOM > +#include <libwacom/libwacom.h> > +#endif > + > #include "libinput-util.h" > #include "litest.h" > > @@ -119,6 +123,35 @@ START_TEST(pad_time) > } > END_TEST > > +START_TEST(pad_num_buttons_libwacom) > +{ > +#if HAVE_LIBWACOM > + struct litest_device *dev = litest_current_device(); > + struct libinput_device *device = dev->libinput_device; > + WacomDeviceDatabase *db = NULL; > + WacomDevice *wacom = NULL; > + unsigned int nb_lw, nb; > + > + db = libwacom_database_new(); > + ck_assert_notnull(db); > + > + wacom = libwacom_new_from_usbid(db, > + libevdev_get_id_vendor(dev->evdev), > + libevdev_get_id_product(dev->evdev), > + NULL); > + ck_assert_notnull(wacom); > + > + nb_lw = libwacom_get_num_buttons(wacom); > + nb = libinput_device_tablet_pad_get_num_buttons(device); > + > + ck_assert_int_eq(nb, nb_lw); > + > + libwacom_destroy(wacom); > + libwacom_database_destroy(db); > +#endif > +} > +END_TEST > + > START_TEST(pad_num_buttons) > { > struct litest_device *dev = litest_current_device(); > @@ -141,33 +174,42 @@ START_TEST(pad_num_buttons) > } > END_TEST > > -START_TEST(pad_button) > +START_TEST(pad_button_intuos) > { > +#if !HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE > struct litest_device *dev = litest_current_device(); > struct libinput *li = dev->libinput; > unsigned int code; > unsigned int expected_number = 0; > struct libinput_event *ev; > struct libinput_event_tablet_pad *pev; > + unsigned int count; > + > + /* Intuos button mapping is sequential up from BTN_0 and continues > + * with BTN_A */ > + > + if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_0)) > + return; > > litest_drain_events(li); > > - for (code = BTN_0; code < KEY_MAX; code++) { > - if (!libevdev_has_event_code(dev->evdev, EV_KEY, code)) > + for (code = BTN_0; code < BTN_DIGI; code++) { > + /* SKip over the BTN_MOUSE and BTN_JOYSTICK range */ > + if (code >= BTN_MOUSE && code < BTN_A) { > + ck_assert(!libevdev_has_event_code(dev->evdev, > + EV_KEY, code)); Will this get tripped up by the ExpressKey remote? It uses BTN_BASE and BTN_BASE2 for its two highest-numbered buttons (following BTN_0..BTN_9, BTN_A..BTN_Z). No other device uses those codes from what I can tell, but a hypothetical future tablet with enough buttons would. > continue; > - > - litest_button_click(dev, code, 1); > - litest_button_click(dev, code, 0); > - libinput_dispatch(li); > - > - switch (code) { > - case BTN_STYLUS: > - litest_assert_empty_queue(li); > - continue; > - default: > - break; > } > > + if (!libevdev_has_event_code(dev->evdev, EV_KEY, code)) > + return; > + > + litest_button_click(dev, code, 1); > + litest_button_click(dev, code, 0); > + libinput_dispatch(li); > + > + count++; > + > ev = libinput_get_event(li); > pev = litest_is_pad_button_event(ev, > expected_number, > @@ -186,6 +228,102 @@ START_TEST(pad_button) > } > > litest_assert_empty_queue(li); > + > + ck_assert_int_gt(count, 3); > +#endif > +} > +END_TEST > + > +START_TEST(pad_button_bamboo) > +{ > +#if !HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE > + struct litest_device *dev = litest_current_device(); > + struct libinput *li = dev->libinput; > + unsigned int code; > + unsigned int expected_number = 0; > + struct libinput_event *ev; > + struct libinput_event_tablet_pad *pev; > + unsigned int count; > + > + if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_LEFT)) > + return; Pre-3.17 kernels combine the pen and pad on the same device. A device like the Intuos4 will declare the BTN_0 range for its ExpressKeys, as well as the BTN_LEFT range for its puck. Not sure if that'll be problematic... > + > + litest_drain_events(li); > + > + for (code = BTN_LEFT; code < BTN_JOYSTICK; code++) { > + if (!libevdev_has_event_code(dev->evdev, EV_KEY, code)) > + return; > + > + litest_button_click(dev, code, 1); > + litest_button_click(dev, code, 0); > + libinput_dispatch(li); > + > + count++; > + > + ev = libinput_get_event(li); > + pev = litest_is_pad_button_event(ev, > + expected_number, > + > LIBINPUT_BUTTON_STATE_PRESSED); > + ev = libinput_event_tablet_pad_get_base_event(pev); > + libinput_event_destroy(ev); > + > + ev = libinput_get_event(li); > + pev = litest_is_pad_button_event(ev, > + expected_number, > + > LIBINPUT_BUTTON_STATE_RELEASED); > + ev = libinput_event_tablet_pad_get_base_event(pev); > + libinput_event_destroy(ev); > + > + expected_number++; > + } > + > + litest_assert_empty_queue(li); > + > + ck_assert_int_gt(count, 3); > +#endif > +} > +END_TEST > + > +START_TEST(pad_button_libwacom) > +{ > +#if HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE > + struct litest_device *dev = litest_current_device(); > + struct libinput *li = dev->libinput; > + WacomDeviceDatabase *db = NULL; > + WacomDevice *wacom = NULL; > + > + db = libwacom_database_new(); > + assert(db); > + > + wacom = libwacom_new_from_usbid(db, > + libevdev_get_id_vendor(dev->evdev), > + libevdev_get_id_product(dev->evdev), > + NULL); > + assert(wacom); > + > + litest_drain_events(li); > + > + for (int i = 0; i < libwacom_get_num_buttons(wacom); i++) { > + unsigned int code; > + > + code = libwacom_get_button_evdev_code(wacom, 'A' + i); > + > + litest_button_click(dev, code, 1); > + litest_button_click(dev, code, 0); > + libinput_dispatch(li); > + > + litest_assert_pad_button_event(li, > + i, > + LIBINPUT_BUTTON_STATE_PRESSED); > + litest_assert_pad_button_event(li, > + i, > + > LIBINPUT_BUTTON_STATE_RELEASED); > + } > + > + > + libwacom_destroy(wacom); > + libwacom_database_destroy(db); > +#endif > } > END_TEST > > @@ -788,7 +926,10 @@ litest_setup_tests_pad(void) > litest_add("pad:time", pad_time, LITEST_TABLET_PAD, LITEST_ANY); > > litest_add("pad:button", pad_num_buttons, LITEST_TABLET_PAD, > LITEST_ANY); > - litest_add("pad:button", pad_button, LITEST_TABLET_PAD, LITEST_ANY); > + litest_add("pad:button", pad_num_buttons_libwacom, LITEST_TABLET_PAD, > LITEST_ANY); > + litest_add("pad:button", pad_button_intuos, LITEST_TABLET_PAD, > LITEST_ANY); > + litest_add("pad:button", pad_button_bamboo, LITEST_TABLET_PAD, > LITEST_ANY); > + litest_add("pad:button", pad_button_libwacom, LITEST_TABLET_PAD, > LITEST_ANY); > litest_add("pad:button", pad_button_mode_groups, LITEST_TABLET_PAD, > LITEST_ANY); > > litest_add("pad:ring", pad_has_ring, LITEST_RING, LITEST_ANY); > -- > 2.13.6 > Those concerns aside, for the set: Acked-by: Jason Gerecke <jason.gere...@wacom.com> Jason --- Now instead of four in the eights place / you’ve got three, ‘Cause you added one / (That is to say, eight) to the two, / But you can’t take seven from three, / So you look at the sixty-fours.... _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel