[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