summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2015-08-07 15:19:12 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2015-08-13 07:52:48 +1000
commite3a888c3ab0f4cc42943b0216852cba110c3dad2 (patch)
tree3520f1fcd689c610d8b356b10f7e2dadaf596962 /test
parentcd61ddb040af288cf0e5a3fcccab3d390e3f1cab (diff)
Add drag lock support
First, why is this here and not in libinput: drag lock should be implemented in the compositor (not in libinput) so it can provide feedback when it activates and grouped in with other accessibility features. That will work for Wayland but in X the compositor cannot filter button events - only the server and the drivers can. This patch adds mostly the same functionality that evdev provides with two options on how it works: * a single button number configures the given button to lock the next button pressed in a logically down state until a press+ release of that same button again * a set of button number pairs configures each button with the to-be-locked logical button, i.e. a pair of "1 3" will hold 3 logically down after a button 1 press The property and the xorg.conf options take the same configuration as the evdev driver (though the property has a different prefix, libinput instead of Evdev). The behavior difference to evdev is in how releases are handled, evdev sends the release on the second button press event, this implementation sends the release on the second release event. https://bugs.freedesktop.org/show_bug.cgi?id=85577 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'test')
-rw-r--r--test/.gitignore1
-rw-r--r--test/Makefile.am13
-rw-r--r--test/test-draglock.c540
3 files changed, 554 insertions, 0 deletions
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644
index 0000000..48a46e3
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1 @@
+test-draglock
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..6f94abe
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,13 @@
+AM_CPPFLAGS = $(XORG_CFLAGS) \
+ $(CWARNFLAGS) \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src
+
+tests = test-draglock
+
+noinst_PROGRAMS = $(tests)
+
+test_draglock_SOURCES = test-draglock.c
+test_draglock_LDADD = ../src/libdraglock.la
+
+TESTS = $(tests)
diff --git a/test/test-draglock.c b/test/test-draglock.c
new file mode 100644
index 0000000..96ef5bb
--- /dev/null
+++ b/test/test-draglock.c
@@ -0,0 +1,540 @@
+/*
+ * Copyright © 2013-2015 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission. Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "draglock.h"
+
+#include <assert.h>
+#include <string.h>
+
+static void
+test_config_empty(void)
+{
+ struct draglock dl;
+ int rc;
+
+ rc = draglock_init_from_string(&dl, NULL);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+ assert(rc == 0);
+}
+
+static void
+test_config_invalid(void)
+{
+ struct draglock dl;
+ int rc;
+
+ /* no trailing space */
+ rc = draglock_init_from_string(&dl, "1 ");
+ assert(rc != 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+
+ rc = draglock_init_from_string(&dl, "256");
+ assert(rc != 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+
+ rc = draglock_init_from_string(&dl, "-1");
+ assert(rc != 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+
+ rc = draglock_init_from_string(&dl, "1 2 3");
+ assert(rc != 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+
+ rc = draglock_init_from_string(&dl, "0 2");
+ assert(rc != 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+
+ rc = draglock_init_from_string(&dl, "0 0");
+ assert(rc != 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+}
+
+static void
+test_config_disable(void)
+{
+ struct draglock dl;
+ int rc;
+
+ rc = draglock_init_from_string(&dl, "");
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+
+ rc = draglock_init_from_string(&dl, "0");
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+}
+
+static void
+test_config_meta_button(void)
+{
+ struct draglock dl;
+ int rc;
+
+ rc = draglock_init_from_string(&dl, "1");
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_META);
+ assert(dl.meta_button == 1);
+
+ rc = draglock_init_from_string(&dl, "2");
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_META);
+ assert(dl.meta_button == 2);
+
+ rc = draglock_init_from_string(&dl, "10");
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_META);
+ assert(dl.meta_button == 10);
+}
+
+static void
+test_config_button_pairs(void)
+{
+ struct draglock dl;
+ int rc;
+
+ rc = draglock_init_from_string(&dl, "1 1");
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_PAIRS);
+
+ rc = draglock_init_from_string(&dl, "1 2 3 4 5 6 7 8");
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_PAIRS);
+
+ rc = draglock_init_from_string(&dl, "1 2 3 4 5 0 7 8");
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_PAIRS);
+
+ /* all disabled */
+ rc = draglock_init_from_string(&dl, "1 0 3 0 5 0 7 0");
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+}
+
+static void
+test_config_get(void)
+{
+ struct draglock dl;
+ int rc;
+ const int sz = 32;
+ int map[sz];
+
+ draglock_init_from_string(&dl, "");
+ rc = draglock_get_meta(&dl);
+ assert(rc == 0);
+ rc = draglock_get_pairs(&dl, map, sz);
+ assert(rc == 0);
+
+ draglock_init_from_string(&dl, "8");
+ rc = draglock_get_meta(&dl);
+ assert(rc == 8);
+ rc = draglock_get_pairs(&dl, map, sz);
+ assert(rc == 0);
+
+ draglock_init_from_string(&dl, "1 2 3 4 5 6");
+ rc = draglock_get_meta(&dl);
+ assert(rc == 0);
+ rc = draglock_get_pairs(&dl, map, sz);
+ assert(rc == 5);
+ assert(map[0] == 0);
+ assert(map[1] == 2);
+ assert(map[2] == 0);
+ assert(map[3] == 4);
+ assert(map[4] == 0);
+ assert(map[5] == 6);
+}
+
+static void
+test_set_meta(void)
+{
+ struct draglock dl;
+ int rc;
+
+ draglock_init_from_string(&dl, "");
+
+ rc = draglock_set_meta(&dl, 0);
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+
+ rc = draglock_set_meta(&dl, 1);
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_META);
+
+ rc = draglock_set_meta(&dl, -1);
+ assert(rc == 1);
+ rc = draglock_set_meta(&dl, 32);
+ assert(rc == 1);
+}
+
+static void
+test_set_pairs(void)
+{
+ struct draglock dl;
+ int rc;
+ const int sz = 32;
+ int map[sz];
+
+ draglock_init_from_string(&dl, "");
+ memset(map, 0, sizeof(map));
+
+ rc = draglock_set_pairs(&dl, map, sz);
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+
+ rc = draglock_set_pairs(&dl, map, 1);
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_DISABLED);
+
+ map[0] = 1;
+ rc = draglock_set_pairs(&dl, map, 1);
+ assert(rc == 1);
+
+ map[0] = 0;
+ map[1] = 2;
+ rc = draglock_set_pairs(&dl, map, sz);
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_PAIRS);
+
+ map[0] = 0;
+ map[1] = 0;
+ map[10] = 8;
+ rc = draglock_set_pairs(&dl, map, sz);
+ assert(rc == 0);
+ assert(dl.mode == DRAGLOCK_PAIRS);
+}
+
+static void
+test_filter_meta_passthrough(void)
+{
+ struct draglock dl;
+ int rc;
+ int button, press;
+ int i;
+
+ rc = draglock_init_from_string(&dl, "10");
+
+ for (i = 0; i < 10; i++) {
+ button = i;
+ press = 1;
+
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == i);
+ assert(press == 1);
+
+ press = 1;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == i);
+ assert(press == 1);
+ }
+}
+
+static void
+test_filter_meta_click_meta_only(void)
+{
+ struct draglock dl;
+ int rc;
+ int button, press;
+
+ rc = draglock_init_from_string(&dl, "10");
+
+ button = 10;
+ press = 1;
+
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ button = 10;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+}
+
+static void
+test_filter_meta(void)
+{
+ struct draglock dl;
+ int rc;
+ int button, press;
+ int i;
+
+ rc = draglock_init_from_string(&dl, "10");
+
+ for (i = 1; i < 10; i++) {
+ /* meta down */
+ button = 10;
+ press = 1;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* meta up */
+ button = 10;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* button down -> passthrough */
+ button = i;
+ press = 1;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == i);
+
+ /* button up -> eaten */
+ button = i;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* button down -> eaten */
+ button = i;
+ press = 1;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* button up -> passthrough */
+ button = i;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == i);
+ assert(press == 0);
+ }
+}
+
+static void
+test_filter_meta_extra_click(void)
+{
+ struct draglock dl;
+ int rc;
+ int button, press;
+ int i;
+
+ rc = draglock_init_from_string(&dl, "10");
+
+ for (i = 1; i < 10; i++) {
+ /* meta down */
+ button = 10;
+ press = 1;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* meta up */
+ button = 10;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* button down -> passthrough */
+ button = i;
+ press = 1;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == i);
+
+ /* button up -> eaten */
+ button = i;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* meta down */
+ button = 10;
+ press = 1;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* meta up */
+ button = 10;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* button down -> eaten */
+ button = i;
+ press = 1;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* button up -> passthrough */
+ button = i;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == i);
+ assert(press == 0);
+ }
+}
+
+static void
+test_filter_meta_interleaved(void)
+{
+ struct draglock dl;
+ int rc;
+ int button, press;
+ int i;
+
+ rc = draglock_init_from_string(&dl, "10");
+
+ for (i = 1; i < 10; i++) {
+ /* meta down */
+ button = 10;
+ press = 1;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* meta up */
+ button = 10;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* button down -> passthrough */
+ button = i;
+ press = 1;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == i);
+
+ /* button up -> eaten */
+ button = i;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+ }
+
+ for (i = 0; i < 10; i++) {
+ /* button down -> eaten */
+ button = i;
+ press = 1;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == 0);
+
+ /* button up -> passthrough */
+ button = i;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ assert(button == i);
+ assert(press == 0);
+ }
+}
+
+static void
+test_filter_pairs(void)
+{
+ struct draglock dl;
+ int rc;
+ int button, press;
+ int i;
+
+ rc = draglock_init_from_string(&dl, "1 11 2 0 3 13 4 0 5 15 6 0 7 17 8 0 9 19");
+
+ for (i = 1; i < 10; i++) {
+ button = i;
+ press = 1;
+
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ if (i % 2)
+ assert(button == i + 10);
+ else
+ assert(button == i);
+ assert(press == 1);
+
+ button = i;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ if (i % 2) {
+ assert(button == 0);
+ } else {
+ assert(button == i);
+ assert(press == 0);
+ }
+ }
+
+ for (i = 1; i < 10; i++) {
+ button = i;
+ press = 1;
+
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ if (i % 2) {
+ assert(button == 0);
+ } else {
+ assert(button == i);
+ assert(press == 1);
+ }
+
+ button = i;
+ press = 0;
+ rc = draglock_filter_button(&dl, &button, &press);
+ assert(rc == 0);
+ if (i % 2)
+ assert(button == i + 10);
+ else
+ assert(button == i);
+ assert(press == 0);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ test_config_empty();
+ test_config_invalid();
+ test_config_disable();
+ test_config_meta_button();
+ test_config_button_pairs();
+
+ test_config_get();
+ test_set_meta();
+ test_set_pairs();
+
+ test_filter_meta_passthrough();
+ test_filter_meta_click_meta_only();
+ test_filter_meta();
+ test_filter_meta_extra_click();
+ test_filter_meta_interleaved();
+
+ test_filter_pairs();
+
+ return 0;
+}