Signed-off-by: Stephen Chandler Paul <[email protected]>
---
 src/evdev-tablet.c     | 42 +++++++++++++++++++++++++++++++
 src/evdev-tablet.h     |  1 +
 src/libinput-private.h |  1 +
 src/libinput.c         |  7 ++++++
 src/libinput.h         | 26 +++++++++++++++++++
 test/tablet.c          | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 145 insertions(+)

diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 6ae6844..f56d7f4 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -298,6 +298,40 @@ tablet_get_tool(struct tablet_dispatch *tablet,
                        .refcount = 1,
                };
 
+               /* Determine the axis capabilities of the tool. Here's a break
+                * down of the heuristics used here:
+                * - The Wacom art pen supports all of the extra axes, along
+                *   with rotation
+                * - All of normal pens and the airbrush support all of the
+                *   extra axes if the tablet can report them
+                * - All of the mouse like devices don't really report any of
+                *   the extra axes except for rotation.
+                * (as of writing this comment, rotation isn't supported, so you
+                * won't see the mouse or art pen here)
+                */
+               switch (type) {
+               case LIBINPUT_TOOL_PEN:
+               case LIBINPUT_TOOL_ERASER:
+               case LIBINPUT_TOOL_PENCIL:
+               case LIBINPUT_TOOL_BRUSH:
+               case LIBINPUT_TOOL_AIRBRUSH:
+                       if (bit_is_set(tablet->axis_caps,
+                                      LIBINPUT_TOOL_AXIS_FLAG_PRESSURE))
+                               set_bit(tool->axis_caps,
+                                       LIBINPUT_TOOL_AXIS_FLAG_PRESSURE);
+                       if (bit_is_set(tablet->axis_caps,
+                                      LIBINPUT_TOOL_AXIS_FLAG_DISTANCE))
+                               set_bit(tool->axis_caps,
+                                       LIBINPUT_TOOL_AXIS_FLAG_DISTANCE);
+                       if (bit_is_set(tablet->axis_caps,
+                                      LIBINPUT_TOOL_AXIS_FLAG_TILT))
+                               set_bit(tool->axis_caps,
+                                       LIBINPUT_TOOL_AXIS_FLAG_TILT);
+                       break;
+               default:
+                       break;
+               }
+
                list_insert(tool_list, &tool->link);
        }
 
@@ -507,6 +541,14 @@ tablet_init(struct tablet_dispatch *tablet,
        tablet->current_tool_type = LIBINPUT_TOOL_NONE;
        list_init(&tablet->tool_list);
 
+       if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_PRESSURE))
+               set_bit(tablet->axis_caps, LIBINPUT_TOOL_AXIS_FLAG_PRESSURE);
+       if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_DISTANCE))
+               set_bit(tablet->axis_caps, LIBINPUT_TOOL_AXIS_FLAG_DISTANCE);
+       if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_TILT_X) &&
+           libevdev_has_event_code(device->evdev, EV_ABS, ABS_TILT_Y))
+               set_bit(tablet->axis_caps, LIBINPUT_TOOL_AXIS_FLAG_TILT);
+
        tablet_mark_all_axes_changed(tablet, device);
 
        return 0;
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index d16aef3..be2d09a 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -49,6 +49,7 @@ struct tablet_dispatch {
        unsigned char status;
        unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_AXIS_CNT)];
        double axes[LIBINPUT_TABLET_AXIS_CNT];
+       unsigned char axis_caps[NCHARS(LIBINPUT_TOOL_AXIS_FLAG_CNT)];
 
        /* Only used for tablets that don't report serial numbers */
        struct list tool_list;
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 8187564..bdef330 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -108,6 +108,7 @@ struct libinput_tool {
        struct list link;
        uint32_t serial;
        enum libinput_tool_type type;
+       unsigned char axis_caps[NCHARS(LIBINPUT_TOOL_AXIS_FLAG_CNT)];
        int refcount;
        void *user_data;
 };
diff --git a/src/libinput.c b/src/libinput.c
index 68187d8..560fedd 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -599,6 +599,13 @@ libinput_tool_get_serial(struct libinput_tool *tool)
        return tool->serial;
 }
 
+LIBINPUT_EXPORT int
+libinput_tool_has_axis(struct libinput_tool *tool,
+                      enum libinput_tool_axis_flag axis)
+{
+       return bit_is_set(tool->axis_caps, axis);
+}
+
 LIBINPUT_EXPORT void
 libinput_tool_set_user_data(struct libinput_tool *tool,
                            void *user_data)
diff --git a/src/libinput.h b/src/libinput.h
index 1d4952b..63c5ad3 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -214,6 +214,19 @@ enum libinput_tool_type {
 };
 
 /**
+ * @ingroup device
+ *
+ * A series of flags for representing which kinds of axes a tablet tool can
+ * support.
+ */
+enum libinput_tool_axis_flag {
+       LIBINPUT_TOOL_AXIS_FLAG_PRESSURE = 0,
+       LIBINPUT_TOOL_AXIS_FLAG_DISTANCE = 1,
+       LIBINPUT_TOOL_AXIS_FLAG_TILT = 2,
+       LIBINPUT_TOOL_AXIS_FLAG_CNT = 3,
+};
+
+/**
  * @ingroup base
  *
  * Event type for events returned by libinput_get_event().
@@ -1010,6 +1023,19 @@ libinput_tool_ref(struct libinput_tool *tool);
 /**
  * @ingroup event_tablet
  *
+ * Return whether or not a tablet tool supports the specified axis
+ *
+ * @param tool The tool to check the axis capabilities of
+ * @param axis The axis to check for support
+ * @return Whether or not the axis is supported
+ */
+int
+libinput_tool_has_axis(struct libinput_tool *tool,
+                      enum libinput_tool_axis_flag axis);
+
+/**
+ * @ingroup event_tablet
+ *
  * Decrement the ref count of tool by one. When the ref count of tool reaches 
0,
  * the memory allocated for tool will be freed.
  *
diff --git a/test/tablet.c b/test/tablet.c
index 60a4240..d4624a5 100644
--- a/test/tablet.c
+++ b/test/tablet.c
@@ -758,10 +758,78 @@ START_TEST(tools_without_serials)
 }
 END_TEST
 
+START_TEST(tool_capabilities)
+{
+       struct libinput *li = litest_create_context();
+       struct litest_device *intuos;
+       struct litest_device *bamboo;
+       struct libinput_event *event;
+
+       /* The axis capabilities of a tool can differ depending on the type of
+        * tablet the tool is being used with */
+       bamboo = litest_create_device_with_overrides(LITEST_WACOM_BAMBOO,
+                                                    NULL,
+                                                    NULL,
+                                                    NULL,
+                                                    NULL);
+       intuos = litest_create_device_with_overrides(LITEST_WACOM_INTUOS,
+                                                    NULL,
+                                                    NULL,
+                                                    NULL,
+                                                    NULL);
+
+       litest_event(bamboo, EV_KEY, BTN_TOOL_PEN, 1);
+       litest_event(bamboo, EV_SYN, SYN_REPORT, 0);
+
+       libinput_dispatch(li);
+       while ((event = libinput_get_event(li))) {
+               if (libinput_event_get_type(event) ==
+                   LIBINPUT_EVENT_TABLET_PROXIMITY_IN) {
+                       struct libinput_event_tablet *t =
+                               libinput_event_get_tablet_event(event);
+                       struct libinput_tool *tool =
+                               libinput_event_tablet_get_tool(t);
+
+                       ck_assert(libinput_tool_has_axis(
+                               tool, LIBINPUT_TOOL_AXIS_FLAG_PRESSURE));
+                       ck_assert(!libinput_tool_has_axis(
+                               tool, LIBINPUT_TOOL_AXIS_FLAG_TILT));
+                       ck_assert(libinput_tool_has_axis(
+                               tool, LIBINPUT_TOOL_AXIS_FLAG_DISTANCE));
+               }
+
+               libinput_event_destroy(event);
+       }
+
+       litest_event(intuos, EV_KEY, BTN_TOOL_PEN, 1);
+       litest_event(intuos, EV_SYN, SYN_REPORT, 0);
+
+       while ((event = libinput_get_event(li))) {
+               if (libinput_event_get_type(event) ==
+                   LIBINPUT_EVENT_TABLET_PROXIMITY_IN) {
+                       struct libinput_event_tablet *t =
+                               libinput_event_get_tablet_event(event);
+                       struct libinput_tool *tool =
+                               libinput_event_tablet_get_tool(t);
+
+                       ck_assert(libinput_tool_has_axis(
+                               tool, LIBINPUT_TOOL_AXIS_FLAG_PRESSURE));
+                       ck_assert(libinput_tool_has_axis(
+                               tool, LIBINPUT_TOOL_AXIS_FLAG_DISTANCE));
+                       ck_assert(libinput_tool_has_axis(
+                               tool, LIBINPUT_TOOL_AXIS_FLAG_TILT));
+               }
+
+               libinput_event_destroy(event);
+       }
+}
+END_TEST
+
 int
 main(int argc, char **argv)
 {
        litest_add("tablet:tool", tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, 
LITEST_ANY);
+       litest_add_no_device("tablet:tool", tool_capabilities);
        litest_add("tablet:tool_serial", tool_serial, LITEST_TABLET | 
LITEST_TOOL_SERIAL, LITEST_ANY);
        litest_add("tablet:tool_serial", serial_changes_tool, LITEST_TABLET | 
LITEST_TOOL_SERIAL, LITEST_ANY);
        litest_add("tablet:tool_serial", invalid_serials, LITEST_TABLET | 
LITEST_TOOL_SERIAL, LITEST_ANY);
-- 
1.8.5.5

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to