[PATCH libinput 5/7] pad: Add a new API for modes and mode groups

Jason Gerecke killertofu at gmail.com
Wed Jun 8 01:33:19 UTC 2016


On Sun, Jun 5, 2016 at 11:50 PM, Peter Hutterer
<peter.hutterer at who-t.net> wrote:
> Move mode control to libinput. This reduces some flexibility on what we can do
> with modes but makes it a lot easier for anyone to implement modes correctly
> and have the LEDs apply appropriately, etc. Let's go with the option to make
> the 95% use-case easy. Note: whether the mode is actually used is up to the
> caller, e.g.  under Windows and OS X the mode only applies to the
> rings/strips, not the buttons.
>
> A tablet pad has 1 or more mode groups, all buttons/ring/strips are assigned
> to a mode group. That group has a numeric mode index and is hooked to the
> LEDs. libinput will switch the LEDs accordingly.
>
> The mode group is a separate object. This allows for better APIs when it comes
> to:
> * checking whether a button/ring/strip is part of a mode group
> * checking whether a button will trigger a mode transition
> * checking which mode transition will happen
>
> and in the future potentially:
> * setting which button should change the mode transition
> * changing what type of mode transition should happen.
> * moving a button from one mode group to the other
>
> This patch adds the basic scaffolding, without any real implementation.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
>  doc/tablet-support.dox |  59 ++++++++-
>  src/libinput-private.h |   6 +
>  src/libinput.c         | 128 +++++++++++++++++++
>  src/libinput.h         | 324 +++++++++++++++++++++++++++++++++++++++++++++++++
>  src/libinput.sym       |  16 +++
>  test/litest.c          |   3 +
>  tools/event-debug.c    |  61 ++++++++--
>  tools/event-gui.c      |   1 +
>  8 files changed, 586 insertions(+), 12 deletions(-)
>
> diff --git a/doc/tablet-support.dox b/doc/tablet-support.dox
> index c555cea..b7267a8 100644
> --- a/doc/tablet-support.dox
> +++ b/doc/tablet-support.dox
> @@ -240,8 +240,7 @@ tablet.
>
>  Some buttons may have expected default behaviors. For example, on Wacom
>  Intuos Pro series tablets, the button inside the touch ring is expected to
> -switch between a mode switch. Mode switching is a feature implemented in the
> -caller and libinput does not provide specific handling. Callers should use
> +switch between a mode switch, see @ref tablet-pad-modes. Callers should use

This was an issue in the prior version but "switch between a mode
switch" doesn't really make sense. Perhaps "switch between modes"
would be clearer?

>  external sources like libwacom to identify which buttons have semantic
>  behaviors.
>
> @@ -276,4 +275,60 @@ symmetric and thus do not support left-handed mode. libinput requires
>  libwacom to determine if a tablet is capable of being switched to
>  left-handed mode.
>
> + at section tablet-pad-modes Tablet pad modes
> +
> +Tablet pad modes are virtual groupings of button, ring and strip
> +functionality. A caller may assign different functionalities depending on
> +the mode the tablet is in. For example, in mode 0 the touch ring may emulate
> +scrolling, in mode 1 the touch ring may emulate zooming, etc. libinput
> +handles the modes and mode switching but does not assign specific
> +functionality to buttons, rings or strips based on the mode. It is up to the
> +caller to decide whether the mode only applies to buttons, rings and strips
> +or only to rings and strips (this is the case with the Wacom OS X and
> +Windows driver).
> +
> +The availability of modes on a touchpad usually depends on visual feedback
> +such as LEDs around the touch ring. If no visual feedback is available, only
> +one mode may be available.
> +
> +Mode switching is controlled by libinput and usually toggled by one or
> +more buttons on the device. For example, on the Wacom Intuos 4, 5, and
> +Pro series tablets the mode button is the button centered in the touch
> +ring and toggles the modes sequentially. On the Wacom Cintiq 24HD the
> +three buttons next to each touch ring allow for directly changing the
> +mode to the desired setting.
> +
> +Multiple modes may exist on the tablet, libinput uses the term "mode group"
> +for such groupings of buttons that share a mode and mode toggle. For
> +example, the Wacom Cintiq 24HD has two separate mode groups, one for the
> +left set of buttons, strips, and touch rings and one for the right set.
> +libinput handles the mode groups independently and returns the mode for each
> +button as appropriate. The mode group is static for the lifetime of the
> +device.
> +
> + at image html tablet-intuos-modes.svg "Modes on an Intuos Pro-like tablet"
> +
> +In the image above, the Intuos Pro-like tablet provides 4 LEDs to indicate
> +the currently active modes. The button inside the touch ring cycles through
> +the modes in a clockwise fashion. The upper-right LED indicates that the
> +currently active mode is 1, based on 0-indexed mode numbering.
> +libinput_event_tablet_pad_get_mode() would thus return 1 for all button and
> +ring events on this tablet. When the center button is pressed, the mode
> +switches to mode 2, the LED changes to the bottom-right and
> +libinput_event_tablet_pad_get_mode() returns 2 for the center button event
> +and all subsequent events.
> +
> + at image html tablet-cintiq24hd-modes.svg "Modes on an Cintiq 24HD-like tablet"
> +
> +In the image above, the Cintiq 24HD-like tablet provides 3 LEDs on each side
> +of the tablet to indicate the currently active mode for that group of
> +buttons and the respective ring. The buttons next to the touch ring select
> +the mode directly. The two LEDs indicate that the mode for the left set of
> +buttons is currently 0, the mode for the right set of buttons is currently
> +1, based on 0-indexed mode numbering. libinput_event_tablet_pad_get_mode()
> +would thus return 0 for all button and ring events on the left and 1 for all
> +button and ring events on the right. When one of the three mode toggle
> +buttons on the right is pressed, the right mode switches to that button's
> +mode but the left mode remains unchanged.
> +
>  */
> diff --git a/src/libinput-private.h b/src/libinput-private.h
> index 1052212..98cb419 100644
> --- a/src/libinput-private.h
> +++ b/src/libinput-private.h
> @@ -329,6 +329,12 @@ struct libinput_tablet_tool {
>         bool has_pressure_offset;
>  };
>
> +struct libinput_tablet_pad_mode_group {
> +       struct list link;
> +       int refcount;
> +       void *user_data;
> +};
> +
>  struct libinput_event {
>         enum libinput_event_type type;
>         struct libinput_device *device;
> diff --git a/src/libinput.c b/src/libinput.c
> index 0f676a3..e174aae 100644
> --- a/src/libinput.c
> +++ b/src/libinput.c
> @@ -140,6 +140,8 @@ struct libinput_event_tablet_tool {
>
>  struct libinput_event_tablet_pad {
>         struct libinput_event base;
> +       unsigned int mode;
> +       struct libinput_tablet_pad_mode_group *mode_group;
>         uint64_t time;
>         struct {
>                 uint32_t button;
> @@ -2580,6 +2582,7 @@ event_type_to_str(enum libinput_event_type type)
>         CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_BUTTON);
>         CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_RING);
>         CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_STRIP);
> +       CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_MODE);
>         CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN);
>         CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE);
>         CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_END);
> @@ -2829,6 +2832,105 @@ libinput_device_tablet_pad_get_num_strips(struct libinput_device *device)
>         return evdev_device_tablet_pad_get_num_strips((struct evdev_device *)device);
>  }
>
> +LIBINPUT_EXPORT int
> +libinput_device_tablet_pad_get_num_mode_groups(struct libinput_device *device)
> +{
> +       return 0;
> +}
> +
> +LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group*
> +libinput_device_tablet_pad_get_mode_group(struct libinput_device *device,
> +                                         unsigned int index)
> +{
> +       return NULL;
> +}
> +
> +LIBINPUT_EXPORT unsigned int
> +libinput_tablet_pad_mode_group_get_num_modes(
> +                                    struct libinput_tablet_pad_mode_group *group)
> +{
> +       return 1;
> +}
> +
> +LIBINPUT_EXPORT unsigned int
> +libinput_tablet_pad_mode_group_get_mode(struct libinput_tablet_pad_mode_group *group)
> +{
> +       return 1;
> +}
> +
> +LIBINPUT_EXPORT int
> +libinput_tablet_pad_mode_group_has_button(struct libinput_tablet_pad_mode_group *group,
> +                                         unsigned int button)
> +{
> +       return 1;
> +}
> +
> +LIBINPUT_EXPORT int
> +libinput_tablet_pad_mode_group_has_ring(struct libinput_tablet_pad_mode_group *group,
> +                                       unsigned int ring)
> +{
> +       return 1;
> +}
> +
> +LIBINPUT_EXPORT int
> +libinput_tablet_pad_mode_group_has_strip(struct libinput_tablet_pad_mode_group *group,
> +                                        unsigned int strip)
> +{
> +       return 1;
> +}
> +
> +LIBINPUT_EXPORT int
> +libinput_tablet_pad_mode_group_button_is_toggle(struct libinput_tablet_pad_mode_group *group,
> +                                               unsigned int button)
> +{
> +       return 0;
> +}
> +
> +LIBINPUT_EXPORT unsigned int
> +libinput_tablet_pad_mode_group_button_get_target_mode(struct libinput_tablet_pad_mode_group *group,
> +                                                     unsigned int button)
> +{
> +       return 0;
> +}
> +
> +LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group *
> +libinput_tablet_pad_mode_group_ref(
> +                       struct libinput_tablet_pad_mode_group *group)
> +{
> +       group->refcount++;
> +       return group;
> +}
> +
> +LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group *
> +libinput_tablet_pad_mode_group_unref(
> +                       struct libinput_tablet_pad_mode_group *group)
> +{
> +       assert(group->refcount > 0);
> +
> +       group->refcount--;
> +       if (group->refcount > 0)
> +               return group;
> +
> +       list_remove(&group->link);
> +       free(group);
> +       return NULL;
> +}
> +
> +LIBINPUT_EXPORT void
> +libinput_tablet_pad_mode_group_set_user_data(
> +                       struct libinput_tablet_pad_mode_group *group,
> +                       void *user_data)
> +{
> +       group->user_data = user_data;
> +}
> +
> +LIBINPUT_EXPORT void *
> +libinput_tablet_pad_mode_group_get_user_data(
> +                       struct libinput_tablet_pad_mode_group *group)
> +{
> +       return group->user_data;
> +}
> +
>  LIBINPUT_EXPORT struct libinput_event *
>  libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event)
>  {
> @@ -2989,6 +3091,32 @@ libinput_event_tablet_pad_get_button_state(struct libinput_event_tablet_pad *eve
>         return event->button.state;
>  }
>
> +LIBINPUT_EXPORT unsigned int
> +libinput_event_tablet_pad_get_mode(struct libinput_event_tablet_pad *event)
> +{
> +       require_event_type(libinput_event_get_context(&event->base),
> +                          event->base.type,
> +                          0,
> +                          LIBINPUT_EVENT_TABLET_PAD_RING,
> +                          LIBINPUT_EVENT_TABLET_PAD_STRIP,
> +                          LIBINPUT_EVENT_TABLET_PAD_BUTTON);
> +
> +       return event->mode;
> +}
> +
> +LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group *
> +libinput_event_tablet_pad_get_mode_group(struct libinput_event_tablet_pad *event)
> +{
> +       require_event_type(libinput_event_get_context(&event->base),
> +                          event->base.type,
> +                          NULL,
> +                          LIBINPUT_EVENT_TABLET_PAD_RING,
> +                          LIBINPUT_EVENT_TABLET_PAD_STRIP,
> +                          LIBINPUT_EVENT_TABLET_PAD_BUTTON);
> +
> +       return event->mode_group;
> +}
> +
>  LIBINPUT_EXPORT uint32_t
>  libinput_event_tablet_pad_get_time(struct libinput_event_tablet_pad *event)
>  {
> diff --git a/src/libinput.h b/src/libinput.h
> index 212bf4a..88345ba 100644
> --- a/src/libinput.h
> +++ b/src/libinput.h
> @@ -356,6 +356,277 @@ enum libinput_tablet_tool_tip_state {
>  };
>
>  /**
> + * @defgroup tablet_pad_modes Tablet pad modes
> + *
> + * Handling the virtual mode groups of buttons, strips and rings on tablet
> + * pad devices. See @ref tablet-pad-modes for details.
> + */
> +
> +/**
> + * @ingroup tablet_pad_modes
> + * @struct libinput_tablet_pad_mode_group
> + *
> + * A mode on a tablet pad is a virtual grouping of functionality, usually
> + * based on some visual feedback like LEDs on the pad. The set of buttons,
> + * rings and strips that share the same mode are a "mode group". Whenever
> + * the mode changes, all buttons, rings and strips within this mode group
> + * are affected. See @ref tablet-pad-modes for detail.
> + *
> + * Most tablets only have a single mode group, some tablets provide multiple
> + * mode groups through independent banks of LEDs (e.g. the Wacom Cintiq
> + * 24HD). libinput guarantees that at least one mode group is always
> + * available.
> + *
> + * This struct is refcounted, use libinput_tablet_pad_mode_group_ref() and
> + * libinput_tablet_pad_mode_group_unref().
> + */
> +struct libinput_tablet_pad_mode_group;
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Most devices only provide a single mode group, however devices such as
> + * the Wacom Cintiq 22HD provide two mode groups. If multiple mode groups
> + * are available, a caller should use
> + * libinput_tablet_pad_mode_group_has_button(),
> + * libinput_tablet_pad_mode_group_has_ring() and
> + * libinput_tablet_pad_mode_group_has_strip() to associate each button,
> + * ring and strip with the correct mode group.
> + *
> + * @return the number of mode groups available on this device
> + */
> +int
> +libinput_device_tablet_pad_get_num_mode_groups(struct libinput_device *device);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * The returned mode group is not refcounted and may become invalid after
> + * the next call to libinput. Use libinput_tablet_pad_mode_group_ref() and
> + * libinput_tablet_pad_mode_group_unref() to continue using the handle
> + * outside of the immediate scope.
> + *
> + * While at least one reference is kept by the caller, the returned mode
> + * group will be identical for each subsequent call of this function with
> + * the same index and that same struct is returned from
> + * libinput_event_tablet_pad_get_mode_group(), provided the event was
> + * generated by this mode group.
> + *
> + * @param device A device with the @ref LIBINPUT_DEVICE_CAP_TABLET_PAD
> + * capability
> + * @param index A mode group index less
> + * @return the mode group with the given index or NULL if an invalid index
> + * is given.
> + */
> +struct libinput_tablet_pad_mode_group*
> +libinput_device_tablet_pad_get_mode_group(struct libinput_device *device,
> +                                         unsigned int index);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * The returned number is the same index as passed to
> + * libinput_device_tablet_pad_get_mode_group(). For tablets with only one
> + * mode this number is always 0
> + *
> + * @param group A previously obtained mode group
> + * @return the numeric index this mode group represents, starting at 0
> + */
> +unsigned int
> +libinput_tablet_pad_mode_group_get_index(struct libinput_tablet_pad_mode_group *group);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Query the mode group for the number of available modes. This number is
> + * usually decided by the number of physical LEDs available on the device.
> + * Different mode groups may have a different number of modes.
> + * Use libinput_tablet_pad_mode_group_get_mode() to get the currently active
> + * mode.
> + *
> + * libinput guarantees that at least one mode is available. A device without
> + * mode switching capability has a single mode group and a single mode.
> + *
> + * @param group A previously obtained mode group
> + * @return the number of modes available in this mode group
> + */
> +unsigned int
> +libinput_tablet_pad_mode_group_get_num_modes(struct libinput_tablet_pad_mode_group *group);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Return the current mode this mode group is in. Note that the returned
> + * mode is the mode valid as of completing the last libinput_dispatch().
> + * The returned mode may thus be different to the mode returned by
> + * libinput_event_tablet_pad_get_mode().
> + *
> + * For example, if the mode was toggled three times between the call to
> + * libinput_dispatch(), this function returns the third mode but the events
> + * in the event queue will return the modes 1, 2 and 3, respectively.
> + *
> + * @param group A previously obtained mode group
> + * @return the numeric index of the current mode in this group, starting at 0
> + */
> +unsigned int
> +libinput_tablet_pad_mode_group_get_mode(struct libinput_tablet_pad_mode_group *group);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Devices without mode switching capabilies return true for every button.
> + *
> + * @param group A previously obtained mode group
> + * @param button A button index, starting at 0
> + * @return true if the given button index is part of this mode group or
> + * false otherwise
> + */
> +int
> +libinput_tablet_pad_mode_group_has_button(struct libinput_tablet_pad_mode_group *group,
> +                                         unsigned int button);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Devices without mode switching capabilies return true for every ring.
> + *
> + * @param group A previously obtained mode group
> + * @param ring A ring index, starting at 0
> + * @return true if the given ring index is part of this mode group or
> + * false otherwise
> + */
> +int
> +libinput_tablet_pad_mode_group_has_ring(struct libinput_tablet_pad_mode_group *group,
> +                                         unsigned int ring);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Devices without mode switching capabilies return true for every strip.
> + *
> + * @param group A previously obtained mode group
> + * @param strip A strip index, starting at 0
> + * @return true if the given strip index is part of this mode group or
> + * false otherwise
> + */
> +int
> +libinput_tablet_pad_mode_group_has_strip(struct libinput_tablet_pad_mode_group *group,
> +                                         unsigned int strip);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Devices without mode switching capabilies return false for every button.
> + *
> + * @param group A previously obtained mode group
> + * @param button A button index, starting at 0
> + * @retval non-zero if the button is a mode toggle button for this group, or
> + * zero otherwise
> + */
> +int
> +libinput_tablet_pad_mode_group_button_is_toggle(struct libinput_tablet_pad_mode_group *group,
> +                                               unsigned int button);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Semantic mode values used by
> + * libinput_tablet_pad_mode_group_button_get_target_mode().
> + *
> + * A mode toggle button may either select a specific mode directly or
> + * toggle to the previous or next mode.
> + */
> +enum libinput_tablet_pad_mode_group_targets {
> +       /**
> +        * Marks the maximum target mode allowed for direct mode selection.
> +        * Any mode number equal or below should be considered a direct mode
> +        * selection. e.g. a value of 2 means "select mode index 2"
> +        */
> +       LIBINPUT_TABLET_PAD_MODE_GROUP_TARGET_MAX_DIRECT = 0xffff,
> +       LIBINPUT_TABLET_PAD_MODE_GROUP_TARGET_PREVIOUS = 0x10000,
> +       LIBINPUT_TABLET_PAD_MODE_GROUP_TARGET_NEXT,
> +};
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Return the target mode for this mode toggle button. If the returned value
> + * is less or equal to @ref
> + * LIBINPUT_TABLET_PAD_MODE_GROUP_TARGET_MAX_DIRECT, the target mode index
> + * is the returned value.
> + *
> + * It is an application bug to call this function for a button index that is
> + * not a mode toggle button. In that case, the return value is always 0.
> + *
> + * @param group A previously obtained mode group
> + * @param button A button index, starting at 0
> + * @return the mode selected when this mode toggle button is
> + * pressed, starting at index 0
> + * @retval LIBINPUT_TABLET_PAD_MODE_GROUP_TARGET_PREVIOUS  Upon pressing
> + * this button, the previous mode is selected
> + * @retval LIBINPUT_TABLET_PAD_MODE_GROUP_TARGET_NEXT  Upon pressing this button, the next mode is selected
> + */
> +unsigned int
> +libinput_tablet_pad_mode_group_button_get_target_mode(struct libinput_tablet_pad_mode_group *group,
> +                                                     unsigned int button);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Increase the refcount of the mode group. A mode device group will be
> + * freed whenever the refcount reaches 0.
> + *
> + * @param group A previously obtained mode group
> + * @return The passed mode group
> + */
> +struct libinput_tablet_pad_mode_group *
> +libinput_tablet_pad_mode_group_ref(
> +                       struct libinput_tablet_pad_mode_group *group);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Decrease the refcount of the mode group. A mode device group will be
> + * freed whenever the refcount reaches 0.
> + *
> + * @param group A previously obtained mode group
> + * @return NULL if the group was destroyed, otherwise the passed mode group
> + */
> +struct libinput_tablet_pad_mode_group *
> +libinput_tablet_pad_mode_group_unref(
> +                       struct libinput_tablet_pad_mode_group *group);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Set caller-specific data associated with this mode group. libinput does
> + * not manage, look at, or modify this data. The caller must ensure the
> + * data is valid.
> + *
> + * @param group A previously obtained mode group
> + * @param user_data Caller-specific data pointer
> + * @see libinput_tablet_pad_mode_group_get_user_data
> + *
> + */
> +void
> +libinput_tablet_pad_mode_group_set_user_data(
> +                       struct libinput_tablet_pad_mode_group *group,
> +                       void *user_data);
> +
> +/**
> + * @ingroup tablet_pad_modes
> + *
> + * Get the caller-specific data associated with this input device, if any.
> + *
> + * @param group A previously obtained mode group
> + * @return Caller-specific data pointer or NULL if none was set
> + * @see libinput_tablet_pad_mode_group_set_user_data
> + */
> +void *
> +libinput_tablet_pad_mode_group_get_user_data(
> +                       struct libinput_tablet_pad_mode_group *group);
> +
> +/**
>   * @ingroup base
>   *
>   * Event type for events returned by libinput_get_event().
> @@ -504,6 +775,19 @@ enum libinput_event_type {
>          */
>         LIBINPUT_EVENT_TABLET_PAD_STRIP,
>
> +       /**
> +        * A mode change on a device with the @ref
> +        * LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
> +        *
> +        * This event is triggered when the mode is changed through
> +        * external means. The event reflects a mode change (see @ref
> +        * tablet-pad-modes) occuring as a result other than that of

s/occuring/occurring/

> +        * pressing a mode toggle button.
> +        *
> +        * @note Support for this event is not yet implemented.
> +        */

Is this a nod to the EKR's read-only mode switches, or a hint about a
future API extension to allow compositors to set modes? If the former,
is there a reason callers would care that the device switched modes
instead of libinput? If the latter, wouldn't it make sense to leave
this event out for the time being?

> +       LIBINPUT_EVENT_TABLET_PAD_MODE,
> +
>         LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN = 800,
>         LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
>         LIBINPUT_EVENT_GESTURE_SWIPE_END,
> @@ -2380,6 +2664,46 @@ libinput_event_tablet_pad_get_button_state(struct libinput_event_tablet_pad *eve
>  /**
>   * @ingroup event_tablet_pad
>   *
> + * Returns the current mode this button, ring, or strip is considered in.
> + * The mode is a virtual grouping of functionality, usually based on some
> + * visual feedback like LEDs on the pad. See @ref tablet-pad-modes for
> + * details. Mode indices start at 0, a device that does not support modes
> + * always returns 0.
> + *
> + * Mode switching is controlled by libinput and more than one mode may exist
> + * on the tablet. This function returns the mode the button, ring or strip
> + * of this event is logically grouped in. If the button is the mode toggle

A little awkward to read. Perhaps "This function returns the mode of
the group that this event's button, ring, or strip is logically
grouped in."

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....

> + * button and the button event caused a new mode to be toggled, the mode
> + * returned is the new mode the button is in.
> + *
> + * @param event The libinput tablet pad event
> + * @return the current 0-indexed mode of this button, ring or strip
> + */
> +unsigned int
> +libinput_event_tablet_pad_get_mode(struct libinput_event_tablet_pad *event);
> +
> +/**
> + * @ingroup event_tablet_pad
> + *
> + * Returns the current mode group this button, ring, or strip is considered in.
> + * The mode is a virtual grouping of functionality, usually based on some
> + * visual feedback like LEDs on the pad. See @ref tablet-pad-modes for
> + * details.
> + *
> + * The returned mode group is not refcounted and may become invalid after
> + * the next call to libinput. Use libinput_tablet_pad_mode_group_ref() and
> + * libinput_tablet_pad_mode_group_unref() to continue using the handle
> + * outside of the immediate scope.
> + *
> + * @param event The libinput tablet pad event
> + * @return the current 0-indexed mode of this button, ring or strip
> + */
> +struct libinput_tablet_pad_mode_group *
> +libinput_event_tablet_pad_get_mode_group(struct libinput_event_tablet_pad *event);
> +
> +/**
> + * @ingroup event_tablet
> + *
>   * @param event The libinput tablet pad event
>   * @return The event time for this event
>   */
> diff --git a/src/libinput.sym b/src/libinput.sym
> index c6a0e4c..631c36d 100644
> --- a/src/libinput.sym
> +++ b/src/libinput.sym
> @@ -258,4 +258,20 @@ LIBINPUT_1.4 {
>         libinput_device_config_rotation_get_default_angle;
>         libinput_device_config_rotation_is_available;
>         libinput_device_config_rotation_set_angle;
> +       libinput_device_tablet_pad_get_mode_group;
> +       libinput_device_tablet_pad_get_num_mode_groups;
> +       libinput_event_tablet_pad_get_mode;
> +       libinput_event_tablet_pad_get_mode_group;
> +       libinput_tablet_pad_mode_group_button_get_target_mode;
> +       libinput_tablet_pad_mode_group_button_is_toggle;
> +       libinput_tablet_pad_mode_group_get_index;
> +       libinput_tablet_pad_mode_group_get_mode;
> +       libinput_tablet_pad_mode_group_get_num_modes;
> +       libinput_tablet_pad_mode_group_get_user_data;
> +       libinput_tablet_pad_mode_group_has_button;
> +       libinput_tablet_pad_mode_group_has_strip;
> +       libinput_tablet_pad_mode_group_has_ring;
> +       libinput_tablet_pad_mode_group_ref;
> +       libinput_tablet_pad_mode_group_set_user_data;
> +       libinput_tablet_pad_mode_group_unref;
>  } LIBINPUT_1.3;
> diff --git a/test/litest.c b/test/litest.c
> index 66f08f2..41a9308 100644
> --- a/test/litest.c
> +++ b/test/litest.c
> @@ -2097,6 +2097,9 @@ litest_event_type_str(struct libinput_event *event)
>         case LIBINPUT_EVENT_TABLET_PAD_STRIP:
>                 str = "TABLET PAD STRIP";
>                 break;
> +       case LIBINPUT_EVENT_TABLET_PAD_MODE:
> +               str = "TABLET PAD MODE";
> +               break;
>         }
>         return str;
>  }
> diff --git a/tools/event-debug.c b/tools/event-debug.c
> index a5608d2..c875035 100644
> --- a/tools/event-debug.c
> +++ b/tools/event-debug.c
> @@ -130,6 +130,9 @@ print_event_header(struct libinput_event *ev)
>         case LIBINPUT_EVENT_TABLET_PAD_STRIP:
>                 type = "TABLET_PAD_STRIP";
>                 break;
> +       case LIBINPUT_EVENT_TABLET_PAD_MODE:
> +               type = "TABLET_PAD_STRIP";
> +               break;
>         }
>
>         printf("%-7s    %-16s ", libinput_device_get_sysname(dev), type);
> @@ -232,16 +235,18 @@ print_device_notify(struct libinput_event *ev)
>
>         if (libinput_device_has_capability(dev,
>                                            LIBINPUT_DEVICE_CAP_TABLET_PAD)) {
> -               int nbuttons, nstrips, nrings;
> +               int nbuttons, nstrips, nrings, ngroups;
>
>                 nbuttons = libinput_device_tablet_pad_get_num_buttons(dev);
>                 nstrips = libinput_device_tablet_pad_get_num_strips(dev);
>                 nrings = libinput_device_tablet_pad_get_num_rings(dev);
> +               ngroups = libinput_device_tablet_pad_get_num_mode_groups(dev);
>
> -               printf(" buttons:%d strips:%d rings:%d",
> +               printf(" buttons:%d strips:%d rings:%d mode groups:%d",
>                        nbuttons,
>                        nstrips,
> -                      nrings);
> +                      nrings,
> +                      ngroups);
>         }
>
>         printf("\n");
> @@ -604,14 +609,25 @@ static void
>  print_tablet_pad_button_event(struct libinput_event *ev)
>  {
>         struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
> +       struct libinput_tablet_pad_mode_group *group;
>         enum libinput_button_state state;
> +       unsigned int button, mode;
>
>         print_event_time(libinput_event_tablet_pad_get_time(p));
>
> +       button = libinput_event_tablet_pad_get_button_number(p),
>         state = libinput_event_tablet_pad_get_button_state(p);
> -       printf("%3d %s\n",
> -              libinput_event_tablet_pad_get_button_number(p),
> -              state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released");
> +       mode = libinput_event_tablet_pad_get_mode(p);
> +       printf("%3d %s (mode %d)",
> +              button,
> +              state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
> +              mode);
> +
> +       group = libinput_event_tablet_pad_get_mode_group(p);
> +       if (libinput_tablet_pad_mode_group_button_is_toggle(group, button))
> +               printf(" <mode toggle>");
> +
> +       printf("\n");
>  }
>
>  static void
> @@ -619,6 +635,7 @@ print_tablet_pad_ring_event(struct libinput_event *ev)
>  {
>         struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
>         const char *source = "<invalid>";
> +       unsigned int mode;
>
>         print_event_time(libinput_event_tablet_pad_get_time(p));
>
> @@ -631,10 +648,12 @@ print_tablet_pad_ring_event(struct libinput_event *ev)
>                 break;
>         }
>
> -       printf("ring %d position %.2f (source %s)\n",
> +       mode = libinput_event_tablet_pad_get_mode(p);
> +       printf("ring %d position %.2f (source %s) (mode %d)\n",
>                libinput_event_tablet_pad_get_ring_number(p),
>                libinput_event_tablet_pad_get_ring_position(p),
> -              source);
> +              source,
> +              mode);
>  }
>
>  static void
> @@ -642,6 +661,7 @@ print_tablet_pad_strip_event(struct libinput_event *ev)
>  {
>         struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
>         const char *source = "<invalid>";
> +       unsigned int mode;
>
>         print_event_time(libinput_event_tablet_pad_get_time(p));
>
> @@ -654,10 +674,28 @@ print_tablet_pad_strip_event(struct libinput_event *ev)
>                 break;
>         }
>
> -       printf("strip %d position %.2f (source %s)\n",
> +       mode = libinput_event_tablet_pad_get_mode(p);
> +       printf("strip %d position %.2f (source %s) (mode %d)\n",
>                libinput_event_tablet_pad_get_strip_number(p),
>                libinput_event_tablet_pad_get_strip_position(p),
> -              source);
> +              source,
> +              mode);
> +}
> +
> +static void
> +print_tablet_pad_mode_event(struct libinput_event *ev)
> +{
> +       struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
> +       struct libinput_tablet_pad_mode_group *group;
> +       unsigned int mode;
> +
> +       print_event_time(libinput_event_tablet_pad_get_time(p));
> +
> +       group = libinput_event_tablet_pad_get_mode_group(p);
> +       mode = libinput_event_tablet_pad_get_mode(p);
> +       printf("group %d mode %d\n",
> +              libinput_tablet_pad_mode_group_get_index(group),
> +              mode);
>  }
>
>  static int
> @@ -748,6 +786,9 @@ handle_and_print_events(struct libinput *li)
>                 case LIBINPUT_EVENT_TABLET_PAD_STRIP:
>                         print_tablet_pad_strip_event(ev);
>                         break;
> +               case LIBINPUT_EVENT_TABLET_PAD_MODE:
> +                       print_tablet_pad_mode_event(ev);
> +                       break;
>                 }
>
>                 libinput_event_destroy(ev);
> diff --git a/tools/event-gui.c b/tools/event-gui.c
> index 605f00a..5eeea1e 100644
> --- a/tools/event-gui.c
> +++ b/tools/event-gui.c
> @@ -843,6 +843,7 @@ handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data)
>                 case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
>                 case LIBINPUT_EVENT_TABLET_PAD_RING:
>                 case LIBINPUT_EVENT_TABLET_PAD_STRIP:
> +               case LIBINPUT_EVENT_TABLET_PAD_MODE:
>                         break;
>                 }
>
> --
> 2.7.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list