mirror of
https://github.com/X11Libre/xf86-input-libinput.git
synced 2026-03-24 09:34:04 +00:00
Compare commits
21 Commits
xf86-input
...
xf86-input
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f48b64c8cd | ||
|
|
b55239ef25 | ||
|
|
9563334dda | ||
|
|
353c52f2be | ||
|
|
f139f14249 | ||
|
|
e3a888c3ab | ||
|
|
cd61ddb040 | ||
|
|
a199880057 | ||
|
|
cc57eecd72 | ||
|
|
fe58cff48b | ||
|
|
4b2bed6912 | ||
|
|
223be9f62b | ||
|
|
d3ee745a24 | ||
|
|
b550b70a00 | ||
|
|
254b1f27a0 | ||
|
|
bfedf7dbac | ||
|
|
9c5cf97143 | ||
|
|
449b496a3a | ||
|
|
d4e0b5420f | ||
|
|
19c91044e4 | ||
|
|
3d6afca975 |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -76,3 +76,11 @@ core
|
||||
# Edit the following section as needed
|
||||
# For example, !report.pc overrides *.pc. See 'man gitignore'
|
||||
#
|
||||
*.log
|
||||
*.trs
|
||||
*.swp
|
||||
*.announce
|
||||
*.sig
|
||||
test-driver
|
||||
tags
|
||||
.vimdir
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = --with-sdkdir='$${includedir}/xorg'
|
||||
|
||||
SUBDIRS = src include man
|
||||
SUBDIRS = src include man test
|
||||
MAINTAINERCLEANFILES = ChangeLog INSTALL
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
# Initialize Autoconf
|
||||
AC_PREREQ([2.60])
|
||||
AC_INIT([xf86-input-libinput],
|
||||
[0.10.0],
|
||||
[0.14.0],
|
||||
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
|
||||
[xf86-input-libinput])
|
||||
AC_CONFIG_SRCDIR([Makefile.am])
|
||||
@@ -45,7 +45,7 @@ XORG_DEFAULT_OPTIONS
|
||||
|
||||
# Obtain compiler/linker options from server and required extensions
|
||||
PKG_CHECK_MODULES(XORG, [xorg-server >= 1.10] xproto [inputproto >= 2.2])
|
||||
PKG_CHECK_MODULES(LIBINPUT, [libinput >= 0.14.0])
|
||||
PKG_CHECK_MODULES(LIBINPUT, [libinput >= 0.21.0])
|
||||
|
||||
# Define a configure option for an alternate input module directory
|
||||
AC_ARG_WITH(xorg-module-dir,
|
||||
@@ -71,5 +71,6 @@ AC_CONFIG_FILES([Makefile
|
||||
include/Makefile
|
||||
src/Makefile
|
||||
man/Makefile
|
||||
test/Makefile
|
||||
xorg-libinput.pc])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -30,6 +30,12 @@
|
||||
/* Tapping default enabled/disabled: BOOL, 1 value, read-only */
|
||||
#define LIBINPUT_PROP_TAP_DEFAULT "libinput Tapping Enabled Default"
|
||||
|
||||
/* Tap drag lock enabled/disabled: BOOL, 1 value */
|
||||
#define LIBINPUT_PROP_TAP_DRAG_LOCK "libinput Tapping Drag Lock Enabled"
|
||||
|
||||
/* Tap drag lock default enabled/disabled: BOOL, 1 value */
|
||||
#define LIBINPUT_PROP_TAP_DRAG_LOCK_DEFAULT "libinput Tapping Drag Lock Enabled Default"
|
||||
|
||||
/* Calibration matrix: FLOAT, 9 values of a 3x3 matrix, in rows */
|
||||
#define LIBINPUT_PROP_CALIBRATION "libinput Calibration Matrix"
|
||||
|
||||
@@ -102,4 +108,20 @@
|
||||
/* Middle button emulation: BOOL, 1 value, read-only */
|
||||
#define LIBINPUT_PROP_MIDDLE_EMULATION_ENABLED_DEFAULT "libinput Middle Emulation Enabled Default"
|
||||
|
||||
/* Disable while typing: BOOL, 1 value */
|
||||
#define LIBINPUT_PROP_DISABLE_WHILE_TYPING "libinput Disable While Typing Enabled"
|
||||
|
||||
/* Disable while typing: BOOL, 1 value, read-only */
|
||||
#define LIBINPUT_PROP_DISABLE_WHILE_TYPING_DEFAULT "libinput Disable While Typing Enabled Default"
|
||||
|
||||
/* Drag lock buttons, either:
|
||||
CARD8, one value, the meta lock button, or
|
||||
CARD8, n * 2 values, the drag lock pairs with n being the button and n+1
|
||||
the target button number */
|
||||
#define LIBINPUT_PROP_DRAG_LOCK_BUTTONS "libinput Drag Lock Buttons"
|
||||
|
||||
/* Horizontal scroll events enabled: BOOL, 1 value (0 or 1).
|
||||
* If disabled, horizontal scroll events are discarded */
|
||||
#define LIBINPUT_PROP_HORIZ_SCROLL_ENABLED "libinput Horizonal Scroll Enabled"
|
||||
|
||||
#endif /* _LIBINPUT_PROPERTIES_H_ */
|
||||
|
||||
@@ -44,6 +44,9 @@ are supported:
|
||||
.BI "Option \*qDevice\*q \*q" string \*q
|
||||
Specifies the device through which the device can be accessed. This will
|
||||
generally be of the form \*q/dev/input/eventX\*q, where X is some integer.
|
||||
When using
|
||||
.B InputClass
|
||||
directives, this option is set by the server.
|
||||
The mapping from device node to hardware is system-dependent. Property:
|
||||
"Device Node" (read-only).
|
||||
.TP 7
|
||||
@@ -64,7 +67,8 @@ default mapping. See section
|
||||
for more details.
|
||||
.TP 7
|
||||
.BI "Option \*qCalibrationMatrix\*q \*q" string \*q
|
||||
A string of 9 space-separated floating point numbers.
|
||||
A string of 9 space-separated floating point numbers, in the order
|
||||
\*qa b c d e f g h i\*q.
|
||||
Sets the calibration matrix to the 3x3 matrix where the first row is (abc),
|
||||
the second row is (def) and the third row is (ghi).
|
||||
.TP 7
|
||||
@@ -103,12 +107,49 @@ Enables a scroll method. Permitted values are
|
||||
Not all devices support all options, if an option is unsupported, the
|
||||
default scroll option for this device is used.
|
||||
.TP 7
|
||||
.BI "Option \*qHorizontalScrolling\*q" bool \*q
|
||||
Disables horizontal scrolling. When disabled, this driver will discard any
|
||||
horizontal scroll events from libinput. Note that this does not disable
|
||||
horizontal scrolling, it merely discards the horizontal axis from any scroll
|
||||
events.
|
||||
.TP 7
|
||||
.BI "Option \*qSendEventsMode\*q \*q" (disabled|enabled|disabled-on-external-mouse) \*q
|
||||
Sets the send events mode to disabled, enabled, or "disable when an external
|
||||
mouse is connected".
|
||||
.TP 7
|
||||
.BI "Option \*qTapping\*q \*q" bool \*q
|
||||
Enables or disables tap-to-click behavior.
|
||||
.TP 7
|
||||
.BI "Option \*qTappingDragLock\*q \*q" bool \*q
|
||||
Enables or disables drag lock during tapping behavior. When enabled, a
|
||||
finger up during tap-and-drag will not immediately release the button. If
|
||||
the finger is set down again within the timeout, the dragging process
|
||||
continues.
|
||||
.TP 7
|
||||
.BI "Option \*qDisableWhileTyping\*q \*q" bool \*q
|
||||
Indicates if the touchpad should be disabled while typing on the keyboard
|
||||
(this does not apply to modifier keys such as Ctrl or Alt).
|
||||
.TP 7
|
||||
.BI "Option \*qDragLockButtons\*q \*q" "L1 B1 L2 B2 ..." \*q
|
||||
Sets "drag lock buttons" that simulate a button logically down even when it has
|
||||
been physically released. To logically release a locked button, a second click
|
||||
of the same button is required.
|
||||
.IP
|
||||
If the option is a single button number, that button acts as the
|
||||
"meta" locking button for the next button number. See section
|
||||
.B BUTTON DRAG LOCK
|
||||
for details.
|
||||
.IP
|
||||
If the option is a list of button number pairs, the first number of each
|
||||
number pair is the lock button, the second number the logical button number
|
||||
to be locked. See section
|
||||
.B BUTTON DRAG LOCK
|
||||
for details.
|
||||
.IP
|
||||
For both meta and button pair configuration, the button numbers are
|
||||
device button numbers, i.e. the
|
||||
.B ButtonMapping
|
||||
applies after drag lock.
|
||||
.PP
|
||||
For all options, the options are only parsed if the device supports that
|
||||
configuration option. For all options, the default value is the one used by
|
||||
@@ -126,6 +167,9 @@ driver.
|
||||
.BI "libinput Tapping Enabled"
|
||||
1 boolean value (8 bit, 0 or 1). 1 enables tapping
|
||||
.TP 7
|
||||
.BI "libinput Tapping Drag Lock Enabled"
|
||||
1 boolean value (8 bit, 0 or 1). 1 enables drag lock during tapping
|
||||
.TP 7
|
||||
.BI "libinput Calibration Matrix"
|
||||
9 32-bit float values, representing a 3x3 calibration matrix, order is row
|
||||
1, row 2, row 3
|
||||
@@ -174,11 +218,24 @@ Indicates which click methods are enabled on this device.
|
||||
.BI "libinput Middle Emulation Enabled"
|
||||
1 boolean value (8 bit, 0 or 1). Indicates if middle emulation is enabled or
|
||||
disabled.
|
||||
.TP7
|
||||
.TP 7
|
||||
.BI "libinput Disable While Typing Enabled"
|
||||
1 boolean value (8 bit, 0 or 1). Indicates if disable while typing is
|
||||
enabled or disabled.
|
||||
.PP
|
||||
The above properties have a
|
||||
.BI "libinput <property name> Default"
|
||||
equivalent that indicates the default value for this setting on this device.
|
||||
.TP 7
|
||||
.BI "libinput Drag Lock Buttons"
|
||||
Either one 8-bit value specifying the meta drag lock button, or a list of
|
||||
button pairs. See section
|
||||
.B BUTTON DRAG LOCK
|
||||
for details.
|
||||
.TP 7
|
||||
.BI "libinput Horizontal Scrolling Enabled"
|
||||
1 boolean value (8 bit, 0 or 1). Indicates whether horizontal scrolling
|
||||
events are enabled or not.
|
||||
|
||||
.SH BUTTON MAPPING
|
||||
X clients receive events with logical button numbers, where 1, 2, 3
|
||||
@@ -205,6 +262,24 @@ __xservername__ input driver does not use the button mapping after setup.
|
||||
Use XSetPointerMapping(__libmansuffix__) to modify the button mapping at
|
||||
runtime.
|
||||
|
||||
.SH BUTTON DRAG LOCK
|
||||
Button drag lock holds a button logically down even when the button itself
|
||||
has been physically released since. Button drag lock comes in two modes.
|
||||
.PP
|
||||
If in "meta" mode, a meta button click activates drag lock for the next
|
||||
button press of any other button. A button click in the future will keep
|
||||
that button held logically down until a subsequent click of that same
|
||||
button. The meta button events themselves are discarded. A separate meta
|
||||
button click is required each time a drag lock should be activated for a
|
||||
button in the future.
|
||||
.PP
|
||||
If in "pairs" mode, each button can be assigned a target locking button.
|
||||
On button click, the target lock button is held logically down until the
|
||||
next click of the same button. The button events themselves are discarded
|
||||
and only the target button events are sent.
|
||||
.TP
|
||||
This feature is provided by this driver, not by libinput.
|
||||
|
||||
.SH AUTHORS
|
||||
Peter Hutterer
|
||||
.SH "SEE ALSO"
|
||||
|
||||
@@ -30,8 +30,10 @@ AM_CPPFLAGS =-I$(top_srcdir)/include $(LIBINPUT_CFLAGS)
|
||||
|
||||
@DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
|
||||
@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
|
||||
@DRIVER_NAME@_drv_la_LIBADD = $(LIBINPUT_LIBS)
|
||||
@DRIVER_NAME@_drv_la_LIBADD = $(LIBINPUT_LIBS) libdraglock.la
|
||||
@DRIVER_NAME@_drv_ladir = @inputdir@
|
||||
|
||||
@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c
|
||||
@DRIVER_NAME@_drv_la_SOURCES = xf86libinput.c
|
||||
|
||||
noinst_LTLIBRARIES = libdraglock.la
|
||||
libdraglock_la_SOURCES = draglock.c draglock.h
|
||||
|
||||
282
src/draglock.c
Normal file
282
src/draglock.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright © 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "draglock.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
|
||||
|
||||
static int
|
||||
draglock_parse_config(struct draglock *dl, const char *config)
|
||||
{
|
||||
int button = 0, target = 0;
|
||||
const char *str = NULL;
|
||||
char *end_str = NULL;
|
||||
int pairs[DRAGLOCK_MAX_BUTTONS] = {0};
|
||||
|
||||
if (!config)
|
||||
return 0;
|
||||
|
||||
/* empty string disables drag lock */
|
||||
if (*config == '\0') {
|
||||
dl->mode = DRAGLOCK_DISABLED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check for a single-number string first, config is "<int>" */
|
||||
button = strtol(config, &end_str, 10);
|
||||
if (*end_str == '\0') {
|
||||
if (button < 0 || button >= DRAGLOCK_MAX_BUTTONS)
|
||||
return 1;
|
||||
/* we allow for button 0 so stacked xorg.conf.d snippets can
|
||||
* disable the config again */
|
||||
if (button == 0) {
|
||||
dl->mode = DRAGLOCK_DISABLED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return draglock_set_meta(dl, button);
|
||||
}
|
||||
|
||||
dl->mode = DRAGLOCK_DISABLED;
|
||||
|
||||
/* check for a set of button pairs, config is
|
||||
* "<int> <int> <int> <int>..." */
|
||||
str = config;
|
||||
while (*str != '\0') {
|
||||
button = strtol(str, &end_str, 10);
|
||||
if (*end_str == '\0')
|
||||
return 1;
|
||||
|
||||
str = end_str;
|
||||
target = strtol(str, &end_str, 10);
|
||||
if (end_str == str)
|
||||
return 1;
|
||||
if (button <= 0 || button >= DRAGLOCK_MAX_BUTTONS || target >= DRAGLOCK_MAX_BUTTONS)
|
||||
return 1;
|
||||
|
||||
pairs[button] = target;
|
||||
str = end_str;
|
||||
}
|
||||
|
||||
return draglock_set_pairs(dl, pairs, ARRAY_SIZE(pairs));
|
||||
}
|
||||
|
||||
int
|
||||
draglock_init_from_string(struct draglock *dl, const char *config)
|
||||
{
|
||||
dl->mode = DRAGLOCK_DISABLED;
|
||||
|
||||
dl->meta_button = 0;
|
||||
dl->meta_state = false;
|
||||
memset(dl->lock_pair, 0, sizeof(dl->lock_pair));
|
||||
memset(dl->lock_state, 0, sizeof(dl->lock_state));
|
||||
|
||||
return draglock_parse_config(dl, config);
|
||||
}
|
||||
|
||||
enum draglock_mode
|
||||
draglock_get_mode(const struct draglock *dl)
|
||||
{
|
||||
return dl->mode;
|
||||
}
|
||||
|
||||
int
|
||||
draglock_get_meta(const struct draglock *dl)
|
||||
{
|
||||
if (dl->mode == DRAGLOCK_META)
|
||||
return dl->meta_button;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
draglock_get_pairs(const struct draglock *dl, int *array, size_t sz)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t last = 0;
|
||||
|
||||
if (dl->mode != DRAGLOCK_PAIRS)
|
||||
return 0;
|
||||
|
||||
/* size 1 array with the meta button */
|
||||
if (dl->meta_button) {
|
||||
*array = dl->meta_button;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* size N array with a[0] == 0, the rest ordered by button number */
|
||||
memset(array, 0, sz * sizeof(array[0]));
|
||||
for (i = 0; i < sz && i < ARRAY_SIZE(dl->lock_pair); i++) {
|
||||
array[i] = dl->lock_pair[i];
|
||||
if (array[i] != 0 && i > last)
|
||||
last = i;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
int
|
||||
draglock_set_meta(struct draglock *dl, int meta_button)
|
||||
{
|
||||
if (meta_button < 0 || meta_button >= DRAGLOCK_MAX_BUTTONS)
|
||||
return 1;
|
||||
|
||||
dl->meta_button = meta_button;
|
||||
dl->mode = meta_button ? DRAGLOCK_META : DRAGLOCK_DISABLED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
draglock_set_pairs(struct draglock *dl, const int *array, size_t sz)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (sz == 0 || array[0] != 0)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < sz; i++) {
|
||||
if (array[i] < 0 || array[i] >= DRAGLOCK_MAX_BUTTONS)
|
||||
return 1;
|
||||
}
|
||||
|
||||
dl->mode = DRAGLOCK_DISABLED;
|
||||
for (i = 0; i < sz; i++) {
|
||||
dl->lock_pair[i] = array[i];
|
||||
if (dl->lock_pair[i])
|
||||
dl->mode = DRAGLOCK_PAIRS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
draglock_filter_meta(struct draglock *dl, int *button, int *press)
|
||||
{
|
||||
int b = *button,
|
||||
is_press = *press;
|
||||
|
||||
if (b == dl->meta_button) {
|
||||
if (is_press)
|
||||
dl->meta_state = true;
|
||||
*button = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (dl->lock_state[b]) {
|
||||
case DRAGLOCK_BUTTON_STATE_NONE:
|
||||
if (dl->meta_state && is_press) {
|
||||
dl->lock_state[b] = DRAGLOCK_BUTTON_STATE_DOWN_1;
|
||||
dl->meta_state = false;
|
||||
}
|
||||
break;
|
||||
case DRAGLOCK_BUTTON_STATE_DOWN_1:
|
||||
if (!is_press) {
|
||||
dl->lock_state[b] = DRAGLOCK_BUTTON_STATE_UP_1;
|
||||
b = 0;
|
||||
}
|
||||
break;
|
||||
case DRAGLOCK_BUTTON_STATE_UP_1:
|
||||
if (is_press) {
|
||||
dl->lock_state[b] = DRAGLOCK_BUTTON_STATE_DOWN_2;
|
||||
b = 0;
|
||||
}
|
||||
break;
|
||||
case DRAGLOCK_BUTTON_STATE_DOWN_2:
|
||||
if (!is_press) {
|
||||
dl->lock_state[b] = DRAGLOCK_BUTTON_STATE_NONE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
*button = b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
draglock_filter_pair(struct draglock *dl, int *button, int *press)
|
||||
{
|
||||
int b = *button,
|
||||
is_press = *press;
|
||||
|
||||
if (dl->lock_pair[b] == 0)
|
||||
return 0;
|
||||
|
||||
switch (dl->lock_state[b]) {
|
||||
case DRAGLOCK_BUTTON_STATE_NONE:
|
||||
if (is_press) {
|
||||
dl->lock_state[b] = DRAGLOCK_BUTTON_STATE_DOWN_1;
|
||||
b = dl->lock_pair[b];
|
||||
}
|
||||
break;
|
||||
case DRAGLOCK_BUTTON_STATE_DOWN_1:
|
||||
if (!is_press) {
|
||||
dl->lock_state[b] = DRAGLOCK_BUTTON_STATE_UP_1;
|
||||
b = 0;
|
||||
}
|
||||
break;
|
||||
case DRAGLOCK_BUTTON_STATE_UP_1:
|
||||
if (is_press) {
|
||||
dl->lock_state[b] = DRAGLOCK_BUTTON_STATE_DOWN_2;
|
||||
b = 0;
|
||||
}
|
||||
break;
|
||||
case DRAGLOCK_BUTTON_STATE_DOWN_2:
|
||||
if (!is_press) {
|
||||
dl->lock_state[b] = DRAGLOCK_BUTTON_STATE_NONE;
|
||||
b = dl->lock_pair[b];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
*button = b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
draglock_filter_button(struct draglock *dl, int *button, int *is_press)
|
||||
{
|
||||
if (*button == 0)
|
||||
return 0;
|
||||
|
||||
switch(dl->mode) {
|
||||
case DRAGLOCK_DISABLED:
|
||||
return 0;
|
||||
case DRAGLOCK_META:
|
||||
return draglock_filter_meta(dl, button, is_press);
|
||||
case DRAGLOCK_PAIRS:
|
||||
return draglock_filter_pair(dl, button, is_press);
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
159
src/draglock.h
Normal file
159
src/draglock.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright © 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef DRAGLOCK_H
|
||||
#define DRAGLOCK_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 32 buttons are enough for everybody™
|
||||
* Note that this is the limit of physical buttons as well as the highest
|
||||
* allowed target button.
|
||||
*/
|
||||
#define DRAGLOCK_MAX_BUTTONS 32
|
||||
|
||||
enum draglock_mode
|
||||
{
|
||||
DRAGLOCK_DISABLED,
|
||||
DRAGLOCK_META,
|
||||
DRAGLOCK_PAIRS
|
||||
};
|
||||
|
||||
enum draglock_button_state
|
||||
{
|
||||
DRAGLOCK_BUTTON_STATE_NONE,
|
||||
DRAGLOCK_BUTTON_STATE_DOWN_1,
|
||||
DRAGLOCK_BUTTON_STATE_UP_1,
|
||||
DRAGLOCK_BUTTON_STATE_DOWN_2,
|
||||
};
|
||||
|
||||
struct draglock
|
||||
{
|
||||
enum draglock_mode mode;
|
||||
int meta_button; /* meta key to lock any button */
|
||||
bool meta_state; /* meta_button state */
|
||||
unsigned int lock_pair[DRAGLOCK_MAX_BUTTONS + 1];/* specify a meta/lock pair */
|
||||
enum draglock_button_state lock_state[DRAGLOCK_MAX_BUTTONS + 1]; /* state of any locked buttons */
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the draglock struct based on the config string. The string is
|
||||
* either a single number to configure DRAGLOCK_META mode or a list of
|
||||
* number pairs, with pair[0] as button and pair[1] as target lock number to
|
||||
* configure DRAGLOCK_PAIRS mode.
|
||||
*
|
||||
* If config is NULL, the empty string, "0" or an even-numbered list of 0,
|
||||
* the drag lock mode is DRAGLOCK_DISABLED.
|
||||
*
|
||||
* @return 0 on success or nonzero on error
|
||||
*/
|
||||
int
|
||||
draglock_init_from_string(struct draglock *dl, const char *config);
|
||||
|
||||
/**
|
||||
* Get the current drag lock mode.
|
||||
*
|
||||
* If the mode is DRAGLOCK_META, a meta button click will cause the next
|
||||
* subsequent button click to be held logically down until the release of
|
||||
* the second button click of that same button. Events from the meta button
|
||||
* are always discarded.
|
||||
*
|
||||
* If the mode is DRAGLOCK_PAIRS, any button may be configured with a
|
||||
* 'target' button number. A click of that button causes the target button
|
||||
* to be held logically down until the release of the second button click.
|
||||
*/
|
||||
enum draglock_mode
|
||||
draglock_get_mode(const struct draglock *dl);
|
||||
|
||||
/**
|
||||
* @return the meta button number or 0 if the current mode is not
|
||||
* DRAGLOCK_META.
|
||||
*/
|
||||
int
|
||||
draglock_get_meta(const struct draglock *dl);
|
||||
|
||||
/**
|
||||
* Get the drag lock button mapping pairs. The array is filled with the
|
||||
* button number as index and the mapped target button number as value, i.e.
|
||||
* array[3] == 8 means button 3 will draglock button 8.
|
||||
*
|
||||
* A value of 0 indicates draglock is disabled for that button.
|
||||
*
|
||||
* @note Button numbers start at 1, array[0] is always 0.
|
||||
*
|
||||
* @param[in|out] array Caller-allocated array to hold the button mappings.
|
||||
* @param[in] sz Maximum number of elements in array
|
||||
*
|
||||
* @return The number of valid elements in array or 0 if the current mode is
|
||||
* not DRAGLOCK_PAIRS
|
||||
*/
|
||||
size_t
|
||||
draglock_get_pairs(const struct draglock *dl, int *array, size_t sz);
|
||||
|
||||
/**
|
||||
* Set the drag lock config to the DRAGLOCK_META mode, with the given
|
||||
* button as meta button.
|
||||
*
|
||||
* If the button is 0 the mode becomes DRAGLOCK_DISABLED.
|
||||
*
|
||||
* @return 0 on success, nonzero otherwise
|
||||
*/
|
||||
int
|
||||
draglock_set_meta(struct draglock *dl, int meta_button);
|
||||
|
||||
/**
|
||||
* Set the drag lock config to the DRAGLOCK_PAIRS mode. The array
|
||||
* must be filled with the button number as index and the mapped target
|
||||
* button number as value, i.e.
|
||||
* array[3] == 8 means button 3 will draglock button 8.
|
||||
*
|
||||
* A value of 0 indicates draglock is disabled for that button. If all
|
||||
* buttons are 0, the mode becomes DRAGLOCK_DISABLED.
|
||||
*
|
||||
* @note Button numbers start at 1, array[0] is always 0.
|
||||
*
|
||||
* @return 0 on successor nonzero otherwise
|
||||
*/
|
||||
int
|
||||
draglock_set_pairs(struct draglock *dl, const int *array, size_t sz);
|
||||
|
||||
/**
|
||||
* Process the given button event through the drag lock state machine.
|
||||
* If the event is to be discarded by the caller, button is set to 0.
|
||||
* Otherwise, button is set to the button event to process and is_press is
|
||||
* set to the button state to process.
|
||||
*
|
||||
* @param[in|out] button The button number to process
|
||||
* @param[in|out] is_press nonzero for press, zero for release
|
||||
*
|
||||
* @return 0 on success or 1 on error
|
||||
*/
|
||||
int
|
||||
draglock_filter_button(struct draglock *dl, int *button, int *is_press);
|
||||
|
||||
#endif /* DRAGLOCK_H */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2013 Red Hat, Inc.
|
||||
* 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
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/epoll.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
@@ -35,18 +34,26 @@
|
||||
#include <exevents.h>
|
||||
#include <xkbsrv.h>
|
||||
#include <xf86Xinput.h>
|
||||
#include <xf86_OSproc.h>
|
||||
#include <xserver-properties.h>
|
||||
#include <libinput.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "draglock.h"
|
||||
#include "libinput-properties.h"
|
||||
|
||||
#ifndef XI86_SERVER_FD
|
||||
#define XI86_SERVER_FD 0x20
|
||||
#endif
|
||||
|
||||
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) * 1000 + GET_ABI_MINOR(ABI_XINPUT_VERSION) > 22000
|
||||
#define HAVE_VMASK_UNACCEL 1
|
||||
#else
|
||||
#undef HAVE_VMASK_UNACCEL
|
||||
#endif
|
||||
|
||||
#define TOUCHPAD_NUM_AXES 4 /* x, y, hscroll, vscroll */
|
||||
#define TOUCH_MAX_SLOTS 15
|
||||
#define XORG_KEYCODE_OFFSET 8
|
||||
@@ -85,13 +92,18 @@ struct xf86libinput {
|
||||
double y_remainder;
|
||||
} scale;
|
||||
|
||||
BOOL has_abs;
|
||||
|
||||
ValuatorMask *valuators;
|
||||
ValuatorMask *valuators_unaccelerated;
|
||||
|
||||
struct options {
|
||||
BOOL tapping;
|
||||
BOOL tap_drag_lock;
|
||||
BOOL natural_scrolling;
|
||||
BOOL left_handed;
|
||||
BOOL middle_emulation;
|
||||
BOOL disable_while_typing;
|
||||
CARD32 sendevents;
|
||||
CARD32 scroll_button; /* xorg button number */
|
||||
float speed;
|
||||
@@ -100,22 +112,11 @@ struct xf86libinput {
|
||||
enum libinput_config_click_method click_method;
|
||||
|
||||
unsigned char btnmap[MAX_BUTTONS + 1];
|
||||
} options;
|
||||
};
|
||||
|
||||
/*
|
||||
libinput provides a userdata for the context, but not per path device. so
|
||||
the open_restricted call has the libinput context, but no reference to
|
||||
the pInfo->fd that we actually need to return.
|
||||
To avoid this, we store each path/fd combination during pre_init in the
|
||||
context, then return that during open_restricted. If a device is added
|
||||
twice with two different fds this may give us the wrong fd but why are
|
||||
you doing that anyway.
|
||||
*/
|
||||
struct serverfd {
|
||||
struct xorg_list node;
|
||||
int fd;
|
||||
char *path;
|
||||
BOOL horiz_scrolling_enabled;
|
||||
} options;
|
||||
|
||||
struct draglock draglock;
|
||||
};
|
||||
|
||||
static inline int
|
||||
@@ -123,60 +124,6 @@ use_server_fd(const InputInfoPtr pInfo) {
|
||||
return pInfo->fd > -1 && (pInfo->flags & XI86_SERVER_FD);
|
||||
}
|
||||
|
||||
static inline void
|
||||
fd_push(struct xf86libinput_driver *context,
|
||||
int fd,
|
||||
const char *path)
|
||||
{
|
||||
struct serverfd *sfd = xnfcalloc(1, sizeof(*sfd));
|
||||
|
||||
sfd->fd = fd;
|
||||
sfd->path = xnfstrdup(path);
|
||||
xorg_list_add(&sfd->node, &context->server_fds);
|
||||
}
|
||||
|
||||
static inline int
|
||||
fd_get(struct xf86libinput_driver *context,
|
||||
const char *path)
|
||||
{
|
||||
struct serverfd *sfd;
|
||||
|
||||
xorg_list_for_each_entry(sfd, &context->server_fds, node) {
|
||||
if (strcmp(path, sfd->path) == 0)
|
||||
return sfd->fd;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
fd_pop(struct xf86libinput_driver *context, int fd)
|
||||
{
|
||||
struct serverfd *sfd;
|
||||
|
||||
xorg_list_for_each_entry(sfd, &context->server_fds, node) {
|
||||
if (fd != sfd->fd)
|
||||
continue;
|
||||
|
||||
xorg_list_del(&sfd->node);
|
||||
free(sfd->path);
|
||||
free(sfd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
fd_find(struct xf86libinput_driver *context, int fd)
|
||||
{
|
||||
struct serverfd *sfd;
|
||||
|
||||
xorg_list_for_each_entry(sfd, &context->server_fds, node) {
|
||||
if (fd == sfd->fd)
|
||||
return fd;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
btn_linux2xorg(unsigned int b)
|
||||
{
|
||||
@@ -253,6 +200,13 @@ LibinputApplyConfig(DeviceIntPtr dev)
|
||||
"Failed to set Tapping to %d\n",
|
||||
driver_data->options.tapping);
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count(device) > 0 &&
|
||||
libinput_device_config_tap_set_drag_lock_enabled(device,
|
||||
driver_data->options.tap_drag_lock) != LIBINPUT_CONFIG_STATUS_SUCCESS)
|
||||
xf86IDrvMsg(pInfo, X_ERROR,
|
||||
"Failed to set Tapping DragLock to %d\n",
|
||||
driver_data->options.tap_drag_lock);
|
||||
|
||||
if (libinput_device_config_calibration_has_matrix(device) &&
|
||||
libinput_device_config_calibration_set_matrix(device,
|
||||
driver_data->options.matrix) != LIBINPUT_CONFIG_STATUS_SUCCESS)
|
||||
@@ -321,6 +275,13 @@ LibinputApplyConfig(DeviceIntPtr dev)
|
||||
xf86IDrvMsg(pInfo, X_ERROR,
|
||||
"Failed to set MiddleEmulation to %d\n",
|
||||
driver_data->options.middle_emulation);
|
||||
|
||||
if (libinput_device_config_dwt_is_available(device) &&
|
||||
libinput_device_config_dwt_set_enabled(device,
|
||||
driver_data->options.disable_while_typing) != LIBINPUT_CONFIG_STATUS_SUCCESS)
|
||||
xf86IDrvMsg(pInfo, X_ERROR,
|
||||
"Failed to set DisableWhileTyping to %d\n",
|
||||
driver_data->options.disable_while_typing);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -331,12 +292,6 @@ xf86libinput_on(DeviceIntPtr dev)
|
||||
struct libinput *libinput = driver_context.libinput;
|
||||
struct libinput_device *device = driver_data->device;
|
||||
|
||||
if (use_server_fd(pInfo)) {
|
||||
char *path = xf86SetStrOption(pInfo->options, "Device", NULL);
|
||||
fd_push(&driver_context, pInfo->fd, path);
|
||||
free(path);
|
||||
}
|
||||
|
||||
device = libinput_path_add_device(libinput, driver_data->path);
|
||||
if (!device)
|
||||
return !Success;
|
||||
@@ -375,7 +330,6 @@ xf86libinput_off(DeviceIntPtr dev)
|
||||
}
|
||||
|
||||
if (use_server_fd(pInfo)) {
|
||||
fd_pop(&driver_context, pInfo->fd);
|
||||
pInfo->fd = xf86SetIntOption(pInfo->options, "fd", -1);
|
||||
} else {
|
||||
pInfo->fd = -1;
|
||||
@@ -447,7 +401,7 @@ xf86libinput_init_pointer(InputInfoPtr pInfo)
|
||||
Atom btnlabels[MAX_BUTTONS];
|
||||
Atom axislabels[TOUCHPAD_NUM_AXES];
|
||||
|
||||
for (i = BTN_BACK; i >= BTN_SIDE; i--) {
|
||||
for (i = BTN_JOYSTICK - 1; i >= BTN_SIDE; i--) {
|
||||
if (libinput_device_pointer_has_button(driver_data->device, i)) {
|
||||
nbuttons += i - BTN_SIDE + 1;
|
||||
break;
|
||||
@@ -526,6 +480,8 @@ xf86libinput_init_pointer_absolute(InputInfoPtr pInfo)
|
||||
SetScrollValuator(dev, 2, SCROLL_TYPE_HORIZONTAL, driver_data->scroll.hdist, 0);
|
||||
SetScrollValuator(dev, 3, SCROLL_TYPE_VERTICAL, driver_data->scroll.vdist, 0);
|
||||
|
||||
driver_data->has_abs = TRUE;
|
||||
|
||||
return Success;
|
||||
}
|
||||
static void
|
||||
@@ -636,7 +592,8 @@ xf86libinput_init(DeviceIntPtr dev)
|
||||
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD))
|
||||
xf86libinput_init_keyboard(pInfo);
|
||||
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) {
|
||||
if (libinput_device_config_calibration_has_matrix(device))
|
||||
if (libinput_device_config_calibration_has_matrix(device) &&
|
||||
!libinput_device_config_accel_is_available(device))
|
||||
xf86libinput_init_pointer_absolute(pInfo);
|
||||
else
|
||||
xf86libinput_init_pointer(pInfo);
|
||||
@@ -695,9 +652,21 @@ xf86libinput_handle_motion(InputInfoPtr pInfo, struct libinput_event_pointer *ev
|
||||
y = libinput_event_pointer_get_dy(event);
|
||||
|
||||
valuator_mask_zero(mask);
|
||||
|
||||
#if HAVE_VMASK_UNACCEL
|
||||
{
|
||||
double ux, uy;
|
||||
|
||||
ux = libinput_event_pointer_get_dx_unaccelerated(event);
|
||||
uy = libinput_event_pointer_get_dy_unaccelerated(event);
|
||||
|
||||
valuator_mask_set_unaccelerated(mask, 0, x, ux);
|
||||
valuator_mask_set_unaccelerated(mask, 1, y, uy);
|
||||
}
|
||||
#else
|
||||
valuator_mask_set_double(mask, 0, x);
|
||||
valuator_mask_set_double(mask, 1, y);
|
||||
|
||||
#endif
|
||||
xf86PostMotionEventM(dev, Relative, mask);
|
||||
}
|
||||
|
||||
@@ -709,6 +678,13 @@ xf86libinput_handle_absmotion(InputInfoPtr pInfo, struct libinput_event_pointer
|
||||
ValuatorMask *mask = driver_data->valuators;
|
||||
double x, y;
|
||||
|
||||
if (!driver_data->has_abs) {
|
||||
xf86IDrvMsg(pInfo, X_ERROR,
|
||||
"Discarding absolute event from relative device. "
|
||||
"Please file a bug\n");
|
||||
return;
|
||||
}
|
||||
|
||||
x = libinput_event_pointer_get_absolute_x_transformed(event, TOUCH_AXIS_MAX);
|
||||
y = libinput_event_pointer_get_absolute_y_transformed(event, TOUCH_AXIS_MAX);
|
||||
|
||||
@@ -723,12 +699,18 @@ static void
|
||||
xf86libinput_handle_button(InputInfoPtr pInfo, struct libinput_event_pointer *event)
|
||||
{
|
||||
DeviceIntPtr dev = pInfo->dev;
|
||||
struct xf86libinput *driver_data = pInfo->private;
|
||||
int button;
|
||||
int is_press;
|
||||
|
||||
button = btn_linux2xorg(libinput_event_pointer_get_button(event));
|
||||
is_press = (libinput_event_pointer_get_button_state(event) == LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
xf86PostButtonEvent(dev, Relative, button, is_press, 0, 0);
|
||||
|
||||
if (draglock_get_mode(&driver_data->draglock) != DRAGLOCK_DISABLED)
|
||||
draglock_filter_button(&driver_data->draglock, &button, &is_press);
|
||||
|
||||
if (button)
|
||||
xf86PostButtonEvent(dev, Relative, button, is_press, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -776,6 +758,10 @@ xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *even
|
||||
}
|
||||
valuator_mask_set_double(mask, 3, value);
|
||||
}
|
||||
|
||||
if (!driver_data->options.horiz_scrolling_enabled)
|
||||
goto out;
|
||||
|
||||
axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
|
||||
if (libinput_event_pointer_has_axis(event, axis)) {
|
||||
if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) {
|
||||
@@ -787,6 +773,7 @@ xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *even
|
||||
valuator_mask_set_double(mask, 2, value);
|
||||
}
|
||||
|
||||
out:
|
||||
xf86PostMotionEventM(dev, Relative, mask);
|
||||
}
|
||||
|
||||
@@ -885,6 +872,13 @@ xf86libinput_handle_event(struct libinput_event *event)
|
||||
libinput_event_get_touch_event(event),
|
||||
libinput_event_get_type(event));
|
||||
break;
|
||||
case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
|
||||
case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
|
||||
case LIBINPUT_EVENT_GESTURE_SWIPE_END:
|
||||
case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
|
||||
case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
|
||||
case LIBINPUT_EVENT_GESTURE_PINCH_END:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -912,25 +906,57 @@ xf86libinput_read_input(InputInfoPtr pInfo)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
libinput provides a userdata for the context, but not per path device. so
|
||||
the open_restricted call has the libinput context, but no reference to
|
||||
the pInfo->fd that we actually need to return.
|
||||
The server stores the fd in the options though, so we just get it from
|
||||
there. If a device is added twice with two different fds this may give us
|
||||
the wrong fd but why are you doing that anyway.
|
||||
*/
|
||||
static int
|
||||
open_restricted(const char *path, int flags, void *data)
|
||||
{
|
||||
struct xf86libinput_driver *context = data;
|
||||
int fd;
|
||||
InputInfoPtr pInfo;
|
||||
int fd = -1;
|
||||
|
||||
fd = fd_get(context, path);
|
||||
if (fd == -1)
|
||||
fd = open(path, flags);
|
||||
nt_list_for_each_entry(pInfo, xf86FirstLocalDevice(), next) {
|
||||
char *device = xf86CheckStrOption(pInfo->options, "Device", NULL);
|
||||
|
||||
if (device != NULL && strcmp(path, device) == 0) {
|
||||
free(device);
|
||||
break;
|
||||
}
|
||||
free(device);
|
||||
}
|
||||
|
||||
if (pInfo == NULL) {
|
||||
xf86Msg(X_ERROR, "Failed to look up path '%s'\n", path);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
fd = xf86OpenSerial(pInfo->options);
|
||||
return fd < 0 ? -errno : fd;
|
||||
}
|
||||
|
||||
static void
|
||||
close_restricted(int fd, void *data)
|
||||
{
|
||||
struct xf86libinput_driver *context = data;
|
||||
InputInfoPtr pInfo;
|
||||
int server_fd = -1;
|
||||
BOOL found = FALSE;
|
||||
|
||||
if (fd_find(context, fd) == -1)
|
||||
close(fd);
|
||||
nt_list_for_each_entry(pInfo, xf86FirstLocalDevice(), next) {
|
||||
server_fd = xf86CheckIntOption(pInfo->options, "fd", -1);
|
||||
|
||||
if (server_fd == fd) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
xf86CloseSerial(fd);
|
||||
}
|
||||
|
||||
const struct libinput_interface interface = {
|
||||
@@ -1001,6 +1027,30 @@ xf86libinput_parse_tap_option(InputInfoPtr pInfo,
|
||||
return tap;
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
xf86libinput_parse_tap_drag_lock_option(InputInfoPtr pInfo,
|
||||
struct libinput_device *device)
|
||||
{
|
||||
BOOL drag_lock;
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count(device) == 0)
|
||||
return FALSE;
|
||||
|
||||
drag_lock = xf86SetBoolOption(pInfo->options,
|
||||
"TappingDragLock",
|
||||
libinput_device_config_tap_get_drag_lock_enabled(device));
|
||||
|
||||
if (libinput_device_config_tap_set_drag_lock_enabled(device, drag_lock) !=
|
||||
LIBINPUT_CONFIG_STATUS_SUCCESS) {
|
||||
xf86IDrvMsg(pInfo, X_ERROR,
|
||||
"Failed to set Tapping Drag Lock to %d\n",
|
||||
drag_lock);
|
||||
drag_lock = libinput_device_config_tap_get_drag_lock_enabled(device);
|
||||
}
|
||||
|
||||
return drag_lock;
|
||||
}
|
||||
|
||||
static inline double
|
||||
xf86libinput_parse_accel_option(InputInfoPtr pInfo,
|
||||
struct libinput_device *device)
|
||||
@@ -1053,28 +1103,28 @@ static inline enum libinput_config_send_events_mode
|
||||
xf86libinput_parse_sendevents_option(InputInfoPtr pInfo,
|
||||
struct libinput_device *device)
|
||||
{
|
||||
char *strmode;
|
||||
char *modestr;
|
||||
enum libinput_config_send_events_mode mode;
|
||||
|
||||
if (libinput_device_config_send_events_get_modes(device) == LIBINPUT_CONFIG_SEND_EVENTS_ENABLED)
|
||||
return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
|
||||
|
||||
mode = libinput_device_config_send_events_get_mode(device);
|
||||
strmode = xf86SetStrOption(pInfo->options,
|
||||
modestr = xf86SetStrOption(pInfo->options,
|
||||
"SendEventsMode",
|
||||
NULL);
|
||||
if (strmode) {
|
||||
if (strcmp(strmode, "enabled") == 0)
|
||||
if (modestr) {
|
||||
if (strcmp(modestr, "enabled") == 0)
|
||||
mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
|
||||
else if (strcmp(strmode, "disabled") == 0)
|
||||
else if (strcmp(modestr, "disabled") == 0)
|
||||
mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
|
||||
else if (strcmp(strmode, "disabled-on-external-mouse") == 0)
|
||||
else if (strcmp(modestr, "disabled-on-external-mouse") == 0)
|
||||
mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
|
||||
else
|
||||
xf86IDrvMsg(pInfo, X_ERROR,
|
||||
"Invalid SendeventsMode: %s\n",
|
||||
strmode);
|
||||
free(strmode);
|
||||
modestr);
|
||||
free(modestr);
|
||||
}
|
||||
|
||||
if (libinput_device_config_send_events_set_mode(device, mode) !=
|
||||
@@ -1267,6 +1317,29 @@ xf86libinput_parse_middleemulation_option(InputInfoPtr pInfo,
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
xf86libinput_parse_disablewhiletyping_option(InputInfoPtr pInfo,
|
||||
struct libinput_device *device)
|
||||
{
|
||||
BOOL enabled;
|
||||
|
||||
if (!libinput_device_config_dwt_is_available(device))
|
||||
return FALSE;
|
||||
|
||||
enabled = xf86SetBoolOption(pInfo->options,
|
||||
"DisableWhileTyping",
|
||||
libinput_device_config_dwt_get_default_enabled(device));
|
||||
if (libinput_device_config_dwt_set_enabled(device, enabled) !=
|
||||
LIBINPUT_CONFIG_STATUS_SUCCESS) {
|
||||
xf86IDrvMsg(pInfo, X_ERROR,
|
||||
"Failed to set DisableWhileTyping to %d\n",
|
||||
enabled);
|
||||
enabled = libinput_device_config_dwt_get_enabled(device);
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static void
|
||||
xf86libinput_parse_buttonmap_option(InputInfoPtr pInfo,
|
||||
unsigned char *btnmap,
|
||||
@@ -1302,6 +1375,26 @@ xf86libinput_parse_buttonmap_option(InputInfoPtr pInfo,
|
||||
free(mapping);
|
||||
}
|
||||
|
||||
static inline void
|
||||
xf86libinput_parse_draglock_option(InputInfoPtr pInfo,
|
||||
struct xf86libinput *driver_data)
|
||||
{
|
||||
char *str;
|
||||
|
||||
str = xf86CheckStrOption(pInfo->options, "DragLockButtons",NULL);
|
||||
if (draglock_init_from_string(&driver_data->draglock, str) != 0)
|
||||
xf86IDrvMsg(pInfo, X_ERROR,
|
||||
"Invalid DragLockButtons option: \"%s\"\n",
|
||||
str);
|
||||
free(str);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
xf86libinput_parse_horiz_scroll_option(InputInfoPtr pInfo)
|
||||
{
|
||||
return xf86SetBoolOption(pInfo->options, "HorizontalScrolling", TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
xf86libinput_parse_options(InputInfoPtr pInfo,
|
||||
struct xf86libinput *driver_data,
|
||||
@@ -1311,6 +1404,7 @@ xf86libinput_parse_options(InputInfoPtr pInfo,
|
||||
|
||||
/* libinput options */
|
||||
options->tapping = xf86libinput_parse_tap_option(pInfo, device);
|
||||
options->tap_drag_lock = xf86libinput_parse_tap_drag_lock_option(pInfo, device);
|
||||
options->speed = xf86libinput_parse_accel_option(pInfo, device);
|
||||
options->natural_scrolling = xf86libinput_parse_natscroll_option(pInfo, device);
|
||||
options->sendevents = xf86libinput_parse_sendevents_option(pInfo, device);
|
||||
@@ -1319,12 +1413,17 @@ xf86libinput_parse_options(InputInfoPtr pInfo,
|
||||
options->scroll_button = xf86libinput_parse_scrollbutton_option(pInfo, device);
|
||||
options->click_method = xf86libinput_parse_clickmethod_option(pInfo, device);
|
||||
options->middle_emulation = xf86libinput_parse_middleemulation_option(pInfo, device);
|
||||
options->disable_while_typing = xf86libinput_parse_disablewhiletyping_option(pInfo, device);
|
||||
xf86libinput_parse_calibration_option(pInfo, device, driver_data->options.matrix);
|
||||
|
||||
/* non-libinput options */
|
||||
xf86libinput_parse_buttonmap_option(pInfo,
|
||||
options->btnmap,
|
||||
sizeof(options->btnmap));
|
||||
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) {
|
||||
xf86libinput_parse_draglock_option(pInfo, driver_data);
|
||||
options->horiz_scrolling_enabled = xf86libinput_parse_horiz_scroll_option(pInfo);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1351,6 +1450,10 @@ xf86libinput_pre_init(InputDriverPtr drv,
|
||||
if (!driver_data->valuators)
|
||||
goto fail;
|
||||
|
||||
driver_data->valuators_unaccelerated = valuator_mask_new(2);
|
||||
if (!driver_data->valuators_unaccelerated)
|
||||
goto fail;
|
||||
|
||||
driver_data->scroll.vdist = 15;
|
||||
driver_data->scroll.hdist = 15;
|
||||
|
||||
@@ -1377,9 +1480,6 @@ xf86libinput_pre_init(InputDriverPtr drv,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (use_server_fd(pInfo))
|
||||
fd_push(&driver_context, pInfo->fd, path);
|
||||
|
||||
device = libinput_path_add_device(libinput, path);
|
||||
if (!device) {
|
||||
xf86IDrvMsg(pInfo, X_ERROR, "Failed to create a device for %s\n", path);
|
||||
@@ -1391,8 +1491,6 @@ xf86libinput_pre_init(InputDriverPtr drv,
|
||||
*/
|
||||
libinput_device_ref(device);
|
||||
libinput_path_remove_device(device);
|
||||
if (use_server_fd(pInfo))
|
||||
fd_pop(&driver_context, pInfo->fd);
|
||||
|
||||
pInfo->private = driver_data;
|
||||
driver_data->path = path;
|
||||
@@ -1418,10 +1516,10 @@ xf86libinput_pre_init(InputDriverPtr drv,
|
||||
|
||||
return Success;
|
||||
fail:
|
||||
if (use_server_fd(pInfo) && driver_context.libinput != NULL)
|
||||
fd_pop(&driver_context, pInfo->fd);
|
||||
if (driver_data->valuators)
|
||||
valuator_mask_free(&driver_data->valuators);
|
||||
if (driver_data->valuators_unaccelerated)
|
||||
valuator_mask_free(&driver_data->valuators_unaccelerated);
|
||||
free(path);
|
||||
free(driver_data);
|
||||
return BadValue;
|
||||
@@ -1486,6 +1584,8 @@ _X_EXPORT XF86ModuleData libinputModuleData = {
|
||||
/* libinput-specific properties */
|
||||
static Atom prop_tap;
|
||||
static Atom prop_tap_default;
|
||||
static Atom prop_tap_drag_lock;
|
||||
static Atom prop_tap_drag_lock_default;
|
||||
static Atom prop_calibration;
|
||||
static Atom prop_calibration_default;
|
||||
static Atom prop_accel;
|
||||
@@ -1507,6 +1607,12 @@ static Atom prop_click_method_enabled;
|
||||
static Atom prop_click_method_default;
|
||||
static Atom prop_middle_emulation;
|
||||
static Atom prop_middle_emulation_default;
|
||||
static Atom prop_disable_while_typing;
|
||||
static Atom prop_disable_while_typing_default;
|
||||
|
||||
/* driver properties */
|
||||
static Atom prop_draglock;
|
||||
static Atom prop_horiz_scroll;
|
||||
|
||||
/* general properties */
|
||||
static Atom prop_float;
|
||||
@@ -1564,6 +1670,37 @@ LibinputSetPropertyTap(DeviceIntPtr dev,
|
||||
return Success;
|
||||
}
|
||||
|
||||
static inline int
|
||||
LibinputSetPropertyTapDragLock(DeviceIntPtr dev,
|
||||
Atom atom,
|
||||
XIPropertyValuePtr val,
|
||||
BOOL checkonly)
|
||||
{
|
||||
InputInfoPtr pInfo = dev->public.devicePrivate;
|
||||
struct xf86libinput *driver_data = pInfo->private;
|
||||
struct libinput_device *device = driver_data->device;
|
||||
BOOL* data;
|
||||
|
||||
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
|
||||
return BadMatch;
|
||||
|
||||
data = (BOOL*)val->data;
|
||||
if (checkonly) {
|
||||
if (*data != 0 && *data != 1)
|
||||
return BadValue;
|
||||
|
||||
if (!xf86libinput_check_device(dev, atom))
|
||||
return BadMatch;
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count(device) == 0)
|
||||
return BadMatch;
|
||||
} else {
|
||||
driver_data->options.tap_drag_lock = *data;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static inline int
|
||||
LibinputSetPropertyCalibration(DeviceIntPtr dev,
|
||||
Atom atom,
|
||||
@@ -1885,6 +2022,143 @@ LibinputSetPropertyMiddleEmulation(DeviceIntPtr dev,
|
||||
return Success;
|
||||
}
|
||||
|
||||
static inline int
|
||||
LibinputSetPropertyDisableWhileTyping(DeviceIntPtr dev,
|
||||
Atom atom,
|
||||
XIPropertyValuePtr val,
|
||||
BOOL checkonly)
|
||||
{
|
||||
InputInfoPtr pInfo = dev->public.devicePrivate;
|
||||
struct xf86libinput *driver_data = pInfo->private;
|
||||
struct libinput_device *device = driver_data->device;
|
||||
BOOL* data;
|
||||
|
||||
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
|
||||
return BadMatch;
|
||||
|
||||
data = (BOOL*)val->data;
|
||||
if (checkonly) {
|
||||
if (*data != 0 && *data != 1)
|
||||
return BadValue;
|
||||
|
||||
if (!xf86libinput_check_device(dev, atom))
|
||||
return BadMatch;
|
||||
|
||||
if (!libinput_device_config_dwt_is_available(device))
|
||||
return BadMatch;
|
||||
} else {
|
||||
driver_data->options.disable_while_typing = *data;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static inline int
|
||||
prop_draglock_set_meta(struct xf86libinput *driver_data,
|
||||
const BYTE *values,
|
||||
int len,
|
||||
BOOL checkonly)
|
||||
{
|
||||
struct draglock *dl,
|
||||
dummy; /* for checkonly */
|
||||
int meta;
|
||||
|
||||
if (len > 1)
|
||||
return BadImplementation; /* should not happen */
|
||||
|
||||
dl = (checkonly) ? &dummy : &driver_data->draglock;
|
||||
meta = len > 0 ? values[0] : 0;
|
||||
|
||||
return draglock_set_meta(dl, meta) == 0 ? Success: BadValue;
|
||||
}
|
||||
|
||||
static inline int
|
||||
prop_draglock_set_pairs(struct xf86libinput *driver_data,
|
||||
const BYTE* pairs,
|
||||
int len,
|
||||
BOOL checkonly)
|
||||
{
|
||||
struct draglock *dl,
|
||||
dummy; /* for checkonly */
|
||||
int data[MAX_BUTTONS + 1] = {0};
|
||||
int i;
|
||||
int highest = 0;
|
||||
|
||||
if (len >= ARRAY_SIZE(data))
|
||||
return BadMatch;
|
||||
|
||||
if (len < 2 || len % 2)
|
||||
return BadImplementation; /* should not happen */
|
||||
|
||||
dl = (checkonly) ? &dummy : &driver_data->draglock;
|
||||
|
||||
for (i = 0; i < len; i += 2) {
|
||||
if (pairs[i] > MAX_BUTTONS)
|
||||
return BadValue;
|
||||
|
||||
data[pairs[i]] = pairs[i+1];
|
||||
highest = max(highest, pairs[i]);
|
||||
}
|
||||
|
||||
return draglock_set_pairs(dl, data, highest + 1) == 0 ? Success : BadValue;
|
||||
}
|
||||
|
||||
static inline int
|
||||
LibinputSetPropertyDragLockButtons(DeviceIntPtr dev,
|
||||
Atom atom,
|
||||
XIPropertyValuePtr val,
|
||||
BOOL checkonly)
|
||||
{
|
||||
InputInfoPtr pInfo = dev->public.devicePrivate;
|
||||
struct xf86libinput *driver_data = pInfo->private;
|
||||
|
||||
if (val->format != 8 || val->type != XA_INTEGER)
|
||||
return BadMatch;
|
||||
|
||||
/* either a single value, or pairs of values */
|
||||
if (val->size > 1 && val->size % 2)
|
||||
return BadMatch;
|
||||
|
||||
if (!xf86libinput_check_device(dev, atom))
|
||||
return BadMatch;
|
||||
|
||||
if (val->size <= 1)
|
||||
return prop_draglock_set_meta(driver_data,
|
||||
(BYTE*)val->data,
|
||||
val->size, checkonly);
|
||||
else
|
||||
return prop_draglock_set_pairs(driver_data,
|
||||
(BYTE*)val->data,
|
||||
val->size, checkonly);
|
||||
}
|
||||
|
||||
static inline int
|
||||
LibinputSetPropertyHorizScroll(DeviceIntPtr dev,
|
||||
Atom atom,
|
||||
XIPropertyValuePtr val,
|
||||
BOOL checkonly)
|
||||
{
|
||||
InputInfoPtr pInfo = dev->public.devicePrivate;
|
||||
struct xf86libinput *driver_data = pInfo->private;
|
||||
BOOL enabled;
|
||||
|
||||
if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
|
||||
return BadMatch;
|
||||
|
||||
enabled = *(BOOL*)val->data;
|
||||
if (checkonly) {
|
||||
if (enabled != 0 && enabled != 1)
|
||||
return BadValue;
|
||||
|
||||
if (!xf86libinput_check_device (dev, atom))
|
||||
return BadMatch;
|
||||
} else {
|
||||
driver_data->options.horiz_scrolling_enabled = enabled;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int
|
||||
LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
|
||||
BOOL checkonly)
|
||||
@@ -1893,6 +2167,8 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
|
||||
|
||||
if (atom == prop_tap)
|
||||
rc = LibinputSetPropertyTap(dev, atom, val, checkonly);
|
||||
else if (atom == prop_tap_drag_lock)
|
||||
rc = LibinputSetPropertyTapDragLock(dev, atom, val, checkonly);
|
||||
else if (atom == prop_calibration)
|
||||
rc = LibinputSetPropertyCalibration(dev, atom, val,
|
||||
checkonly);
|
||||
@@ -1918,8 +2194,15 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
|
||||
rc = LibinputSetPropertyClickMethod(dev, atom, val, checkonly);
|
||||
else if (atom == prop_middle_emulation)
|
||||
rc = LibinputSetPropertyMiddleEmulation(dev, atom, val, checkonly);
|
||||
else if (atom == prop_disable_while_typing)
|
||||
rc = LibinputSetPropertyDisableWhileTyping(dev, atom, val, checkonly);
|
||||
else if (atom == prop_draglock)
|
||||
rc = LibinputSetPropertyDragLockButtons(dev, atom, val, checkonly);
|
||||
else if (atom == prop_horiz_scroll)
|
||||
rc = LibinputSetPropertyHorizScroll(dev, atom, val, checkonly);
|
||||
else if (atom == prop_device || atom == prop_product_id ||
|
||||
atom == prop_tap_default ||
|
||||
atom == prop_tap_drag_lock_default ||
|
||||
atom == prop_calibration_default ||
|
||||
atom == prop_accel_default ||
|
||||
atom == prop_natural_scroll_default ||
|
||||
@@ -1928,7 +2211,8 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
|
||||
atom == prop_scroll_method_default ||
|
||||
atom == prop_scroll_button_default ||
|
||||
atom == prop_click_method_default ||
|
||||
atom == prop_middle_emulation_default)
|
||||
atom == prop_middle_emulation_default ||
|
||||
atom == prop_disable_while_typing_default)
|
||||
return BadAccess; /* read-only */
|
||||
else
|
||||
return Success;
|
||||
@@ -1987,6 +2271,30 @@ LibinputInitTapProperty(DeviceIntPtr dev,
|
||||
1, &tap);
|
||||
}
|
||||
|
||||
static void
|
||||
LibinputInitTapDragLockProperty(DeviceIntPtr dev,
|
||||
struct xf86libinput *driver_data,
|
||||
struct libinput_device *device)
|
||||
{
|
||||
BOOL drag_lock = driver_data->options.tap_drag_lock;
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count(device) == 0)
|
||||
return;
|
||||
|
||||
prop_tap_drag_lock = LibinputMakeProperty(dev,
|
||||
LIBINPUT_PROP_TAP_DRAG_LOCK,
|
||||
XA_INTEGER, 8,
|
||||
1, &drag_lock);
|
||||
if (!prop_tap_drag_lock)
|
||||
return;
|
||||
|
||||
drag_lock = libinput_device_config_tap_get_default_enabled(device);
|
||||
prop_tap_drag_lock_default = LibinputMakeProperty(dev,
|
||||
LIBINPUT_PROP_TAP_DRAG_LOCK_DEFAULT,
|
||||
XA_INTEGER, 8,
|
||||
1, &drag_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
LibinputInitCalibrationProperty(DeviceIntPtr dev,
|
||||
struct xf86libinput *driver_data,
|
||||
@@ -2205,9 +2513,6 @@ LibinputInitScrollMethodsProperty(DeviceIntPtr dev,
|
||||
return;
|
||||
|
||||
scroll_methods = libinput_device_config_scroll_get_default_method(device);
|
||||
if (scroll_methods == LIBINPUT_CONFIG_SCROLL_NO_SCROLL)
|
||||
return;
|
||||
|
||||
if (scroll_methods & LIBINPUT_CONFIG_SCROLL_2FG)
|
||||
methods[0] = TRUE;
|
||||
if (scroll_methods & LIBINPUT_CONFIG_SCROLL_EDGE)
|
||||
@@ -2336,6 +2641,75 @@ LibinputInitMiddleEmulationProperty(DeviceIntPtr dev,
|
||||
1, &middle);
|
||||
}
|
||||
|
||||
static void
|
||||
LibinputInitDisableWhileTypingProperty(DeviceIntPtr dev,
|
||||
struct xf86libinput *driver_data,
|
||||
struct libinput_device *device)
|
||||
{
|
||||
BOOL dwt = driver_data->options.disable_while_typing;
|
||||
|
||||
if (!libinput_device_config_dwt_is_available(device))
|
||||
return;
|
||||
|
||||
prop_disable_while_typing = LibinputMakeProperty(dev,
|
||||
LIBINPUT_PROP_DISABLE_WHILE_TYPING,
|
||||
XA_INTEGER,
|
||||
8,
|
||||
1,
|
||||
&dwt);
|
||||
if (!prop_disable_while_typing)
|
||||
return;
|
||||
|
||||
dwt = libinput_device_config_dwt_get_default_enabled(device);
|
||||
prop_disable_while_typing_default = LibinputMakeProperty(dev,
|
||||
LIBINPUT_PROP_DISABLE_WHILE_TYPING_DEFAULT,
|
||||
XA_INTEGER, 8,
|
||||
1, &dwt);
|
||||
}
|
||||
|
||||
static void
|
||||
LibinputInitDragLockProperty(DeviceIntPtr dev,
|
||||
struct xf86libinput *driver_data)
|
||||
{
|
||||
size_t sz;
|
||||
int dl_values[MAX_BUTTONS + 1];
|
||||
|
||||
if (!libinput_device_has_capability(driver_data->device,
|
||||
LIBINPUT_DEVICE_CAP_POINTER))
|
||||
return;
|
||||
|
||||
switch (draglock_get_mode(&driver_data->draglock)) {
|
||||
case DRAGLOCK_DISABLED:
|
||||
sz = 0; /* will be an empty property */
|
||||
break;
|
||||
case DRAGLOCK_META:
|
||||
dl_values[0] = draglock_get_meta(&driver_data->draglock);
|
||||
sz = 1;
|
||||
break;
|
||||
case DRAGLOCK_PAIRS:
|
||||
sz = draglock_get_pairs(&driver_data->draglock,
|
||||
dl_values, sizeof(dl_values));
|
||||
break;
|
||||
}
|
||||
|
||||
prop_draglock = LibinputMakeProperty(dev,
|
||||
LIBINPUT_PROP_DRAG_LOCK_BUTTONS,
|
||||
XA_INTEGER, 8,
|
||||
sz, dl_values);
|
||||
}
|
||||
|
||||
static void
|
||||
LibinputInitHorizScrollProperty(DeviceIntPtr dev,
|
||||
struct xf86libinput *driver_data)
|
||||
{
|
||||
BOOL enabled = driver_data->options.horiz_scrolling_enabled;
|
||||
|
||||
prop_horiz_scroll = LibinputMakeProperty(dev,
|
||||
LIBINPUT_PROP_HORIZ_SCROLL_ENABLED,
|
||||
XA_INTEGER, 8,
|
||||
1, &enabled);
|
||||
}
|
||||
|
||||
static void
|
||||
LibinputInitProperty(DeviceIntPtr dev)
|
||||
{
|
||||
@@ -2349,6 +2723,7 @@ LibinputInitProperty(DeviceIntPtr dev)
|
||||
prop_float = XIGetKnownProperty("FLOAT");
|
||||
|
||||
LibinputInitTapProperty(dev, driver_data, device);
|
||||
LibinputInitTapDragLockProperty(dev, driver_data, device);
|
||||
LibinputInitCalibrationProperty(dev, driver_data, device);
|
||||
LibinputInitAccelProperty(dev, driver_data, device);
|
||||
LibinputInitNaturalScrollProperty(dev, driver_data, device);
|
||||
@@ -2357,6 +2732,7 @@ LibinputInitProperty(DeviceIntPtr dev)
|
||||
LibinputInitScrollMethodsProperty(dev, driver_data, device);
|
||||
LibinputInitClickMethodsProperty(dev, driver_data, device);
|
||||
LibinputInitMiddleEmulationProperty(dev, driver_data, device);
|
||||
LibinputInitDisableWhileTypingProperty(dev, driver_data, device);
|
||||
|
||||
/* Device node property, read-only */
|
||||
device_node = driver_data->path;
|
||||
@@ -2383,4 +2759,7 @@ LibinputInitProperty(DeviceIntPtr dev)
|
||||
return;
|
||||
|
||||
XISetDevicePropertyDeletable(dev, prop_product_id, FALSE);
|
||||
|
||||
LibinputInitDragLockProperty(dev, driver_data);
|
||||
LibinputInitHorizScrollProperty(dev, driver_data);
|
||||
}
|
||||
1
test/.gitignore
vendored
Normal file
1
test/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
test-draglock
|
||||
13
test/Makefile.am
Normal file
13
test/Makefile.am
Normal file
@@ -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)
|
||||
540
test/test-draglock.c
Normal file
540
test/test-draglock.c
Normal file
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user