Compare commits

...

15 Commits

Author SHA1 Message Date
Peter Hutterer
efb5cacb25 xf86-input-libinput 0.5.0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2015-01-16 14:39:29 +10:00
Peter Hutterer
2348a6812a Fix for new libinput APIs
Scroll events carry multiple axes.

Left-handed config was renamed to drop the "button" bit

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2015-01-15 13:12:36 +10:00
Peter Hutterer
0c4eaf5480 Support server-side fds
libinput's device handling and server-side fd handling are a bit of a
mismatch, so this is hackier than one would hope for.

The server sets pInfo->fd and the options "fd" and "device".
The server requires pInfo->fd to be the one triggering select(2) to call the
correct pInfo->read_input. We can't pass an fd to use into libinput, all we
have is the open_restricted callback. That callback gives us the context, but
not the pInfo with the fd we want.

The solution:
1) In PreInit, store the patch + fd combination in a driver-wide list. Search
that list for an fd in open_restricted, return the pre-openend fd.

2) Overwrite all devices' pInfo->fd with the libinput epollfd. In this driver
we don't care about which device read_input is called on, we get the correct
pInfo to post events from through the struct libinput_device of the libinput
events.

3) When a device is closed, swap the real fd back in so systemd-logind closes the
right fd.

This saves us worrying about keeping the right refcount on who currently has
the fd set to the libinput fd. We just set it for all devices, let the server
figure out which device to call (the first in inputInfo.devices) and we only
need to remember to swap it back during DEVICE_OFF.

If the server calls close on a pInfo->fd without telling the driver, that's a
bug anyway.

This patch also drops the pInfo->fd = -1 calls, they've been unnecessary since
at least 1.11, possibly earlier.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2014-12-08 08:36:16 +10:00
Peter Hutterer
bc7bcca342 xf86-input-libinput 0.4.0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-12-05 15:18:40 +10:00
Peter Hutterer
e5079cd98e Require libinput 0.7.0
We've required this already anyway, now we have the libinput version to match
though

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-12-05 15:12:31 +10:00
Peter Hutterer
200be95ac9 Support absolute pointer devices
Detecting them is a bit of guesswork: if a device is a pointer device and has
a calibration matrix option, then the device must be an abs device.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-12-05 15:12:31 +10:00
Peter Hutterer
8b5dbd4c01 Split up a really long line
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-12-01 15:20:41 +10:00
Peter Hutterer
fb5c5b6f85 Move the option parsing into a separate function
No functional changes, makes preinit a bit more digestible.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-12-01 11:52:28 +10:00
Peter Hutterer
182363d674 Change a sigsafe error to xf86IDrvMsg
We don't use the signal handler in this driver, so no need for sigsafe
logging.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-12-01 11:48:56 +10:00
Peter Hutterer
f0b14c6ccc Change the touch IDs to uints
Better overflow behavior, not that we're likely to trigger it.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-12-01 11:47:15 +10:00
Peter Hutterer
e92c9f0bad man: fix wrong option name
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-12-01 11:45:40 +10:00
Peter Hutterer
dda952fafe Leave the XKB defaults up to the server
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-12-01 11:44:11 +10:00
Peter Hutterer
17302c3352 Allow disabling scroll methods
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-12-01 11:31:30 +10:00
Peter Hutterer
7e3926f2b7 Split sendevent modes property into "available" and "current"
Clients need to know which methods are available, not just which one
is currently set. Export bitmask config options as two properties,
one read-only named "... Available" and one set-able one named "... Enabled"

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-12-01 11:31:30 +10:00
Peter Hutterer
9ad23dd1cb Split scroll methods property into "available" and "current"
Clients need to know which methods are available, not just which one is
currently set. Export bitmask config options as two properties, one read-only
named "... Available" and one set-able one named "... Enabled"

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-11-28 09:14:24 +10:00
3 changed files with 447 additions and 141 deletions

View File

@@ -23,7 +23,7 @@
# Initialize Autoconf
AC_PREREQ([2.60])
AC_INIT([xf86-input-libinput],
[0.3.0],
[0.5.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.6.0])
PKG_CHECK_MODULES(LIBINPUT, [libinput >= 0.8.0])
# Define a configure option for an alternate input module directory
AC_ARG_WITH(xorg-module-dir,

View File

@@ -48,7 +48,7 @@ The mapping from device node to hardware is system-dependent. Property:
.BI "Option \*qAccelSpeed\*q \*q" float \*q
Sets the pointer acceleration speed within the range [-1, 1]
.TP 7
.BI "Option \*qCalibration\*q \*q" string \*q
.BI "Option \*qCalibrationMatrix\*q \*q" string \*q
A string of 9 space-separated floating point numbers.
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).

View File

@@ -31,6 +31,7 @@
#include <time.h>
#include <unistd.h>
#include <xorg-server.h>
#include <list.h>
#include <exevents.h>
#include <xkbsrv.h>
#include <xf86Xinput.h>
@@ -40,6 +41,10 @@
#include <X11/Xatom.h>
#ifndef XI86_SERVER_FD
#define XI86_SERVER_FD 0x20
#endif
#define TOUCHPAD_NUM_AXES 4 /* x, y, hscroll, vscroll */
#define TOUCH_MAX_SLOTS 15
#define XORG_KEYCODE_OFFSET 8
@@ -54,13 +59,14 @@
/*
libinput scales wheel events by DEFAULT_AXIS_STEP_DISTANCE, which is
currently 10.
currently 15.
*/
#define DEFAULT_LIBINPUT_AXIS_STEP_DISTANCE 10
#define DEFAULT_LIBINPUT_AXIS_STEP_DISTANCE 15
struct xf86libinput_driver {
struct libinput *libinput;
int device_enabled_count;
struct xorg_list server_fds;
};
static struct xf86libinput_driver driver_context;
@@ -95,6 +101,80 @@ struct xf86libinput {
} 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;
};
static inline int
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)
{
@@ -142,6 +222,7 @@ LibinputApplyConfig(DeviceIntPtr dev)
InputInfoPtr pInfo = dev->public.devicePrivate;
struct xf86libinput *driver_data = pInfo->private;
struct libinput_device *device = driver_data->device;
unsigned int scroll_button;
if (libinput_device_config_send_events_get_modes(device) != LIBINPUT_CONFIG_SEND_EVENTS_ENABLED &&
libinput_device_config_send_events_set_mode(device,
@@ -182,8 +263,8 @@ LibinputApplyConfig(DeviceIntPtr dev)
driver_data->options.matrix[6], driver_data->options.matrix[7],
driver_data->options.matrix[8]);
if (libinput_device_config_buttons_set_left_handed(device,
driver_data->options.left_handed) != LIBINPUT_CONFIG_STATUS_SUCCESS)
if (libinput_device_config_left_handed_set(device,
driver_data->options.left_handed) != LIBINPUT_CONFIG_STATUS_SUCCESS)
xf86IDrvMsg(pInfo, X_ERROR,
"Failed to set LeftHanded to %d\n",
driver_data->options.left_handed);
@@ -206,8 +287,8 @@ LibinputApplyConfig(DeviceIntPtr dev)
method);
}
if (libinput_device_config_scroll_set_button(device,
btn_xorg2linux(driver_data->options.scroll_button)) != LIBINPUT_CONFIG_STATUS_SUCCESS)
scroll_button = btn_xorg2linux(driver_data->options.scroll_button);
if (libinput_device_config_scroll_set_button(device, scroll_button) != LIBINPUT_CONFIG_STATUS_SUCCESS)
xf86IDrvMsg(pInfo, X_ERROR,
"Failed to set ScrollButton to %d\n",
driver_data->options.scroll_button);
@@ -221,13 +302,24 @@ 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;
libinput_device_ref(device);
libinput_device_set_user_data(device, pInfo);
driver_data->device = device;
/* if we use server fds, overwrite the fd with the one from
libinput nonetheless, otherwise the server won't call ReadInput
for our device. This must be swapped back to the real fd in
DEVICE_OFF so systemd-logind closes the right fd */
pInfo->fd = libinput_get_fd(libinput);
if (driver_context.device_enabled_count == 0) {
@@ -251,7 +343,13 @@ xf86libinput_off(DeviceIntPtr dev)
RemoveEnabledDevice(pInfo->fd);
}
pInfo->fd = -1;
if (use_server_fd(pInfo)) {
fd_pop(&driver_context, pInfo->fd);
pInfo->fd = xf86SetIntOption(pInfo->options, "fd", -1);
} else {
pInfo->fd = -1;
}
dev->public.on = FALSE;
libinput_device_set_user_data(driver_data->device, NULL);
@@ -354,6 +452,53 @@ xf86libinput_init_pointer(InputInfoPtr pInfo)
return Success;
}
static int
xf86libinput_init_pointer_absolute(InputInfoPtr pInfo)
{
DeviceIntPtr dev= pInfo->dev;
struct xf86libinput *driver_data = pInfo->private;
int min, max, res;
int nbuttons = 7;
int i;
unsigned char btnmap[MAX_BUTTONS + 1];
Atom btnlabels[MAX_BUTTONS];
Atom axislabels[TOUCHPAD_NUM_AXES];
for (i = BTN_BACK; i >= BTN_SIDE; i--) {
if (libinput_device_has_button(driver_data->device, i)) {
nbuttons += i - BTN_SIDE + 1;
break;
}
}
init_button_map(btnmap, ARRAY_SIZE(btnmap));
init_button_labels(btnlabels, ARRAY_SIZE(btnlabels));
init_axis_labels(axislabels, ARRAY_SIZE(axislabels));
InitPointerDeviceStruct((DevicePtr)dev, btnmap,
nbuttons,
btnlabels,
xf86libinput_ptr_ctl,
GetMotionHistorySize(),
TOUCHPAD_NUM_AXES,
axislabels);
min = 0;
max = TOUCH_AXIS_MAX;
res = 0;
xf86InitValuatorAxisStruct(dev, 0,
XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X),
min, max, res * 1000, 0, res * 1000, Absolute);
xf86InitValuatorAxisStruct(dev, 1,
XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y),
min, max, res * 1000, 0, res * 1000, Absolute);
SetScrollValuator(dev, 2, SCROLL_TYPE_HORIZONTAL, driver_data->scroll_hdist, 0);
SetScrollValuator(dev, 3, SCROLL_TYPE_VERTICAL, driver_data->scroll_vdist, 0);
return Success;
}
static void
xf86libinput_kbd_ctrl(DeviceIntPtr device, KeybdCtrl *ctrl)
{
@@ -387,16 +532,30 @@ xf86libinput_init_keyboard(InputInfoPtr pInfo)
{
DeviceIntPtr dev= pInfo->dev;
XkbRMLVOSet rmlvo = {0};
XkbRMLVOSet defaults = {0};
rmlvo.rules = xf86SetStrOption(pInfo->options, "xkb_rules", "evdev");
rmlvo.model = xf86SetStrOption(pInfo->options, "xkb_model", "pc104");
rmlvo.layout = xf86SetStrOption(pInfo->options, "xkb_layout", "us");
rmlvo.variant = xf86SetStrOption(pInfo->options, "xkb_variant", NULL);
rmlvo.options = xf86SetStrOption(pInfo->options, "xkb_options", NULL);
XkbGetRulesDflts(&defaults);
rmlvo.rules = xf86SetStrOption(pInfo->options,
"xkb_rules",
defaults.rules);
rmlvo.model = xf86SetStrOption(pInfo->options,
"xkb_model",
defaults.model);
rmlvo.layout = xf86SetStrOption(pInfo->options,
"xkb_layout",
defaults.layout);
rmlvo.variant = xf86SetStrOption(pInfo->options,
"xkb_variant",
defaults.variant);
rmlvo.options = xf86SetStrOption(pInfo->options,
"xkb_options",
defaults.options);
InitKeyboardDeviceStruct(dev, &rmlvo, NULL,
xf86libinput_kbd_ctrl);
XkbFreeRMLVOSet(&rmlvo, FALSE);
XkbFreeRMLVOSet(&defaults, FALSE);
}
static void
@@ -445,8 +604,12 @@ 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))
xf86libinput_init_pointer(pInfo);
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) {
if (libinput_device_config_calibration_has_matrix(device))
xf86libinput_init_pointer_absolute(pInfo);
else
xf86libinput_init_pointer(pInfo);
}
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH))
xf86libinput_init_touch(pInfo);
@@ -506,6 +669,24 @@ xf86libinput_handle_motion(InputInfoPtr pInfo, struct libinput_event_pointer *ev
xf86PostMotionEventM(dev, Relative, mask);
}
static void
xf86libinput_handle_absmotion(InputInfoPtr pInfo, struct libinput_event_pointer *event)
{
DeviceIntPtr dev = pInfo->dev;
struct xf86libinput *driver_data = pInfo->private;
ValuatorMask *mask = driver_data->valuators;
double x, y;
x = libinput_event_pointer_get_absolute_x_transformed(event, TOUCH_AXIS_MAX);
y = libinput_event_pointer_get_absolute_y_transformed(event, TOUCH_AXIS_MAX);
valuator_mask_zero(mask);
valuator_mask_set_double(mask, 0, x);
valuator_mask_set_double(mask, 1, y);
xf86PostMotionEventM(dev, Absolute, mask);
}
static void
xf86libinput_handle_button(InputInfoPtr pInfo, struct libinput_event_pointer *event)
{
@@ -537,19 +718,38 @@ xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *even
DeviceIntPtr dev = pInfo->dev;
struct xf86libinput *driver_data = pInfo->private;
ValuatorMask *mask = driver_data->valuators;
int axis;
double value;
if (libinput_event_pointer_get_axis(event) ==
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)
axis = 3;
else
axis = 2;
value = libinput_event_pointer_get_axis_value(event) / DEFAULT_LIBINPUT_AXIS_STEP_DISTANCE;
enum libinput_pointer_axis axis;
enum libinput_pointer_axis_source source;
valuator_mask_zero(mask);
valuator_mask_set_double(mask, axis, value);
source = libinput_event_pointer_get_axis_source(event);
switch(source) {
case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
break;
default:
return;
}
axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
if (libinput_event_pointer_has_axis(event, axis)) {
if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL)
value = libinput_event_pointer_get_axis_value_discrete(event, axis);
else
value = libinput_event_pointer_get_axis_value(event, axis);
valuator_mask_set_double(mask, 3, value);
}
axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
if (libinput_event_pointer_has_axis(event, axis)) {
if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL)
value = libinput_event_pointer_get_axis_value_discrete(event, axis);
else
value = libinput_event_pointer_get_axis_value(event, axis);
valuator_mask_set_double(mask, 2, value);
}
xf86PostMotionEventM(dev, Relative, mask);
}
@@ -568,8 +768,8 @@ xf86libinput_handle_touch(InputInfoPtr pInfo,
/* libinput doesn't give us hw touch ids which X expects, so
emulate them here */
static int next_touchid;
static int touchids[TOUCH_MAX_SLOTS] = {0};
static unsigned int next_touchid;
static unsigned int touchids[TOUCH_MAX_SLOTS] = {0};
slot = libinput_event_touch_get_slot(event);
@@ -619,7 +819,8 @@ xf86libinput_handle_event(struct libinput_event *event)
case LIBINPUT_EVENT_DEVICE_REMOVED:
break;
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
/* FIXME */
xf86libinput_handle_absmotion(pInfo,
libinput_event_get_pointer_event(event));
break;
case LIBINPUT_EVENT_POINTER_MOTION:
@@ -663,7 +864,9 @@ xf86libinput_read_input(InputInfoPtr pInfo)
return;
if (rc < 0) {
ErrorFSigSafe("Error reading events: %d\n", -rc);
xf86IDrvMsg(pInfo, X_ERROR,
"Error reading events: %s\n",
strerror(-rc));
return;
}
@@ -676,14 +879,22 @@ xf86libinput_read_input(InputInfoPtr pInfo)
static int
open_restricted(const char *path, int flags, void *data)
{
int fd = open(path, flags);
struct xf86libinput_driver *context = data;
int fd;
fd = fd_get(context, path);
if (fd == -1)
fd = open(path, flags);
return fd < 0 ? -errno : fd;
}
static void
close_restricted(int fd, void *data)
{
close(fd);
struct xf86libinput_driver *context = data;
if (fd_find(context, fd) == -1)
close(fd);
}
const struct libinput_interface interface = {
@@ -730,77 +941,13 @@ xf86libinput_log_handler(struct libinput *libinput,
LogVMessageVerb(type, verbosity, format, args);
}
static int xf86libinput_pre_init(InputDriverPtr drv,
InputInfoPtr pInfo,
int flags)
static void
xf86libinput_parse_options(InputInfoPtr pInfo,
struct xf86libinput *driver_data,
struct libinput_device *device)
{
struct xf86libinput *driver_data = NULL;
struct libinput *libinput = NULL;
struct libinput_device *device;
char *path;
uint32_t scroll_methods;
pInfo->fd = -1;
pInfo->type_name = 0;
pInfo->device_control = xf86libinput_device_control;
pInfo->read_input = xf86libinput_read_input;
pInfo->control_proc = NULL;
pInfo->switch_mode = NULL;
driver_data = calloc(1, sizeof(*driver_data));
if (!driver_data)
goto fail;
driver_data->valuators = valuator_mask_new(2);
if (!driver_data->valuators)
goto fail;
driver_data->scroll_vdist = 1;
driver_data->scroll_hdist = 1;
path = xf86SetStrOption(pInfo->options, "Device", NULL);
if (!path)
goto fail;
if (!driver_context.libinput) {
driver_context.libinput = libinput_path_create_context(&interface, &driver_context);
libinput_log_set_handler(driver_context.libinput,
xf86libinput_log_handler);
/* we want all msgs, let the server filter */
libinput_log_set_priority(driver_context.libinput,
LIBINPUT_LOG_PRIORITY_DEBUG);
} else {
libinput_ref(driver_context.libinput);
}
libinput = driver_context.libinput;
if (libinput == NULL) {
xf86IDrvMsg(pInfo, X_ERROR, "Creating a device for %s failed\n", path);
goto fail;
}
device = libinput_path_add_device(libinput, path);
if (!device) {
xf86IDrvMsg(pInfo, X_ERROR, "Failed to create a device for %s\n", path);
goto fail;
}
/* We ref the device but remove it afterwards. The hope is that
between now and DEVICE_INIT/DEVICE_ON, the device doesn't change.
*/
libinput_device_ref(device);
libinput_path_remove_device(device);
pInfo->fd = -1;
pInfo->private = driver_data;
driver_data->path = path;
driver_data->device = device;
/* Disable acceleration in the server, libinput does it for us */
pInfo->options = xf86ReplaceIntOption(pInfo->options, "AccelerationProfile", -1);
pInfo->options = xf86ReplaceStrOption(pInfo->options, "AccelerationScheme", "none");
if (libinput_device_config_tap_get_finger_count(device) > 0) {
BOOL tap = xf86SetBoolOption(pInfo->options,
"Tapping",
@@ -908,17 +1055,17 @@ static int xf86libinput_pre_init(InputDriverPtr drv,
}
}
if (libinput_device_config_buttons_has_left_handed(device)) {
if (libinput_device_config_left_handed_is_available(device)) {
BOOL left_handed = xf86SetBoolOption(pInfo->options,
"LeftHanded",
libinput_device_config_buttons_get_left_handed(device));
if (libinput_device_config_buttons_set_left_handed(device,
left_handed) !=
libinput_device_config_left_handed_get(device));
if (libinput_device_config_left_handed_set(device,
left_handed) !=
LIBINPUT_CONFIG_STATUS_SUCCESS) {
xf86IDrvMsg(pInfo, X_ERROR,
"Failed to set LeftHanded to %d\n",
left_handed);
left_handed = libinput_device_config_buttons_get_left_handed(device);
left_handed = libinput_device_config_left_handed_get(device);
}
driver_data->options.left_handed = left_handed;
}
@@ -970,6 +1117,84 @@ static int xf86libinput_pre_init(InputDriverPtr drv,
driver_data->options.scroll_button = scroll_button;
}
}
static int xf86libinput_pre_init(InputDriverPtr drv,
InputInfoPtr pInfo,
int flags)
{
struct xf86libinput *driver_data = NULL;
struct libinput *libinput = NULL;
struct libinput_device *device;
char *path;
pInfo->type_name = 0;
pInfo->device_control = xf86libinput_device_control;
pInfo->read_input = xf86libinput_read_input;
pInfo->control_proc = NULL;
pInfo->switch_mode = NULL;
driver_data = calloc(1, sizeof(*driver_data));
if (!driver_data)
goto fail;
driver_data->valuators = valuator_mask_new(2);
if (!driver_data->valuators)
goto fail;
driver_data->scroll_vdist = 1;
driver_data->scroll_hdist = 1;
path = xf86SetStrOption(pInfo->options, "Device", NULL);
if (!path)
goto fail;
if (!driver_context.libinput) {
driver_context.libinput = libinput_path_create_context(&interface, &driver_context);
libinput_log_set_handler(driver_context.libinput,
xf86libinput_log_handler);
/* we want all msgs, let the server filter */
libinput_log_set_priority(driver_context.libinput,
LIBINPUT_LOG_PRIORITY_DEBUG);
xorg_list_init(&driver_context.server_fds);
} else {
libinput_ref(driver_context.libinput);
}
libinput = driver_context.libinput;
if (libinput == NULL) {
xf86IDrvMsg(pInfo, X_ERROR, "Creating a device for %s failed\n", path);
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);
goto fail;
}
/* We ref the device but remove it afterwards. The hope is that
between now and DEVICE_INIT/DEVICE_ON, the device doesn't change.
*/
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;
driver_data->device = device;
/* Disable acceleration in the server, libinput does it for us */
pInfo->options = xf86ReplaceIntOption(pInfo->options, "AccelerationProfile", -1);
pInfo->options = xf86ReplaceStrOption(pInfo->options, "AccelerationScheme", "none");
xf86libinput_parse_options(pInfo, driver_data, device);
/* now pick an actual type */
if (libinput_device_config_tap_get_finger_count(device) > 0)
pInfo->type_name = XI_TOUCHPAD;
@@ -984,6 +1209,8 @@ static int 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);
free(path);
@@ -1012,6 +1239,11 @@ InputDriverRec xf86libinput_driver = {
.driverName = "libinput",
.PreInit = xf86libinput_pre_init,
.UnInit = xf86libinput_uninit,
.module = NULL,
.default_options= NULL,
#ifdef XI86_DRV_CAP_SERVER_FD
.capabilities = XI86_DRV_CAP_SERVER_FD
#endif
};
static XF86ModuleVersionInfo xf86libinput_version_info = {
@@ -1050,13 +1282,20 @@ _X_EXPORT XF86ModuleData libinputModuleData = {
#define PROP_ACCEL "libinput Accel Speed"
/* Natural scrolling: BOOL, 1 value */
#define PROP_NATURAL_SCROLL "libinput Natural Scrolling Enabled"
/* Send-events mode: 32-bit int, 1 value */
#define PROP_SENDEVENTS "libinput Send Events Mode"
/* Send-events mode: BOOL read-only, 2 values in order disabled,
disabled-on-external-mouse */
#define PROP_SENDEVENTS_AVAILABLE "libinput Send Events Modes Available"
/* Send-events mode: BOOL, 2 values in order disabled,
disabled-on-external-mouse */
#define PROP_SENDEVENTS_ENABLED "libinput Send Events Mode Enabled"
/* Left-handed enabled/disabled: BOOL, 1 value */
#define PROP_LEFT_HANDED "libinput Left Handed Enabled"
/* Scroll method: BOOL read-only, 3 values in order 2fg, edge, button.
shows available scroll methods */
#define PROP_SCROLL_METHODS_AVAILABLE "libinput Scroll Methods Available"
/* Scroll method: BOOL, 3 values in order 2fg, edge, button
only one is enabled at a time at max */
#define PROP_SCROLL_METHODS "libinput Scroll Methods"
#define PROP_SCROLL_METHOD_ENABLED "libinput Scroll Method Enabled"
/* Scroll button for button scrolling: 32-bit int, 1 value */
#define PROP_SCROLL_BUTTON "libinput Button Scrolling Button"
@@ -1065,9 +1304,11 @@ static Atom prop_tap;
static Atom prop_calibration;
static Atom prop_accel;
static Atom prop_natural_scroll;
static Atom prop_sendevents;
static Atom prop_sendevents_available;
static Atom prop_sendevents_enabled;
static Atom prop_left_handed;
static Atom prop_scroll_methods;
static Atom prop_scroll_methods_available;
static Atom prop_scroll_method_enabled;
static Atom prop_scroll_button;
/* general properties */
@@ -1203,25 +1444,28 @@ LibinputSetPropertySendEvents(DeviceIntPtr dev,
InputInfoPtr pInfo = dev->public.devicePrivate;
struct xf86libinput *driver_data = pInfo->private;
struct libinput_device *device = driver_data->device;
CARD32* data;
BOOL* data;
uint32_t modes = 0;
if (val->format != 32 || val->size != 1 || val->type != XA_CARDINAL)
if (val->format != 8 || val->size != 2 || val->type != XA_INTEGER)
return BadMatch;
data = (CARD32*)val->data;
data = (BOOL*)val->data;
if (data[0])
modes |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
if (data[1])
modes |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
if (checkonly) {
uint32_t supported = libinput_device_config_send_events_get_modes(device);
uint32_t new_mode = *data;
uint32_t supported =
libinput_device_config_send_events_get_modes(device);
if ((new_mode | supported) != supported)
if ((modes | supported) != supported)
return BadValue;
/* Only one bit must be set */
if (new_mode && ((new_mode & (new_mode - 1)) != 0))
return BadValue;
} else {
driver_data->options.sendevents = *data;
driver_data->options.sendevents = modes;
}
return Success;
@@ -1244,7 +1488,7 @@ LibinputSetPropertyLeftHanded(DeviceIntPtr dev,
data = (BOOL*)val->data;
if (checkonly) {
int supported = libinput_device_config_buttons_has_left_handed(device);
int supported = libinput_device_config_left_handed_is_available(device);
int left_handed = *data;
if (!supported && left_handed)
@@ -1286,7 +1530,7 @@ LibinputSetPropertyScrollMethods(DeviceIntPtr dev,
if (__builtin_popcount(modes) > 1)
return BadValue;
if ((modes & supported) == 0)
if (modes && (modes & supported) == 0)
return BadValue;
} else {
driver_data->options.scroll_method = modes;
@@ -1340,11 +1584,15 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
rc = LibinputSetPropertyAccel(dev, atom, val, checkonly);
else if (atom == prop_natural_scroll)
rc = LibinputSetPropertyNaturalScroll(dev, atom, val, checkonly);
else if (atom == prop_sendevents)
else if (atom == prop_sendevents_available)
return BadAccess; /* read-only */
else if (atom == prop_sendevents_enabled)
rc = LibinputSetPropertySendEvents(dev, atom, val, checkonly);
else if (atom == prop_left_handed)
rc = LibinputSetPropertyLeftHanded(dev, atom, val, checkonly);
else if (atom == prop_scroll_methods)
else if (atom == prop_scroll_methods_available)
return BadAccess; /* read-only */
else if (atom == prop_scroll_method_enabled)
rc = LibinputSetPropertyScrollMethods(dev, atom, val, checkonly);
else if (atom == prop_scroll_button)
rc = LibinputSetPropertyScrollButton(dev, atom, val, checkonly);
@@ -1368,6 +1616,7 @@ LibinputInitProperty(DeviceIntPtr dev)
const char *device_node;
CARD32 product[2];
uint32_t scroll_methods;
uint32_t sendevent_modes;
int rc;
prop_float = XIGetKnownProperty("FLOAT");
@@ -1428,23 +1677,51 @@ LibinputInitProperty(DeviceIntPtr dev)
XISetDevicePropertyDeletable(dev, prop_natural_scroll, FALSE);
}
if (libinput_device_config_send_events_get_modes(device) !=
LIBINPUT_CONFIG_SEND_EVENTS_ENABLED) {
uint32_t sendevents = driver_data->options.sendevents;
sendevent_modes = libinput_device_config_send_events_get_modes(device);
if (sendevent_modes != LIBINPUT_CONFIG_SEND_EVENTS_ENABLED) {
uint32_t sendevents;
BOOL modes[2] = {FALSE};
prop_sendevents = MakeAtom(PROP_SENDEVENTS,
strlen(PROP_SENDEVENTS),
TRUE);
rc = XIChangeDeviceProperty(dev, prop_sendevents,
XA_CARDINAL, 32,
PropModeReplace, 1, &sendevents, FALSE);
if (sendevent_modes & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED)
modes[0] = TRUE;
if (sendevent_modes & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
modes[1] = TRUE;
prop_sendevents_available = MakeAtom(PROP_SENDEVENTS_AVAILABLE,
strlen(PROP_SENDEVENTS_AVAILABLE),
TRUE);
rc = XIChangeDeviceProperty(dev, prop_sendevents_available,
XA_INTEGER, 8,
PropModeReplace, 2, modes, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_sendevents, FALSE);
XISetDevicePropertyDeletable(dev, prop_sendevents_available, FALSE);
memset(modes, 0, sizeof(modes));
sendevents = driver_data->options.sendevents;
switch(sendevents) {
case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
modes[0] = TRUE;
break;
case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
modes[1] = TRUE;
break;
}
prop_sendevents_enabled = MakeAtom(PROP_SENDEVENTS_ENABLED,
strlen(PROP_SENDEVENTS_ENABLED),
TRUE);
rc = XIChangeDeviceProperty(dev, prop_sendevents_enabled,
XA_INTEGER, 8,
PropModeReplace, 2, modes, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_sendevents_enabled, FALSE);
}
if (libinput_device_config_buttons_has_left_handed(device)) {
if (libinput_device_config_left_handed_is_available(device)) {
BOOL left_handed = driver_data->options.left_handed;
prop_left_handed = MakeAtom(PROP_LEFT_HANDED,
@@ -1463,6 +1740,31 @@ LibinputInitProperty(DeviceIntPtr dev)
enum libinput_config_scroll_method method;
BOOL methods[3] = {FALSE};
if (scroll_methods & LIBINPUT_CONFIG_SCROLL_2FG)
methods[0] = TRUE;
if (scroll_methods & LIBINPUT_CONFIG_SCROLL_EDGE)
methods[1] = TRUE;
if (scroll_methods & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN)
methods[2] = TRUE;
prop_scroll_methods_available =
MakeAtom(PROP_SCROLL_METHODS_AVAILABLE,
strlen(PROP_SCROLL_METHODS_AVAILABLE),
TRUE);
rc = XIChangeDeviceProperty(dev,
prop_scroll_methods_available,
XA_INTEGER, 8,
PropModeReplace,
ARRAY_SIZE(methods),
&methods, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev,
prop_scroll_methods_available,
FALSE);
memset(methods, 0, sizeof(methods));
method = libinput_device_config_scroll_get_method(device);
switch(method) {
case LIBINPUT_CONFIG_SCROLL_2FG:
@@ -1478,18 +1780,22 @@ LibinputInitProperty(DeviceIntPtr dev)
break;
}
prop_scroll_methods = MakeAtom(PROP_SCROLL_METHODS,
strlen(PROP_SCROLL_METHODS),
TRUE);
prop_scroll_method_enabled =
MakeAtom(PROP_SCROLL_METHOD_ENABLED,
strlen(PROP_SCROLL_METHOD_ENABLED),
TRUE);
rc = XIChangeDeviceProperty(dev,
prop_scroll_methods,
prop_scroll_method_enabled,
XA_INTEGER, 8,
PropModeReplace,
ARRAY_SIZE(methods),
&methods, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_scroll_methods, FALSE);
XISetDevicePropertyDeletable(dev,
prop_scroll_method_enabled,
FALSE);
}
if (libinput_device_config_scroll_get_methods(device) &