diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2015-08-07 15:19:12 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2015-08-13 07:52:48 +1000 |
commit | e3a888c3ab0f4cc42943b0216852cba110c3dad2 (patch) | |
tree | 3520f1fcd689c610d8b356b10f7e2dadaf596962 /test | |
parent | cd61ddb040af288cf0e5a3fcccab3d390e3f1cab (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/.gitignore | 1 | ||||
-rw-r--r-- | test/Makefile.am | 13 | ||||
-rw-r--r-- | test/test-draglock.c | 540 |
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; +} |