fallback: make the paired keyboard list a struct list
authorPeter Hutterer <peter.hutterer@who-t.net>
Mon, 28 May 2018 01:27:06 +0000 (11:27 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Tue, 29 May 2018 23:42:06 +0000 (09:42 +1000)
This removes the artificial 3 keyboard limit. If you have more internal
keyboards than that, something is wrong in your setup but that shouldn't stop
us from working. Or more specificially: this can happen easily when running
tests so let's not fail the test suite because we created a few hundred
keyboards.

We'll still throw out a log message though.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
src/evdev-fallback.c
src/evdev-fallback.h

index fa01faa..acc5d38 100644 (file)
@@ -660,7 +660,7 @@ fallback_lid_toggle_keyboard_listeners(struct fallback_dispatch *dispatch,
 {
        struct paired_keyboard *kbd;
 
-       ARRAY_FOR_EACH(dispatch->lid.paired_keyboard, kbd) {
+       list_for_each(kbd, &dispatch->lid.paired_keyboard_list, link) {
                if (!kbd->device)
                        continue;
 
@@ -1007,18 +1007,27 @@ fallback_interface_suspend(struct evdev_dispatch *evdev_dispatch,
 }
 
 static void
+fallback_paired_keyboard_destroy(struct paired_keyboard *kbd)
+{
+       kbd->device = NULL;
+       libinput_device_remove_event_listener(&kbd->listener);
+       list_remove(&kbd->link);
+       free(kbd);
+}
+
+static void
 fallback_interface_remove(struct evdev_dispatch *evdev_dispatch)
 {
        struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch);
-       struct paired_keyboard *kbd;
+       struct paired_keyboard *kbd, *tmp;
 
        libinput_device_remove_event_listener(&dispatch->tablet_mode.other.listener);
 
-       ARRAY_FOR_EACH(dispatch->lid.paired_keyboard, kbd) {
-               if (!kbd->device)
-                       continue;
-
-               libinput_device_remove_event_listener(&kbd->listener);
+       list_for_each_safe(kbd,
+                          tmp,
+                          &dispatch->lid.paired_keyboard_list,
+                          link) {
+               fallback_paired_keyboard_destroy(kbd);
        }
 }
 
@@ -1096,7 +1105,7 @@ fallback_lid_pair_keyboard(struct evdev_device *lid_switch,
        struct fallback_dispatch *dispatch =
                fallback_dispatch(lid_switch->dispatch);
        struct paired_keyboard *kbd;
-       bool paired = false;
+       size_t count = 0;
 
        if ((keyboard->tags & EVDEV_TAG_KEYBOARD) == 0 ||
            (lid_switch->tags & EVDEV_TAG_LID_SWITCH) == 0)
@@ -1105,30 +1114,30 @@ fallback_lid_pair_keyboard(struct evdev_device *lid_switch,
        if ((keyboard->tags & EVDEV_TAG_INTERNAL_KEYBOARD) == 0)
                return;
 
-       ARRAY_FOR_EACH(dispatch->lid.paired_keyboard, kbd) {
-               if (kbd->device)
-                       continue;
-
-               kbd->device = keyboard;
-               evdev_log_debug(lid_switch,
-                               "lid: keyboard paired with %s<->%s\n",
-                               lid_switch->devname,
-                               keyboard->devname);
-
-               /* We need to init the event listener now only if the
-                * reported state is closed. */
-               if (dispatch->lid.is_closed)
-                       fallback_lid_toggle_keyboard_listener(
-                                             dispatch,
-                                             kbd,
-                                             dispatch->lid.is_closed);
-               paired = true;
-               break;
+       list_for_each(kbd, &dispatch->lid.paired_keyboard_list, link) {
+               count++;
+               if (count > 3) {
+                       evdev_log_info(lid_switch,
+                                      "lid: too many internal keyboards\n");
+                       break;
+               }
        }
 
-       if (!paired)
-               evdev_log_bug_libinput(lid_switch,
-                                      "lid: too many internal keyboards\n");
+       kbd = zalloc(sizeof(*kbd));
+       kbd->device = keyboard;
+       libinput_device_init_event_listener(&kbd->listener);
+       list_insert(&dispatch->lid.paired_keyboard_list, &kbd->link);
+       evdev_log_debug(lid_switch,
+                       "lid: keyboard paired with %s<->%s\n",
+                       lid_switch->devname,
+                       keyboard->devname);
+
+       /* We need to init the event listener now only if the
+        * reported state is closed. */
+       if (dispatch->lid.is_closed)
+               fallback_lid_toggle_keyboard_listener(dispatch,
+                                                     kbd,
+                                                     dispatch->lid.is_closed);
 }
 
 static void
@@ -1229,18 +1238,19 @@ fallback_interface_device_removed(struct evdev_device *device,
 {
        struct fallback_dispatch *dispatch =
                        fallback_dispatch(device->dispatch);
-       struct paired_keyboard *kbd;
+       struct paired_keyboard *kbd, *tmp;
 
-       ARRAY_FOR_EACH(dispatch->lid.paired_keyboard, kbd) {
+       list_for_each_safe(kbd,
+                          tmp,
+                          &dispatch->lid.paired_keyboard_list,
+                          link) {
                if (!kbd->device)
                        continue;
 
                if (kbd->device != removed_device)
                        continue;
 
-               libinput_device_remove_event_listener(&kbd->listener);
-               libinput_device_init_event_listener(&kbd->listener);
-               kbd->device = NULL;
+               fallback_paired_keyboard_destroy(kbd);
        }
 
        if (removed_device == dispatch->tablet_mode.other.sw_device) {
@@ -1435,12 +1445,9 @@ fallback_dispatch_init_switch(struct fallback_dispatch *dispatch,
 {
        int val;
 
-       if (device->tags & EVDEV_TAG_LID_SWITCH) {
-               struct paired_keyboard *kbd;
-
-               ARRAY_FOR_EACH(dispatch->lid.paired_keyboard, kbd)
-                       libinput_device_init_event_listener(&kbd->listener);
+       list_init(&dispatch->lid.paired_keyboard_list);
 
+       if (device->tags & EVDEV_TAG_LID_SWITCH) {
                dispatch->lid.reliability = evdev_read_switch_reliability_prop(device);
                dispatch->lid.is_closed = false;
        }
@@ -1466,6 +1473,7 @@ fallback_dispatch_create(struct libinput_device *libinput_device)
        dispatch->base.dispatch_type = DISPATCH_FALLBACK;
        dispatch->base.interface = &fallback_interface;
        dispatch->pending_event = EVDEV_NONE;
+       list_init(&dispatch->lid.paired_keyboard_list);
 
        fallback_dispatch_init_rel(dispatch, device);
        fallback_dispatch_init_abs(dispatch, device);
index d64d36d..ca48f13 100644 (file)
@@ -45,6 +45,12 @@ enum debounce_state {
        DEBOUNCE_STATE_DISABLED = 999,
 };
 
+struct paired_keyboard {
+       struct list link;
+       struct evdev_device *device;
+       struct libinput_event_listener listener;
+};
+
 struct fallback_dispatch {
        struct evdev_dispatch base;
        struct evdev_device *device;
@@ -117,17 +123,12 @@ struct fallback_dispatch {
                bool is_closed;
                bool is_closed_client_state;
 
-               /* We allow up to 3 paired keyboards for the lid switch
+               /* We allow multiple paired keyboards for the lid switch
                 * listener. Only one keyboard should exist, but that can
-                * have more than one event node.
-                *
-                * Note: this is a sparse list, any element may have a
-                * non-NULL device.
+                * have more than one event node. And it's a list because
+                * otherwise the test suite run fails too often.
                 */
-               struct paired_keyboard {
-                       struct evdev_device *device;
-                       struct libinput_event_listener listener;
-               } paired_keyboard[3];
+               struct list paired_keyboard_list;
        } lid;
 };