This will allow switch devices known to libinput to be exposed. Currently,
this is SW_LID.

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.hutte...@who-t.net>
Signed-off-by: James Ye <jye...@gmail.com>
---
Changes since v2:
 - removed tablet mode enum

 doc/Makefile.am        |   1 +
 doc/switches.dox       |  16 +++++++
 src/libinput-private.h |   5 +++
 src/libinput.c         | 103 +++++++++++++++++++++++++++++++++++++++++++++
 src/libinput.h         | 112 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/libinput.sym       |   9 ++++
 test/litest.c          |   3 ++
 tools/event-debug.c    |  31 ++++++++++++++
 8 files changed, 280 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 @@
+/**
+@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 40cc926..18d82b6 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -623,6 +623,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 4daa11d..4997153 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 fdbba3c..f8b123a 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,
 };
 
 /**
@@ -598,6 +599,38 @@ 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,
+};
+
+/**
+ * @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().
@@ -752,6 +785,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,
 };
 
 /**
@@ -891,6 +926,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.
  *
@@ -2699,6 +2747,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 b3e7ba3..5b1e7b5 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -2203,6 +2203,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 a3e460a..779b54a 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);
@@ -706,6 +712,28 @@ 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;
+       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)
 {
@@ -794,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

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

Reply via email to