Compare commits

...

13 Commits

Author SHA1 Message Date
Peter Hutterer
2be6487de4 xf86-input-libinput 0.26.0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-09-15 11:26:54 +10:00
Peter Hutterer
6ce3d0249d Post a motion event before a tablet button down
Not all clients update the pointer position correctly from the button events
(for historical reasons) so we need to send a motion event before the button
event that represents a tip state change.

https://bugs.freedesktop.org/show_bug.cgi?id=101588

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-08-17 15:20:29 +10:00
Peter Hutterer
87f9fe3a6f Only initialize properties that match capabilities on a subdevice
If a device is split into multiple subdevices, usually pointer+keyboard, we
initialized properties matching the libinput device on both devices. This
results in the keyboard having e.g. a Accel Speed or Left Handed settings even
though it cannot send any events of that type.

Filter by capabilities on the subdevice so we only get those properties that
match the subdevice's capabilities.

https://bugs.freedesktop.org/show_bug.cgi?id=100900

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-05-29 08:15:20 +10:00
Peter Hutterer
0c657e0dcf Update copyright years
because why not

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-05-18 14:03:06 +10:00
Niklas Haas
ac3574958f man: add missing documentation for Accel Profile
This seems to have been simply missing from 0163482e.

cf. https://bugs.freedesktop.org/show_bug.cgi?id=101017

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-05-15 11:41:46 +10:00
Martin Kepplinger
8772a593b4 Fix config comment description to match the config
Since the config matches on tablets too, update the describing comment
accordingly.

Signed-off-by: Martin Kepplinger <martin.kepplinger@ginzinger.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-05-08 10:33:58 +10:00
Peter Hutterer
a80773a488 xf86-input-libinput 0.25.1
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-05-05 13:43:23 +10:00
Peter Hutterer
8bc694595d Post a motion event after proximity events
This patch splits the meat of xf86libinput_handle_tablet_axis into a helper
function xf86libinput_post_tablet_motion(), to be called right after we send
the proximity in event.

Clients that don't handle proximity (e.g. all XI2 clients) don't see the
coordinates we send along with the proximity events. And, for historical
reasons, they may not look at the coordinates in button events. So a device
that comes into proximity and immediately sends a tip down button event
doesn't send a motion event, causing the client to think the tip down was at
whatever the last known position was (before previous prox-out).

The practical effect is that when a user tries to draw a few dots, they end up
being connected to each other.

https://bugzilla.redhat.com/show_bug.cgi?id=1433755

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-03-22 11:14:15 +10:00
Peter Hutterer
153a7fc62f xf86-input-libinput 0.25.0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-03-09 15:58:39 +10:00
Peter Hutterer
72fb6d304e test: fix a test failure on ppc64(le) and aarch64
Caused by different results in -O0 vs -O2. The resulting array differs only
slightly but the initial sequence has one extra zero. That triggers our
assert, no other compiler flag seem to be affecting this.

Compiled with -O0:
Breakpoint 1, test_nonzero_x_linear () at test-bezier.c:157
157			assert(bezier[x] > bezier[x-1]);
(gdb) p bezier
$6 = {0 <repeats 409 times>, 1, 2, 4, 5, 7, 9, 10, 12, 14, 15, 17, 19, 21, 22,

Compiled with -O2:
(gdb) p bezier
$1 = {0 <repeats 410 times>, 1, 3, 5, 7, 9, 10, 12, 14, 15, 17, 19, 20, 22,

Printing of the temporary numbers in the decasteljau function shows that a few
of them are off by one, e.g.
    408.530612/0.836735 with O0, but
    409.510204/0.836735 with O2
Note: these are not rounding errors caused by the code, the cast to int
happens afterwards.

Hack around this by allowing for one extra zero before we check that the rest
of the curve is ascending again.

https://bugs.freedesktop.org/show_bug.cgi?id=99992

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-02-28 15:27:33 +10:00
Peter Hutterer
aae2c8ad9a Open sysfs files directly instead of going through the server
Only use-case here are pad mode LEDs that now live in /sys/class/leds. Asking
the server to open them is pointless, the server only knows how to open Option
"Device". And since the LEDs are in sysfs we should have access to them
anyway, so no need for jumping through or hula-ing hoops.

xf86CloseSerial() works as intended as it's a slim wrapper around close(), so
we only have to worry about the open() path here.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-02-27 09:34:36 +10:00
Peter Hutterer
dafc296f2d Add streq() macro, replace strcmp instances with it
And why isn't this a thing in glibc yet

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Eric Engestrom <eric.engestrom@imgtec.com>
2017-02-27 09:34:36 +10:00
Peter Hutterer
7c90f06d56 Update pad modes in a workproc, not during the input thread
Updating the property directly causes us to send events from the input thread
which has some "interesting" side effects like messing up the reply order or
just crashing the server.

Schedule a work proc instead and update it whenever the server is back in the
main thread.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-02-27 09:34:36 +10:00
5 changed files with 165 additions and 45 deletions

View File

@@ -1,4 +1,4 @@
# Match on all types of devices but tablet devices and joysticks
# Match on all types of devices but joysticks
Section "InputClass"
Identifier "libinput pointer catchall"
MatchIsPointer "on"

View File

@@ -23,7 +23,7 @@
# Initialize Autoconf
AC_PREREQ([2.60])
AC_INIT([xf86-input-libinput],
[0.24.0],
[0.26.0],
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
[xf86-input-libinput])
AC_CONFIG_SRCDIR([Makefile.am])

View File

@@ -203,6 +203,14 @@ on the device. The following properties are provided by the
.B libinput
driver.
.TP 7
.BI "libinput Accel Profiles Available"
2 boolean values (8 bit, 0 or 1), in order "adaptive", "flat".
Indicates which acceleration profiles are available on this device.
.TP 7
.BI "libinput Accel Profile Enabled"
2 boolean values (8 bit, 0 or 1), in order "adaptive", "flat".
Indicates which acceleration profile is currently enabled on this device.
.TP 7
.BI "libinput Accel Speed"
1 32-bit float value, defines the pointer speed. Value range -1, 1
.TP 7

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2013-2015 Red Hat, Inc.
* Copyright © 2013-2017 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
@@ -65,6 +65,9 @@
#define TOUCH_MAX_SLOTS 15
#define XORG_KEYCODE_OFFSET 8
#define streq(a, b) (strcmp(a, b) == 0)
#define strneq(a, b, n) (strncmp(a, b, n) == 0)
/*
libinput does not provide axis information for absolute devices, instead
it scales into the screen dimensions provided. So we set up the axes with
@@ -209,6 +212,10 @@ update_mode_prop(InputInfoPtr pInfo,
static enum event_handling
xf86libinput_handle_event(struct libinput_event *event);
static void
xf86libinput_post_tablet_motion(InputInfoPtr pInfo,
struct libinput_event_tablet_tool *event);
static inline int
use_server_fd(const InputInfoPtr pInfo) {
return pInfo->fd > -1 && (pInfo->flags & XI86_SERVER_FD);
@@ -259,7 +266,7 @@ xf86libinput_is_subdevice(InputInfoPtr pInfo)
BOOL is_subdevice;
source = xf86SetStrOption(pInfo->options, "_source", "");
is_subdevice = strcmp(source, "_driver/libinput") == 0;
is_subdevice = streq(source, "_driver/libinput");
free(source);
return is_subdevice;
@@ -1213,7 +1220,7 @@ is_libinput_device(InputInfoPtr pInfo)
BOOL rc;
driver = xf86CheckStrOption(pInfo->options, "driver", "");
rc = strcmp(driver, "libinput") == 0;
rc = streq(driver, "libinput");
free(driver);
return rc;
@@ -1713,12 +1720,15 @@ static enum event_handling
xf86libinput_handle_tablet_tip(InputInfoPtr pInfo,
struct libinput_event_tablet_tool *event)
{
DeviceIntPtr pDev = pInfo->dev;
enum libinput_tablet_tool_tip_state state;
const BOOL is_absolute = TRUE;
if (xf86libinput_tool_queue_event(event))
return EVENT_QUEUED;
xf86libinput_post_tablet_motion(pDev->public.devicePrivate, event);
state = libinput_event_tablet_tool_get_tip_state(event);
xf86PostButtonEventP(pInfo->dev,
@@ -1773,8 +1783,8 @@ xf86libinput_apply_area(InputInfoPtr pInfo, double *x, double *y)
*y = sy;
}
static enum event_handling
xf86libinput_handle_tablet_axis(InputInfoPtr pInfo,
static void
xf86libinput_post_tablet_motion(InputInfoPtr pInfo,
struct libinput_event_tablet_tool *event)
{
DeviceIntPtr dev = pInfo->dev;
@@ -1784,9 +1794,6 @@ xf86libinput_handle_tablet_axis(InputInfoPtr pInfo,
double value;
double x, y;
if (xf86libinput_tool_queue_event(event))
return EVENT_QUEUED;
x = libinput_event_tablet_tool_get_x_transformed(event,
TABLET_AXIS_MAX);
y = libinput_event_tablet_tool_get_y_transformed(event,
@@ -1836,13 +1843,23 @@ xf86libinput_handle_tablet_axis(InputInfoPtr pInfo,
default:
xf86IDrvMsg(pInfo, X_ERROR,
"Invalid rotation axis on tool\n");
return EVENT_HANDLED;
return;
}
valuator_mask_set_double(mask, valuator, value);
}
xf86PostMotionEventM(dev, Absolute, mask);
}
static enum event_handling
xf86libinput_handle_tablet_axis(InputInfoPtr pInfo,
struct libinput_event_tablet_tool *event)
{
if (xf86libinput_tool_queue_event(event))
return EVENT_QUEUED;
xf86libinput_post_tablet_motion(pInfo, event);
return EVENT_HANDLED;
}
@@ -1974,6 +1991,13 @@ xf86libinput_handle_tablet_proximity(InputInfoPtr pInfo,
xf86PostProximityEventM(pDev, in_prox, mask);
/* We have to send an extra motion event after proximity to make
* sure the client got the updated x/y coordinates, especially if
* they don't handle proximity events (XI2).
*/
if (in_prox)
xf86libinput_post_tablet_motion(pDev->public.devicePrivate, event);
return EVENT_HANDLED;
}
@@ -2184,10 +2208,16 @@ open_restricted(const char *path, int flags, void *data)
InputInfoPtr pInfo;
int fd = -1;
/* Special handling for sysfs files (used for pad LEDs) */
if (strneq(path, "/sys/", 5)) {
fd = open(path, flags);
return fd < 0 ? -errno : fd;
}
nt_list_for_each_entry(pInfo, xf86FirstLocalDevice(), next) {
char *device = xf86CheckStrOption(pInfo->options, "Device", NULL);
if (device != NULL && strcmp(path, device) == 0) {
if (device != NULL && streq(path, device)) {
free(device);
break;
}
@@ -2353,9 +2383,9 @@ xf86libinput_parse_tap_buttonmap_option(InputInfoPtr pInfo,
"TappingButtonMap",
NULL);
if (str) {
if (strcmp(str, "lmr") == 0)
if (streq(str, "lmr"))
map = LIBINPUT_CONFIG_TAP_MAP_LMR;
else if (strcmp(str, "lrm") == 0)
else if (streq(str, "lrm"))
map = LIBINPUT_CONFIG_TAP_MAP_LRM;
else
xf86IDrvMsg(pInfo, X_ERROR,
@@ -2468,11 +2498,11 @@ xf86libinput_parse_sendevents_option(InputInfoPtr pInfo,
"SendEventsMode",
NULL);
if (modestr) {
if (strcmp(modestr, "enabled") == 0)
if (streq(modestr, "enabled"))
mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
else if (strcmp(modestr, "disabled") == 0)
else if (streq(modestr, "disabled"))
mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
else if (strcmp(modestr, "disabled-on-external-mouse") == 0)
else if (streq(modestr, "disabled-on-external-mouse"))
mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
else
xf86IDrvMsg(pInfo, X_ERROR,
@@ -2866,7 +2896,7 @@ xf86libinput_parse_tablet_area_option(InputInfoPtr pInfo,
str = xf86SetStrOption(pInfo->options,
"TabletToolAreaRatio",
NULL);
if (!str || strcmp(str, "default") == 0)
if (!str || streq(str, "default"))
goto out;
rc = sscanf(str, "%d:%d", &area.x, &area.y);
@@ -3386,17 +3416,43 @@ static Atom prop_float;
static Atom prop_device;
static Atom prop_product_id;
static inline void
update_mode_prop(InputInfoPtr pInfo,
struct libinput_event_tablet_pad *event)
{
struct xf86libinput *driver_data = pInfo->private;
struct mode_prop_state {
int deviceid;
InputInfoPtr pInfo;
struct libinput_tablet_pad_mode_group *group;
unsigned int mode;
unsigned int idx;
};
static Bool
update_mode_prop_cb(ClientPtr client, pointer closure)
{
struct mode_prop_state *state = closure;
InputInfoPtr pInfo = state->pInfo, tmp;
struct xf86libinput *driver_data = pInfo->private;
BOOL found = FALSE;
XIPropertyValuePtr val;
int rc;
unsigned char groups[4] = {0};
struct libinput_tablet_pad_mode_group *group = state->group;
unsigned int mode = state->mode;
unsigned int idx = state->idx;
if (idx >= ARRAY_SIZE(groups))
goto out;
/* The device may have gotten removed before the WorkProc was
* scheduled. X reuses deviceids, but if the pointer value and
* device ID are what we had before, we're good */
nt_list_for_each_entry(tmp, xf86FirstLocalDevice(), next) {
if (tmp->dev->id == state->deviceid && tmp == pInfo) {
found = TRUE;
break;
}
}
if (!found)
goto out;
rc = XIGetDeviceProperty(pInfo->dev,
prop_mode_groups,
@@ -3404,18 +3460,12 @@ update_mode_prop(InputInfoPtr pInfo,
if (rc != Success ||
val->format != 8 ||
val->size <= 0)
return;
goto out;
memcpy(groups, (unsigned char*)val->data, val->size);
group = libinput_event_tablet_pad_get_mode_group(event);
mode = libinput_event_tablet_pad_get_mode(event);
idx = libinput_tablet_pad_mode_group_get_index(group);
if (idx >= ARRAY_SIZE(groups))
return;
if (groups[idx] == mode)
return;
goto out;
groups[idx] = mode;
@@ -3428,8 +3478,36 @@ update_mode_prop(InputInfoPtr pInfo,
groups,
TRUE);
driver_data->allow_mode_group_updates = false;
if (rc != Success)
out:
libinput_tablet_pad_mode_group_unref(group);
free(state);
return TRUE;
}
static inline void
update_mode_prop(InputInfoPtr pInfo,
struct libinput_event_tablet_pad *event)
{
struct libinput_tablet_pad_mode_group *group;
struct mode_prop_state *state;
state = calloc(1, sizeof(*state));
if (!state)
return;
state->deviceid = pInfo->dev->id;
state->pInfo = pInfo;
group = libinput_event_tablet_pad_get_mode_group(event);
state->group = libinput_tablet_pad_mode_group_ref(group);
state->mode = libinput_event_tablet_pad_get_mode(event);
state->idx = libinput_tablet_pad_mode_group_get_index(group);
/* Schedule a WorkProc so we don't update from within the input
thread */
QueueWorkProc(update_mode_prop_cb, serverClient, state);
}
static inline BOOL
@@ -5160,6 +5238,19 @@ LibinputInitTabletAreaRatioProperty(DeviceIntPtr dev,
2, data);
}
static inline bool
subdevice_filter_for_capabilities(DeviceIntPtr dev,
uint32_t capabilities)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
struct xf86libinput *driver_data = pInfo->private;
if (!xf86libinput_is_subdevice(pInfo))
return false;
return !(driver_data->capabilities & capabilities);
}
static void
LibinputInitProperty(DeviceIntPtr dev)
{
@@ -5172,21 +5263,35 @@ LibinputInitProperty(DeviceIntPtr dev)
prop_float = XIGetKnownProperty("FLOAT");
LibinputInitTapProperty(dev, driver_data, device);
LibinputInitTapDragProperty(dev, driver_data, device);
LibinputInitTapDragLockProperty(dev, driver_data, device);
LibinputInitTapButtonmapProperty(dev, driver_data, device);
LibinputInitCalibrationProperty(dev, driver_data, device);
LibinputInitAccelProperty(dev, driver_data, device);
LibinputInitNaturalScrollProperty(dev, driver_data, device);
/* On a subdevice, we likely only have a keyboard, so filter out the
* properties for the capabilities we don't have */
if (!subdevice_filter_for_capabilities(dev, CAP_POINTER|CAP_TOUCH)) {
LibinputInitTapProperty(dev, driver_data, device);
LibinputInitTapDragProperty(dev, driver_data, device);
LibinputInitTapDragLockProperty(dev, driver_data, device);
LibinputInitTapButtonmapProperty(dev, driver_data, device);
LibinputInitNaturalScrollProperty(dev, driver_data, device);
}
if (!subdevice_filter_for_capabilities(dev, CAP_TOUCH|CAP_TABLET)) {
LibinputInitCalibrationProperty(dev, driver_data, device);
LibinputInitLeftHandedProperty(dev, driver_data, device);
LibinputInitAccelProperty(dev, driver_data, device);
}
if (!subdevice_filter_for_capabilities(dev, CAP_POINTER)) {
LibinputInitScrollMethodsProperty(dev, driver_data, device);
LibinputInitClickMethodsProperty(dev, driver_data, device);
LibinputInitMiddleEmulationProperty(dev, driver_data, device);
LibinputInitRotationAngleProperty(dev, driver_data, device);
}
if (!subdevice_filter_for_capabilities(dev, CAP_TABLET_PAD)) {
LibinputInitModeGroupProperties(dev, driver_data, device);
}
LibinputInitSendEventsProperty(dev, driver_data, device);
LibinputInitLeftHandedProperty(dev, driver_data, device);
LibinputInitScrollMethodsProperty(dev, driver_data, device);
LibinputInitClickMethodsProperty(dev, driver_data, device);
LibinputInitMiddleEmulationProperty(dev, driver_data, device);
LibinputInitDisableWhileTypingProperty(dev, driver_data, device);
LibinputInitModeGroupProperties(dev, driver_data, device);
LibinputInitRotationAngleProperty(dev, driver_data, device);
/* Device node property, read-only */
device_node = driver_data->path;

View File

@@ -153,6 +153,13 @@ test_nonzero_x_linear(void)
assert(bezier[x] == 0);
} while (++x < size * 0.2 - 1);
/* ppc64le, ppc64, aarch64 have different math results at -O2,
resulting in one extra zero at the beginning of the array.
some other numbers are different too but within the error
margin (#99992) */
if (bezier[x] == 0)
x++;
do {
assert(bezier[x] > bezier[x-1]);
} while (++x < size * 0.8 - 1);