Tracking is done of serial/tool type, so it is only really notified on
tool changes.

Signed-off-by: Carlos Garnacho <carl...@gnome.org>
---
 src/evdev-tablet.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/evdev-tablet.h |  10 +++++
 2 files changed, 113 insertions(+), 6 deletions(-)

diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 02877d9..fcd3396 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -52,6 +52,85 @@ tablet_process_absolute(struct tablet_dispatch *tablet,
 }
 
 static void
+tablet_update_tool(struct tablet_dispatch *tablet,
+                  uint32_t tool,
+                  uint32_t enabled)
+{
+       assert(tool != LIBINPUT_TOOL_NONE);
+
+       if (enabled && tool != tablet->state.tool) {
+               tablet->state.tool = tool;
+               tablet_set_status(tablet, TABLET_INTERACTED);
+       } else if (!enabled && tool == tablet->state.tool) {
+               tablet->state.tool = LIBINPUT_TOOL_NONE;
+               tablet_unset_status(tablet, TABLET_INTERACTED);
+       }
+}
+
+static void
+tablet_process_key(struct tablet_dispatch *tablet,
+                  struct evdev_device *device,
+                  struct input_event *e,
+                  uint32_t time)
+{
+       switch (e->code) {
+       case BTN_TOOL_PEN:
+       case BTN_TOOL_RUBBER:
+       case BTN_TOOL_BRUSH:
+       case BTN_TOOL_PENCIL:
+       case BTN_TOOL_AIRBRUSH:
+       case BTN_TOOL_FINGER:
+       case BTN_TOOL_MOUSE:
+       case BTN_TOOL_LENS:
+               /* These codes have an equivalent libinput_tool value */
+               tablet_update_tool(tablet, e->code, e->value);
+               break;
+       default:
+               break;
+       }
+}
+
+static void
+tablet_process_misc(struct tablet_dispatch *tablet,
+                   struct evdev_device *device,
+                   struct input_event *e,
+                   uint32_t time)
+{
+       switch (e->code) {
+       case MSC_SERIAL:
+               tablet->state.tool_serial = e->value;
+               break;
+       default:
+               log_info("Unhandled MSC event code 0x%x\n", e->code);
+               break;
+       }
+}
+
+static void
+tablet_check_notify_tool(struct tablet_dispatch *tablet,
+                        struct evdev_device *device,
+                        uint32_t time,
+                        int post_check)
+{
+       struct libinput_device *base = &device->base;
+
+       if (tablet->state.tool == tablet->prev_state.tool)
+               return;
+
+       if (tablet->state.tool == LIBINPUT_TOOL_NONE) {
+               /* Wait for post-check */
+               if (post_check)
+                       return;
+       } else if (post_check) {
+               /* Already handled in pre-check */
+               return;
+       }
+
+       pointer_notify_tool_update(
+               base, time, tablet->state.tool, tablet->state.tool_serial);
+}
+
+static void
 tablet_flush(struct tablet_dispatch *tablet,
             struct evdev_device *device,
             uint32_t time)
@@ -59,14 +138,25 @@ tablet_flush(struct tablet_dispatch *tablet,
        struct libinput_device *base = &device->base;
        li_fixed_t x, y;
 
-       if (tablet_has_status(tablet, TABLET_UPDATED)) {
-               /* FIXME: apply hysteresis, calibration */
-               x = li_fixed_from_int(device->abs.x);
-               y = li_fixed_from_int(device->abs.y);
+       /* pre-update notifications */
+       tablet_check_notify_tool(tablet, device, time, 0);
+
+       if (tablet->state.tool != LIBINPUT_TOOL_NONE) {
+               if (tablet_has_status(tablet, TABLET_UPDATED)) {
+                       /* FIXME: apply hysteresis, calibration */
+                       x = li_fixed_from_int(device->abs.x);
+                       y = li_fixed_from_int(device->abs.y);
 
-               pointer_notify_motion_absolute(base, time, x, y);
-               tablet_unset_status(tablet, TABLET_UPDATED);
+                       pointer_notify_motion_absolute(base, time, x, y);
+                       tablet_unset_status(tablet, TABLET_UPDATED);
+               }
        }
+
+       /* post-update notifications */
+       tablet_check_notify_tool(tablet, device, time, 1);
+
+       /* replace previous state */
+       tablet->prev_state = tablet->state;
 }
 
 static void
@@ -82,6 +172,12 @@ tablet_process(struct evdev_dispatch *dispatch,
        case EV_ABS:
                tablet_process_absolute(tablet, device, e, time);
                break;
+       case EV_KEY:
+               tablet_process_key(tablet, device, e, time);
+               break;
+       case EV_MSC:
+               tablet_process_misc(tablet, device, e, time);
+               break;
        case EV_SYN:
                tablet_flush(tablet, device, time);
                break;
@@ -112,6 +208,7 @@ tablet_init(struct tablet_dispatch *tablet,
        tablet->base.interface = &tablet_interface;
        tablet->device = device;
        tablet->status = TABLET_NONE;
+       tablet->state.tool = LIBINPUT_TOOL_NONE;
 
        return 0;
 }
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index e1479fa..7b7b066 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -29,11 +29,21 @@
 enum tablet_status {
        TABLET_NONE = 0,
        TABLET_UPDATED = 1 << 0,
+       TABLET_INTERACTED = 1 << 1,
+};
+
+struct device_state {
+       enum libinput_tool tool;
+       int32_t tool_serial;
 };
 
 struct tablet_dispatch {
        struct evdev_dispatch base;
        struct evdev_device *device;
+
+       struct device_state state;
+       struct device_state prev_state;
+
        enum tablet_status status;
 };
 
-- 
1.9.0

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to