Compare commits

..

19 Commits

Author SHA1 Message Date
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
Peter Hutterer
7b2dbdc224 xf86-input-libinput 0.3.0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-11-24 17:43:23 +10:00
Peter Hutterer
eddc8cb1b2 Don't process events from devices that got removed already
If the driver doesn't have a pInfo reference anymore for a libinput device,
don't bother processing events, the device was already removed. This was
triggered by the libevdev test suite which adds/removes devices very quickly.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-11-24 11:50:48 +10:00
Peter Hutterer
95597d8070 Drop double empty lines
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-11-24 11:50:48 +10:00
Peter Hutterer
a323e221a7 Use the button conversion helper for normal button events too
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-11-24 11:01:25 +10:00
Peter Hutterer
6385974e4d Add support for changing the button-scrolling button
This currently exposes the libinput button name, which isn't ideal. Needs to
be switched to X button numbers.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-11-24 11:01:25 +10:00
Peter Hutterer
439a244ae7 Add support for switching scroll methods
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-11-24 11:00:44 +10:00
Peter Hutterer
4a049ad6f8 Add support for left-handed button orientation
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-11-24 10:50:24 +10:00
3 changed files with 607 additions and 118 deletions

View File

@@ -23,7 +23,7 @@
# Initialize Autoconf
AC_PREREQ([2.60])
AC_INIT([xf86-input-libinput],
[0.2.0],
[0.4.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.7.0])
# Define a configure option for an alternate input module directory
AC_ARG_WITH(xorg-module-dir,

View File

@@ -48,14 +48,34 @@ 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).
.TP 7
.BI "Option \*qLeftHanded\*q \*q" bool \*q
Enables left-handed button orientation, i.e. swapping left and right buttons.
.TP 7
.BI "Option \*qNaturalScrolling\*q \*q" bool \*q
Enables or disables natural scrolling behavior.
.TP 7
.BI "Option \*qScrollButton\*q \*q" int \*q
Designates a button as scroll button. If the
.BI ScrollMethod
is
.BI button
and the button is logically held down, x/y axis movement is converted into
scroll events.
.TP 7
.BI "Option \*qScrollMethod\*q \*q" string \*q
Enables a scroll method. Permitted values are
.BI none,
.BI twofinger,
.BI edge,
.BI button.
Not all devices support all options, if an option is unsupported, the
default scroll option for this device is used.
.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".

View File

@@ -86,12 +86,50 @@ struct xf86libinput {
struct {
BOOL tapping;
BOOL natural_scrolling;
BOOL left_handed;
CARD32 sendevents;
CARD32 scroll_button; /* xorg button number */
float speed;
float matrix[9];
enum libinput_config_scroll_method scroll_method;
} options;
};
static inline unsigned int
btn_linux2xorg(unsigned int b)
{
unsigned int button;
switch(b) {
case 0: button = 0; break;
case BTN_LEFT: button = 1; break;
case BTN_MIDDLE: button = 2; break;
case BTN_RIGHT: button = 3; break;
default:
button = 8 + b - BTN_SIDE;
break;
}
return button;
}
static inline unsigned int
btn_xorg2linux(unsigned int b)
{
unsigned int button;
switch(b) {
case 0: button = 0; break;
case 1: button = BTN_LEFT; break;
case 2: button = BTN_MIDDLE; break;
case 3: button = BTN_RIGHT; break;
default:
button = b - 8 + BTN_SIDE;
break;
}
return button;
}
static int
LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
BOOL checkonly);
@@ -104,6 +142,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,
@@ -143,6 +182,36 @@ LibinputApplyConfig(DeviceIntPtr dev)
driver_data->options.matrix[4], driver_data->options.matrix[5],
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)
xf86IDrvMsg(pInfo, X_ERROR,
"Failed to set LeftHanded to %d\n",
driver_data->options.left_handed);
if (libinput_device_config_scroll_set_method(device,
driver_data->options.scroll_method) != LIBINPUT_CONFIG_STATUS_SUCCESS) {
const char *method;
switch(driver_data->options.scroll_method) {
case LIBINPUT_CONFIG_SCROLL_NO_SCROLL: method = "none"; break;
case LIBINPUT_CONFIG_SCROLL_2FG: method = "twofinger"; break;
case LIBINPUT_CONFIG_SCROLL_EDGE: method = "edge"; break;
case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN: method = "button"; break;
default:
method = "unknown"; break;
}
xf86IDrvMsg(pInfo, X_ERROR,
"Failed to set scroll to %s\n",
method);
}
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);
}
static int
@@ -199,7 +268,6 @@ xf86libinput_ptr_ctl(DeviceIntPtr dev, PtrCtrl *ctl)
{
}
static void
init_button_map(unsigned char *btnmap, size_t size)
{
@@ -263,7 +331,6 @@ xf86libinput_init_pointer(InputInfoPtr pInfo)
init_button_labels(btnlabels, ARRAY_SIZE(btnlabels));
init_axis_labels(axislabels, ARRAY_SIZE(axislabels));
InitPointerDeviceStruct((DevicePtr)dev, btnmap,
nbuttons,
btnlabels,
@@ -288,6 +355,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)
{
@@ -321,16 +435,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
@@ -379,8 +507,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);
@@ -440,6 +572,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)
{
@@ -447,13 +597,7 @@ xf86libinput_handle_button(InputInfoPtr pInfo, struct libinput_event_pointer *ev
int button;
int is_press;
switch(libinput_event_pointer_get_button(event)) {
case BTN_LEFT: button = 1; break;
case BTN_MIDDLE: button = 2; break;
case BTN_RIGHT: button = 3; break;
default: /* no touchpad actually has those buttons */
return;
}
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);
}
@@ -508,8 +652,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);
@@ -550,7 +694,7 @@ xf86libinput_handle_event(struct libinput_event *event)
device = libinput_event_get_device(event);
pInfo = libinput_device_get_user_data(device);
if (pInfo && !pInfo->dev->public.on)
if (!pInfo || !pInfo->dev->public.on)
return;
switch (libinput_event_get_type(event)) {
@@ -559,7 +703,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:
@@ -591,7 +736,6 @@ xf86libinput_handle_event(struct libinput_event *event)
}
}
static void
xf86libinput_read_input(InputInfoPtr pInfo)
{
@@ -604,7 +748,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;
}
@@ -671,75 +817,12 @@ 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;
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");
uint32_t scroll_methods;
if (libinput_device_config_tap_get_finger_count(device) > 0) {
BOOL tap = xf86SetBoolOption(pInfo->options,
@@ -848,6 +931,142 @@ static int xf86libinput_pre_init(InputDriverPtr drv,
}
}
if (libinput_device_config_buttons_has_left_handed(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_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);
}
driver_data->options.left_handed = left_handed;
}
scroll_methods = libinput_device_config_scroll_get_methods(device);
if (scroll_methods != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) {
enum libinput_config_scroll_method m;
char *method = xf86SetStrOption(pInfo->options,
"ScrollMethod",
NULL);
if (!method)
m = libinput_device_config_scroll_get_method(device);
else if (strncasecmp(method, "twofinger", 9) == 0)
m = LIBINPUT_CONFIG_SCROLL_2FG;
else if (strncasecmp(method, "edge", 4) == 0)
m = LIBINPUT_CONFIG_SCROLL_EDGE;
else if (strncasecmp(method, "button", 6) == 0)
m = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
else if (strncasecmp(method, "none", 4) == 0)
m = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
else {
xf86IDrvMsg(pInfo, X_ERROR,
"Unknown scroll method '%s'. Using default.\n",
method);
m = libinput_device_config_scroll_get_method(device);
}
driver_data->options.scroll_method = m;
free(method);
}
if (libinput_device_config_scroll_get_methods(device) &
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) {
unsigned int b = btn_linux2xorg(libinput_device_config_scroll_get_button(device));
CARD32 scroll_button = xf86SetIntOption(pInfo->options,
"ScrollButton",
b);
b = btn_xorg2linux(scroll_button);
if (libinput_device_config_scroll_set_button(device,
b) != LIBINPUT_CONFIG_STATUS_SUCCESS) {
xf86IDrvMsg(pInfo, X_ERROR,
"Failed to set ScrollButton to %d\n",
scroll_button);
scroll_button = btn_linux2xorg(libinput_device_config_scroll_get_button(device));
}
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->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");
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;
@@ -918,8 +1137,6 @@ _X_EXPORT XF86ModuleData libinputModuleData = {
.teardown = NULL
};
/* Property support */
/* Tapping enabled/disabled: BOOL, 1 value */
@@ -930,15 +1147,34 @@ _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_METHOD_ENABLED "libinput Scroll Method Enabled"
/* Scroll button for button scrolling: 32-bit int, 1 value */
#define PROP_SCROLL_BUTTON "libinput Button Scrolling Button"
/* libinput-specific properties */
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_available;
static Atom prop_scroll_method_enabled;
static Atom prop_scroll_button;
/* general properties */
static Atom prop_float;
@@ -1069,6 +1305,110 @@ LibinputSetPropertySendEvents(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;
uint32_t modes = 0;
if (val->format != 8 || val->size != 2 || val->type != XA_INTEGER)
return BadMatch;
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);
if ((modes | supported) != supported)
return BadValue;
} else {
driver_data->options.sendevents = modes;
}
return Success;
}
static inline int
LibinputSetPropertyLeftHanded(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) {
int supported = libinput_device_config_buttons_has_left_handed(device);
int left_handed = *data;
if (!supported && left_handed)
return BadValue;
} else {
driver_data->options.left_handed = *data;
}
return Success;
}
static inline int
LibinputSetPropertyScrollMethods(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;
uint32_t modes = 0;
if (val->format != 8 || val->size != 3 || val->type != XA_INTEGER)
return BadMatch;
data = (BOOL*)val->data;
if (data[0])
modes |= LIBINPUT_CONFIG_SCROLL_2FG;
if (data[1])
modes |= LIBINPUT_CONFIG_SCROLL_EDGE;
if (data[2])
modes |= LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
if (checkonly) {
uint32_t supported = libinput_device_config_scroll_get_methods(device);
if (__builtin_popcount(modes) > 1)
return BadValue;
if (modes && (modes & supported) == 0)
return BadValue;
} else {
driver_data->options.scroll_method = modes;
}
return Success;
}
static inline int
LibinputSetPropertyScrollButton(DeviceIntPtr dev,
Atom atom,
XIPropertyValuePtr val,
BOOL checkonly)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
struct xf86libinput *driver_data = pInfo->private;
@@ -1081,17 +1421,14 @@ LibinputSetPropertySendEvents(DeviceIntPtr dev,
data = (CARD32*)val->data;
if (checkonly) {
uint32_t supported = libinput_device_config_send_events_get_modes(device);
uint32_t new_mode = *data;
uint32_t button = *data;
uint32_t supported = libinput_device_has_button(device,
btn_xorg2linux(button));
if ((new_mode | supported) != supported)
return BadValue;
/* Only one bit must be set */
if (new_mode && ((new_mode & (new_mode - 1)) != 0))
if (button && !supported)
return BadValue;
} else {
driver_data->options.sendevents = *data;
driver_data->options.scroll_button = *data;
}
return Success;
@@ -1112,8 +1449,18 @@ 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_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);
else if (atom == prop_device || atom == prop_product_id)
return BadAccess; /* read-only */
else
@@ -1133,6 +1480,8 @@ LibinputInitProperty(DeviceIntPtr dev)
struct libinput_device *device = driver_data->device;
const char *device_node;
CARD32 product[2];
uint32_t scroll_methods;
uint32_t sendevent_modes;
int rc;
prop_float = XIGetKnownProperty("FLOAT");
@@ -1193,20 +1542,141 @@ 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)) {
BOOL left_handed = driver_data->options.left_handed;
prop_left_handed = MakeAtom(PROP_LEFT_HANDED,
strlen(PROP_LEFT_HANDED),
TRUE);
rc = XIChangeDeviceProperty(dev, prop_left_handed,
XA_INTEGER, 8,
PropModeReplace, 1, &left_handed, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_left_handed, FALSE);
}
scroll_methods = libinput_device_config_scroll_get_methods(device);
if (scroll_methods != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) {
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:
methods[0] = TRUE;
break;
case LIBINPUT_CONFIG_SCROLL_EDGE:
methods[1] = TRUE;
break;
case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN:
methods[2] = TRUE;
break;
default:
break;
}
prop_scroll_method_enabled =
MakeAtom(PROP_SCROLL_METHOD_ENABLED,
strlen(PROP_SCROLL_METHOD_ENABLED),
TRUE);
rc = XIChangeDeviceProperty(dev,
prop_scroll_method_enabled,
XA_INTEGER, 8,
PropModeReplace,
ARRAY_SIZE(methods),
&methods, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev,
prop_scroll_method_enabled,
FALSE);
}
if (libinput_device_config_scroll_get_methods(device) &
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) {
CARD32 scroll_button = driver_data->options.scroll_button;
prop_scroll_button = MakeAtom(PROP_SCROLL_BUTTON,
strlen(PROP_SCROLL_BUTTON),
TRUE);
rc = XIChangeDeviceProperty(dev, prop_scroll_button,
XA_CARDINAL, 32,
PropModeReplace, 1,
&scroll_button, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_scroll_button, FALSE);
}
/* Device node property, read-only */
@@ -1223,7 +1693,6 @@ LibinputInitProperty(DeviceIntPtr dev)
XISetDevicePropertyDeletable(dev, prop_device, FALSE);
prop_product_id = MakeAtom(XI_PROP_PRODUCT_ID,
strlen(XI_PROP_PRODUCT_ID),
TRUE);