[RFC libinput] Add a "switch" interface for parts of the SW_* range
Hans de Goede
hdegoede at redhat.com
Wed Jan 6 01:51:09 PST 2016
Hi,
On 04-01-16 02:20, Peter Hutterer wrote:
> This is a first draft to gather some comments, it's not hooked up to
> anything yet and really just to get the main intention across.
>
> Things up for comments and discussion:
> Unlike buttons, we only expose switches we understand, hence enum
> libinput_switch rather than just forwarding uint32_t
> devices. This enables us to be selective on which devices should be handled
> by libinput, e.g. libinput doesn't need to handle devices that expose
> SW_JACK_PHYSICAL_INSERT. The ones that matter because they are input
> device-related are SW_LID, SW_TABLET_MODE, SW_DOCK, and SW_MUTE_DEVICE and
> SW_KEYPAD_SLIDE.
>
> libinput will also handle switch events internally, e.g. disable the
> touchpad automatically when the lid is closed. this will be transparent to
> the caller, though they will receive the event too. See
> https://bugs.freedesktop.org/show_bug.cgi?id=86223
> This feature is the main driver for the interface, the alternative would be
> to handle the device completely internally and let the caller open a
> separate fd for the any switch device. That makes some sense for the "Led
> Switch" device, not so much for the Wacom tablets that have SW_MUTE_DEVICE
> on the device itself.
>
> Should we have a separate event type for the current state of the switch
> when the device is added? I think sending a EVENT_SWITCH_TOGGLE burst on
> DEVICE_ADDED is sufficient. There will also be a
> libinput_device_switch_has_switch() and
> libinput_device_switch_get_switch_state() that do the obvious thing.
>
> comments, etc. welcome. Any typos you can safely ignore for now, this is
> just a first draft :)
>
> Cheers,
> Peter
> ---
> doc/Makefile.am | 1 +
> doc/switches.dox | 14 ++++++++
> src/libinput-private.h | 6 ++++
> src/libinput.c | 80 ++++++++++++++++++++++++++++++++++++++++++++
> src/libinput.h | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++
> src/libinput.sym | 7 ++++
> 6 files changed, 198 insertions(+)
> create mode 100644 doc/switches.dox
>
> diff --git a/doc/Makefile.am b/doc/Makefile.am
> index fe70f6a..84eb033 100644
> --- a/doc/Makefile.am
> +++ b/doc/Makefile.am
> @@ -22,6 +22,7 @@ header_files = \
> $(srcdir)/reporting-bugs.dox \
> $(srcdir)/scrolling.dox \
> $(srcdir)/seats.dox \
> + $(srcdir)/switches.dox \
> $(srcdir)/t440-support.dox \
> $(srcdir)/tapping.dox \
> $(srcdir)/test-suite.dox \
> diff --git a/doc/switches.dox b/doc/switches.dox
> new file mode 100644
> index 0000000..ae070560
> --- /dev/null
> +++ b/doc/switches.dox
> @@ -0,0 +1,14 @@
> +/**
> + at page switches Switches
> +
> +libinput supports a couple of switches. Unlike button events that come in
> +press and release pairs, switches are usually toggled once and left at the
> +setting for an extended period of time.
> +
> +Only some switches are handled by libinput, see @ref libinput_switch for a
> +list of supported switches. Switch events are exposed to the caller, but
> +libinput may handle some switch events internally and enable or disable
> +specific features based on a switch state.
> +
> +*/
> +
> diff --git a/src/libinput-private.h b/src/libinput-private.h
> index 51ac35e..91c843b 100644
> --- a/src/libinput-private.h
> +++ b/src/libinput-private.h
> @@ -444,6 +444,12 @@ gesture_notify_pinch_end(struct libinput_device *device,
> double scale,
> int cancelled);
>
> +void
> +switch_notify_toggle(struct libinput_device *device,
> + uint64_t time,
> + enum libinput_switch sw,
> + enum libinput_switch_state state);
> +
> static inline uint64_t
> libinput_now(struct libinput *libinput)
> {
> diff --git a/src/libinput.c b/src/libinput.c
> index dd16ab7..120552b 100644
> --- a/src/libinput.c
> +++ b/src/libinput.c
> @@ -125,6 +125,13 @@ struct libinput_event_gesture {
> double angle;
> };
>
> +struct libinput_event_switch {
> + struct libinput_event base;
> + uint64_t time;
> + enum libinput_switch sw;
> + enum libinput_switch_state state;
> +};
> +
> static void
> libinput_default_log_func(struct libinput *libinput,
> enum libinput_log_priority priority,
> @@ -304,6 +311,17 @@ libinput_event_get_device_notify_event(struct libinput_event *event)
> return (struct libinput_event_device_notify *) event;
> }
>
> +LIBINPUT_EXPORT struct libinput_event_switch *
> +libinput_event_get_switch_event(struct libinput_event *event)
> +{
> + require_event_type(libinput_event_get_context(event),
> + event->type,
> + NULL,
> + LIBINPUT_EVENT_SWITCH_TOGGLE);
> +
> + return (struct libinput_event_switch *) event;
> +}
> +
> LIBINPUT_EXPORT uint32_t
> libinput_event_keyboard_get_time(struct libinput_event_keyboard *event)
> {
> @@ -884,6 +902,28 @@ libinput_event_gesture_get_angle_delta(struct libinput_event_gesture *event)
> return event->angle;
> }
>
> +LIBINPUT_EXPORT enum libinput_switch
> +libinput_event_switch_get_switch(struct libinput_event_switch *event)
> +{
> + require_event_type(libinput_event_get_context(&event->base),
> + event->base.type,
> + 0,
> + LIBINPUT_EVENT_SWITCH_TOGGLE);
> +
> + return event->sw;
> +}
> +
> +LIBINPUT_EXPORT enum libinput_switch_state
> +libinput_event_switch_get_switch_state(struct libinput_event_switch *event)
> +{
> + require_event_type(libinput_event_get_context(&event->base),
> + event->base.type,
> + 0,
> + LIBINPUT_EVENT_SWITCH_TOGGLE);
> +
> + return event->state;
> +}
> +
> struct libinput_source *
> libinput_add_fd(struct libinput *libinput,
> int fd,
> @@ -1355,6 +1395,9 @@ device_has_cap(struct libinput_device *device,
> case LIBINPUT_DEVICE_CAP_GESTURE:
> capability = "CAP_GESTURE";
> break;
> + case LIBINPUT_DEVICE_CAP_SWITCH:
> + capability = "CAP_SWITCH";
> + break;
> }
>
> log_bug_libinput(device->seat->libinput,
> @@ -1694,6 +1737,32 @@ gesture_notify_pinch_end(struct libinput_device *device,
> 2, cancelled, &zero, &zero, scale, 0.0);
> }
>
> +void
> +switch_notify_toggle(struct libinput_device *device,
> + uint64_t time,
> + enum libinput_switch sw,
> + enum libinput_switch_state state)
> +{
> + struct libinput_event_switch *switch_event;
> +
> + if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_SWITCH))
> + return;
> +
> + switch_event = zalloc(sizeof *switch_event);
> + if (!switch_event)
> + return;
> +
> + *switch_event = (struct libinput_event_switch) {
> + .time = time,
> + .sw = sw,
> + .state = state,
> + };
> +
> + post_device_event(device, time,
> + LIBINPUT_EVENT_SWITCH_TOGGLE,
> + &switch_event->base);
> +}
> +
> static void
> libinput_post_event(struct libinput *libinput,
> struct libinput_event *event)
> @@ -1976,6 +2045,17 @@ libinput_event_gesture_get_base_event(struct libinput_event_gesture *event)
> return &event->base;
> }
>
> +LIBINPUT_EXPORT struct libinput_event *
> +libinput_event_switch_get_base_event(struct libinput_event_switch *event)
> +{
> + require_event_type(libinput_event_get_context(&event->base),
> + event->base.type,
> + NULL,
> + LIBINPUT_EVENT_SWITCH_TOGGLE);
> +
> + return &event->base;
> +}
> +
> LIBINPUT_EXPORT struct libinput_device_group *
> libinput_device_group_ref(struct libinput_device_group *group)
> {
> diff --git a/src/libinput.h b/src/libinput.h
> index 79d6e90..2c353ff 100644
> --- a/src/libinput.h
> +++ b/src/libinput.h
> @@ -59,6 +59,7 @@ enum libinput_device_capability {
> LIBINPUT_DEVICE_CAP_POINTER = 1,
> LIBINPUT_DEVICE_CAP_TOUCH = 2,
> LIBINPUT_DEVICE_CAP_GESTURE = 5,
> + LIBINPUT_DEVICE_CAP_SWITCH = 6,
> };
>
> /**
> @@ -134,6 +135,34 @@ enum libinput_pointer_axis_source {
> };
>
> /**
> + * @ingroup device
> + *
> + * The type of a switch.
> + */
> +enum libinput_switch {
> + /**
> + * The laptop lid was closed or opened.
It would be good to document how closed / open is mapped to STATE_OFF / STATE_ON.
> + */
> + LIBINPUT_SWITCH_LID = 1,
> + /**
> + * The device was switched to or from tablet mode, usually by
> + * rotating the screen and fixating it in place over the keyboard so
> + * that the device now looks like a tablet.
> + */
Liewise it would be good to document how tablet-mode vs laptop-mode is mapped to
STATE_OFF / STATE_ON.
Otherwise things look good to me.
> + LIBINPUT_SWITCH_TABLET_MODE = 2,
> +};
> +
> +/**
> + * @ingroup device
> + *
> + * The state of a switch.
> + */
> +enum libinput_switch_state {
> + LIBINPUT_SWITCH_STATE_OFF = 0,
> + LIBINPUT_SWITCH_STATE_ON = 1,
> +};
> +
> +/**
> * @ingroup base
> *
> * Event type for events returned by libinput_get_event().
> @@ -185,6 +214,8 @@ enum libinput_event_type {
> LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
> LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
> LIBINPUT_EVENT_GESTURE_PINCH_END,
> +
> + LIBINPUT_EVENT_SWITCH_TOGGLE = 900,
> };
>
> /**
> @@ -274,6 +305,14 @@ struct libinput_event_pointer;
> struct libinput_event_touch;
>
> /**
> + * @ingroup event_switch
> + * @struct libinput_event_switch
> + *
> + * A switch event representing a changed state in a switch.
> + */
> +struct libinput_event_switch;
> +
> +/**
> * @defgroup event Accessing and destruction of events
> */
>
> @@ -384,6 +423,19 @@ libinput_event_get_gesture_event(struct libinput_event *event);
> /**
> * @ingroup event
> *
> + * Return the switch event that is this input event. If the event type does
> + * not match the switch event types, this function returns NULL.
> + *
> + * The inverse of this function is libinput_event_switch_get_base_event().
> + *
> + * @return A switch event, or NULL for other events
> + */
> +struct libinput_event_switch *
> +libinput_event_get_switch_event(struct libinput_event *event);
> +
> +/**
> + * @ingroup event
> + *
> * Return the device event that is this input event. If the event type does
> * not match the device event types, this function returns NULL.
> *
> @@ -1170,6 +1222,44 @@ double
> libinput_event_gesture_get_angle_delta(struct libinput_event_gesture *event);
>
> /**
> + * @ingroup event_switch
> + *
> + * Return the switch that triggered this event.
> + * For pointer events that are not of type @ref
> + * LIBINPUT_EVENT_SWITCH_TOGGLE, this function returns 0.
> + *
> + * @note It is an application bug to call this function for events other than
> + * @ref LIBINPUT_EVENT_SWITCH_TOGGLE.
> + *
> + * @return The switch triggering this event
> + */
> +enum libinput_switch
> +libinput_event_switch_get_switch(struct libinput_event_switch *event);
> +
> +/**
> + * @ingroup event_switch
> + *
> + * Return the switch state that triggered this event.
> + * For switch events that are not of type @ref
> + * LIBINPUT_EVENT_SWITCH_TOGGLE, this function returns 0.
> + *
> + * @note It is an application bug to call this function for events other than
> + * @ref LIBINPUT_EVENT_SWITCH_TOGGLE.
> + *
> + * @return The switch state triggering this event
> + */
> +enum libinput_switch_state
> +libinput_event_switch_get_switch_state(struct libinput_event_switch *event);
> +
> +/**
> + * @ingroup event_switch
> + *
> + * @return The generic libinput_event of this event
> + */
> +struct libinput_event *
> +libinput_event_switch_get_base_event(struct libinput_event_switch *event);
> +
> +/**
> * @defgroup base Initialization and manipulation of libinput contexts
> */
>
> diff --git a/src/libinput.sym b/src/libinput.sym
> index 15203c8..5b1efee 100644
> --- a/src/libinput.sym
> +++ b/src/libinput.sym
> @@ -179,3 +179,10 @@ LIBINPUT_1.1 {
> libinput_device_config_accel_get_default_profile;
> libinput_device_config_accel_set_profile;
> } LIBINPUT_0.21.0;
> +
> +LIBINPUT_SWITCH {
> + libinput_event_get_switch_event;
> + libinput_event_switch_get_base_event;
> + libinput_event_switch_get_switch_state;
> + libinput_event_switch_get_switch;
> +} LIBINPUT_1.1;
>
More information about the wayland-devel
mailing list