[PATCH libinput v2 2/5] Add a "switch" interface for parts of the SW_* range
James Ye
jye836 at gmail.com
Tue Jan 10 01:24:22 UTC 2017
This will allow switch devices known to libinput to be exposed. Currently,
these are SW_LID and SW_TABLET_MODE.
libinput also handles switch events internally, e.g. a laptop touchpad will
be disabled autmoatically when the lid is closed. This is transparent to
the caller, although the caller will also receive the event. See
https://bugs.freedesktop.org/show_bug.cgi?id=86223
This features is intended to be the main driver for the interface.
Co-Authored-By: Peter Hutterer <peter.hutterer at who-t.net>
Signed-off-by: James Ye <jye836 at gmail.com>
---
Changes since v1:
- minor doxygen fixes
- missing @defgroup event_switch
- missing @ingroup event
doc/Makefile.am | 1 +
doc/switches.dox | 16 +++++++
src/libinput-private.h | 5 ++
src/libinput.c | 103 +++++++++++++++++++++++++++++++++++++++++
src/libinput.h | 121 +++++++++++++++++++++++++++++++++++++++++++++++++
src/libinput.sym | 9 ++++
test/litest.c | 3 ++
tools/event-debug.c | 34 ++++++++++++++
8 files changed, 292 insertions(+)
create mode 100644 doc/switches.dox
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 698a316..a92d791 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)/tablet-support.dox \
$(srcdir)/tapping.dox \
diff --git a/doc/switches.dox b/doc/switches.dox
new file mode 100644
index 0000000..4bb2675
--- /dev/null
+++ b/doc/switches.dox
@@ -0,0 +1,16 @@
+/**
+ 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.
+
+The order of switch events is guaranteed to be correct, i.e., a switch will
+never send consecutive switch on, or switch off, events.
+
+*/
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 0c75b3a..7ad02ef 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -618,6 +618,11 @@ tablet_pad_notify_strip(struct libinput_device *device,
double value,
enum libinput_tablet_pad_strip_axis_source source,
struct libinput_tablet_pad_mode_group *group);
+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 1e97ad1..98bbec7 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -159,6 +159,13 @@ struct libinput_event_tablet_pad {
} strip;
};
+struct libinput_event_switch {
+ struct libinput_event base;
+ uint64_t time;
+ enum libinput_switch sw;
+ enum libinput_switch_state state;
+};
+
LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
static void
libinput_default_log_func(struct libinput *libinput,
@@ -365,6 +372,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)
{
@@ -1508,6 +1526,61 @@ libinput_tablet_tool_unref(struct libinput_tablet_tool *tool)
return NULL;
}
+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 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;
+}
+
+LIBINPUT_EXPORT uint32_t
+libinput_event_switch_get_time(struct libinput_event_switch *event)
+{
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ 0,
+ LIBINPUT_EVENT_SWITCH_TOGGLE);
+
+ return us2ms(event->time);
+}
+
+LIBINPUT_EXPORT uint64_t
+libinput_event_switch_get_time_usec(struct libinput_event_switch *event)
+{
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ 0,
+ LIBINPUT_EVENT_SWITCH_TOGGLE);
+
+ return event->time;
+}
+
struct libinput_source *
libinput_add_fd(struct libinput *libinput,
int fd,
@@ -2024,6 +2097,9 @@ device_has_cap(struct libinput_device *device,
case LIBINPUT_DEVICE_CAP_TABLET_PAD:
capability = "CAP_TABLET_PAD";
break;
+ case LIBINPUT_DEVICE_CAP_SWITCH:
+ capability = "CAP_SWITCH";
+ break;
}
log_bug_libinput(device->seat->libinput,
@@ -2619,6 +2695,7 @@ event_type_to_str(enum libinput_event_type type)
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_BEGIN);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_UPDATE);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_END);
+ CASE_RETURN_STRING(LIBINPUT_EVENT_SWITCH_TOGGLE);
case LIBINPUT_EVENT_NONE:
abort();
}
@@ -2626,6 +2703,32 @@ event_type_to_str(enum libinput_event_type type)
return NULL;
}
+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)
diff --git a/src/libinput.h b/src/libinput.h
index 18a96bd..77cb056 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -187,6 +187,7 @@ enum libinput_device_capability {
LIBINPUT_DEVICE_CAP_TABLET_TOOL = 3,
LIBINPUT_DEVICE_CAP_TABLET_PAD = 4,
LIBINPUT_DEVICE_CAP_GESTURE = 5,
+ LIBINPUT_DEVICE_CAP_SWITCH = 6,
};
/**
@@ -592,6 +593,47 @@ libinput_tablet_pad_mode_group_get_user_data(
struct libinput_tablet_pad_mode_group *group);
/**
+ * @ingroup device
+ *
+ * The state of a switch.
+ */
+enum libinput_switch_state {
+ LIBINPUT_SWITCH_STATE_OFF = 0,
+ LIBINPUT_SWITCH_STATE_ON = 1,
+};
+
+/**
+ * @ingroup device
+ *
+ * The type of a switch.
+ */
+enum libinput_switch {
+ /**
+ * The laptop lid was closed when the switch state is @ref
+ * LIBINPUT_SWITCH_STATE_ON, or was opened when it is @ref
+ * LIBINPUT_SWITCH_STATE_OFF.
+ */
+ 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.
+ * Tablet mode is on when the switch state is @ref
+ * LIBINPUT_SWITCH_STATE_ON, or off when it is @ref
+ * LIBINPUT_SWITCH_STATE_OFF.
+ */
+ LIBINPUT_SWITCH_TABLET_MODE = 2,
+};
+
+/**
+ * @ingroup event_switch
+ * @struct libinput_event_switch
+ *
+ * A switch event representing a changed state in a switch.
+ */
+struct libinput_event_switch;
+
+/**
* @ingroup base
*
* Event type for events returned by libinput_get_event().
@@ -746,6 +788,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,
};
/**
@@ -885,6 +929,19 @@ libinput_event_get_tablet_pad_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.
*
@@ -2684,6 +2741,70 @@ uint64_t
libinput_event_tablet_pad_get_time_usec(struct libinput_event_tablet_pad *event);
/**
+ * @defgroup event_switch Switch events
+ *
+ * Events that come from switch devices.
+ */
+
+/**
+ * @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.
+ *
+ * @param event The libinput switch event
+ * @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.
+ *
+ * @param event The libinput switch event
+ * @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);
+
+/**
+ * @ingroup event_switch
+ *
+ * @param event The libinput switch event
+ * @return The event time for this event
+ */
+uint32_t
+libinput_event_switch_get_time(struct libinput_event_switch *event);
+
+/**
+ * @ingroup event_switch
+ *
+ * @param event The libinput switch event
+ * @return The event time for this event in microseconds
+ */
+uint64_t
+libinput_event_switch_get_time_usec(struct libinput_event_switch *event);
+
+/**
* @defgroup base Initialization and manipulation of libinput contexts
*/
diff --git a/src/libinput.sym b/src/libinput.sym
index 97bb57f..f440521 100644
--- a/src/libinput.sym
+++ b/src/libinput.sym
@@ -280,3 +280,12 @@ LIBINPUT_1.5 {
libinput_device_config_tap_get_default_button_map;
libinput_device_config_tap_set_button_map;
} LIBINPUT_1.4;
+
+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_event_switch_get_time;
+ libinput_event_switch_get_time_usec;
+} LIBINPUT_1.5;
diff --git a/test/litest.c b/test/litest.c
index 0574c0a..98ea0ec 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -2179,6 +2179,9 @@ litest_event_type_str(enum libinput_event_type type)
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
str = "TABLET PAD STRIP";
break;
+ case LIBINPUT_EVENT_SWITCH_TOGGLE:
+ str = "SWITCH TOGGLE";
+ break;
}
return str;
}
diff --git a/tools/event-debug.c b/tools/event-debug.c
index d7d2018..179dc12 100644
--- a/tools/event-debug.c
+++ b/tools/event-debug.c
@@ -133,6 +133,9 @@ print_event_header(struct libinput_event *ev)
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
type = "TABLET_PAD_STRIP";
break;
+ case LIBINPUT_EVENT_SWITCH_TOGGLE:
+ type = "SWITCH_TOGGLE";
+ break;
}
prefix = (last_device != dev) ? '-' : ' ';
@@ -194,6 +197,9 @@ print_device_notify(struct libinput_event *ev)
if (libinput_device_has_capability(dev,
LIBINPUT_DEVICE_CAP_TABLET_PAD))
printf("P");
+ if (libinput_device_has_capability(dev,
+ LIBINPUT_DEVICE_CAP_SWITCH))
+ printf("S");
if (libinput_device_get_size(dev, &w, &h) == 0)
printf(" size %.0fx%.0fmm", w, h);
@@ -703,6 +709,31 @@ print_tablet_pad_strip_event(struct libinput_event *ev)
mode);
}
+static void
+print_switch_event(struct libinput_event *ev)
+{
+ struct libinput_event_switch *sw = libinput_event_get_switch_event(ev);
+ enum libinput_switch_state state;
+ const char *which;
+
+ print_event_time(libinput_event_switch_get_time(sw));
+
+ switch (libinput_event_switch_get_switch(sw)) {
+ case LIBINPUT_SWITCH_LID:
+ which = "lid";
+ break;
+ case LIBINPUT_SWITCH_TABLET_MODE:
+ which = "tablet-mode";
+ break;
+ default:
+ abort();
+ }
+
+ state = libinput_event_switch_get_switch_state(sw);
+
+ printf("switch %s state %d\n", which, state);
+}
+
static int
handle_and_print_events(struct libinput *li)
{
@@ -791,6 +822,9 @@ handle_and_print_events(struct libinput *li)
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
print_tablet_pad_strip_event(ev);
break;
+ case LIBINPUT_EVENT_SWITCH_TOGGLE:
+ print_switch_event(ev);
+ break;
}
libinput_event_destroy(ev);
--
2.9.3
More information about the wayland-devel
mailing list