xf86libinput.c 151 KB
Newer Older
1
/*
Peter Hutterer's avatar
Peter Hutterer committed
2
 * Copyright © 2013-2017 Red Hat, Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 *
 * 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 <errno.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <xorg-server.h>
Peter Hutterer's avatar
Peter Hutterer committed
33
#include <list.h>
34
#include <exevents.h>
35
#include <xkbsrv.h>
36
#include <xf86.h>
37
#include <xf86Xinput.h>
38
#include <xf86_OSproc.h>
39 40 41 42
#include <xserver-properties.h>
#include <libinput.h>
#include <linux/input.h>

43 44
#include <X11/Xatom.h>

45
#include "bezier.h"
Peter Hutterer's avatar
Peter Hutterer committed
46
#include "draglock.h"
47 48
#include "libinput-properties.h"

Peter Hutterer's avatar
Peter Hutterer committed
49 50 51 52
#ifndef XI86_SERVER_FD
#define XI86_SERVER_FD 0x20
#endif

53 54 55 56 57 58
#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

59 60 61 62
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 23
#define HAVE_THREADED_INPUT	1
#endif

63
#define TOUCHPAD_NUM_AXES 4 /* x, y, hscroll, vscroll */
64
#define TABLET_NUM_BUTTONS 7 /* we need scroll buttons */
Peter Hutterer's avatar
Peter Hutterer committed
65
#define TOUCH_MAX_SLOTS 15
66 67
#define XORG_KEYCODE_OFFSET 8

68 69 70
#define streq(a, b) (strcmp(a, b) == 0)
#define strneq(a, b, n) (strncmp(a, b, n) == 0)

Peter Hutterer's avatar
Peter Hutterer committed
71 72 73 74 75 76 77
/*
   libinput does not provide axis information for absolute devices, instead
   it scales into the screen dimensions provided. So we set up the axes with
   a fixed range, let libinput scale into that range and then the server
   do the scaling it usually does.
 */
#define TOUCH_AXIS_MAX 0xffff
78 79 80
#define TABLET_AXIS_MAX 0xffffff
#define TABLET_PRESSURE_AXIS_MAX 2047
#define TABLET_TILT_AXIS_MAX 64
Peter Hutterer's avatar
Peter Hutterer committed
81 82
#define TABLET_STRIP_AXIS_MAX 4096
#define TABLET_RING_AXIS_MAX 71
83

84 85 86
#define CAP_KEYBOARD	0x1
#define CAP_POINTER	0x2
#define CAP_TOUCH	0x4
87 88
#define CAP_TABLET	0x8
#define CAP_TABLET_TOOL	0x10
Peter Hutterer's avatar
Peter Hutterer committed
89
#define CAP_TABLET_PAD	0x20
90

Peter Hutterer's avatar
Peter Hutterer committed
91 92
struct xf86libinput_driver {
	struct libinput *libinput;
93
	int device_enabled_count;
94
	void *registered_InputInfoPtr;
Peter Hutterer's avatar
Peter Hutterer committed
95 96 97 98
};

static struct xf86libinput_driver driver_context;

99 100 101 102 103 104 105
struct xf86libinput_device {
	int refcount;
	int enabled_count;
	uint32_t id;
	struct libinput_device *device;
	struct xorg_list device_list;
	int server_fd;
106 107 108 109

	struct xorg_list unclaimed_tablet_tool_list;
};

110 111 112 113 114 115 116 117 118 119
struct xf86libinput_tablet_tool_queued_event {
	struct xorg_list node;
	struct libinput_event_tablet_tool *event;
};

struct xf86libinput_tablet_tool_event_queue {
	bool need_to_queue;
	struct xorg_list event_list;
};

120 121 122
struct xf86libinput_tablet_tool {
	struct xorg_list node;
	struct libinput_tablet_tool *tool;
123 124
};

125 126 127 128 129
struct curve_point {
	struct xorg_list node;
	float x, fx;
} curve_point;

130
struct xf86libinput {
131
	InputInfoPtr pInfo;
132
	char *path;
133
	uint32_t capabilities;
134

135 136 137
	struct {
		int vdist;
		int hdist;
138 139 140

		double vdist_fraction;
		double hdist_fraction;
141
	} scroll;
142 143 144 145 146 147 148

	struct {
		double x;
		double y;
		double x_remainder;
		double y_remainder;
	} scale;
149

150 151
	BOOL has_abs;

152
	ValuatorMask *valuators;
153
	ValuatorMask *valuators_unaccelerated;
154

155
	struct options {
156
		BOOL tapping;
157
		BOOL tap_drag;
158
		BOOL tap_drag_lock;
159
		enum libinput_config_tap_button_map tap_button_map;
160
		BOOL natural_scrolling;
161
		BOOL left_handed;
162
		BOOL middle_emulation;
163
		BOOL disable_while_typing;
164
		CARD32 sendevents;
165
		CARD32 scroll_button; /* xorg button number */
166 167
		float speed;
		float matrix[9];
168
		enum libinput_config_scroll_method scroll_method;
169
		enum libinput_config_click_method click_method;
170
		enum libinput_config_accel_profile accel_profile;
171 172

		unsigned char btnmap[MAX_BUTTONS + 1];
173 174

		BOOL horiz_scrolling_enabled;
175 176

		float rotation_angle;
177
		struct bezier_control_point pressurecurve[4];
178 179 180
		struct ratio {
			int x, y;
		} area;
181 182

		struct xorg_list curve_points;
183
	} options;
Peter Hutterer's avatar
Peter Hutterer committed
184 185

	struct draglock draglock;
186 187 188

	struct xf86libinput_device *shared_device;
	struct xorg_list shared_device_link;
189 190

	struct libinput_tablet_tool *tablet_tool;
191 192

	bool allow_mode_group_updates;
193 194 195 196 197 198 199

	/* Pre-calculated pressure curve.
	   In the 0...TABLET_AXIS_MAX range */
	struct {
		int *values;
		size_t sz;
	} pressurecurve;
200 201 202 203

	struct scale_factor {
		double x, y;
	} area_scale_factor;
204 205
};

206 207 208
enum event_handling {
	EVENT_QUEUED,
	EVENT_HANDLED,
209 210
};

211
static void
212 213 214
xf86libinput_create_subdevice(InputInfoPtr pInfo,
			      uint32_t capabilities,
			      XF86OptionPtr extra_opts);
215 216 217
static inline void
update_mode_prop(InputInfoPtr pInfo,
		 struct libinput_event_tablet_pad *event);
218

219 220 221
static enum event_handling
xf86libinput_handle_event(struct libinput_event *event);

222 223 224 225
static void
xf86libinput_post_tablet_motion(InputInfoPtr pInfo,
				struct libinput_event_tablet_tool *event);

Peter Hutterer's avatar
Peter Hutterer committed
226 227 228 229 230
static inline int
use_server_fd(const InputInfoPtr pInfo) {
	return pInfo->fd > -1 && (pInfo->flags & XI86_SERVER_FD);
}

231 232 233 234 235 236 237 238 239 240
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;
241 242 243
	/* tablet button range */
	case BTN_STYLUS: button = 2; break;
	case BTN_STYLUS2: button = 3; break;
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
	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;
}

269 270 271 272 273 274 275
static BOOL
xf86libinput_is_subdevice(InputInfoPtr pInfo)
{
	char *source;
	BOOL is_subdevice;

	source = xf86SetStrOption(pInfo->options, "_source", "");
276
	is_subdevice = streq(source, "_driver/libinput");
277 278 279 280 281
	free(source);

	return is_subdevice;
}

282 283 284 285 286 287 288 289 290 291 292 293 294 295
static inline InputInfoPtr
xf86libinput_get_parent(InputInfoPtr pInfo)
{
	InputInfoPtr parent;
	int parent_id;

	parent_id = xf86CheckIntOption(pInfo->options, "_libinput/shared-device", -1);
	if (parent_id == -1)
		return NULL;

	nt_list_for_each_entry(parent, xf86FirstLocalDevice(), next) {
		int id = xf86CheckIntOption(parent->options,
					    "_libinput/shared-device",
					    -1);
296
		if (id == parent_id && !xf86libinput_is_subdevice(parent))
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
			return parent;
	}

	return NULL;
}

static inline struct xf86libinput_device*
xf86libinput_shared_create(struct libinput_device *device)
{
	static uint32_t next_shared_device_id;
	struct xf86libinput_device *shared_device;

	shared_device = calloc(1, sizeof(*shared_device));
	if (!shared_device)
		return NULL;

	shared_device->device = device;
	shared_device->refcount = 1;
	shared_device->id = ++next_shared_device_id;
	xorg_list_init(&shared_device->device_list);
317
	xorg_list_init(&shared_device->unclaimed_tablet_tool_list);
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417

	return shared_device;
}

static inline struct xf86libinput_device*
xf86libinput_shared_ref(struct xf86libinput_device *shared_device)
{
	shared_device->refcount++;

	return shared_device;
}

static inline struct xf86libinput_device*
xf86libinput_shared_unref(struct xf86libinput_device *shared_device)
{
	shared_device->refcount--;

	if (shared_device->refcount > 0)
		return shared_device;

	free(shared_device);

	return NULL;
}

static inline struct libinput_device *
xf86libinput_shared_enable(InputInfoPtr pInfo,
			   struct xf86libinput_device *shared_device,
			   const char *path)
{
	struct libinput_device *device;
	struct libinput *libinput = driver_context.libinput;

	/* With systemd-logind the server requests the fd from logind, sets
	 * pInfo->fd and sets the "fd" option to the fd number.
	 *
	 * If we have a second device that uses the same path, the server
	 * checks all pInfo->major/minor for a match and returns the matched
	 * device's pInfo->fd. In this driver, this fd is the epollfd, not
	 * the actual device. This causes troubles when removing the
	 * device.
	 *
	 * What we need to do here is: after enabling the device the first
	 * time extract the real fd and store it in the shared device
	 * struct. The second device replaces the pInfo->options "fd" with
	 * the real fd we're using.
	 *
	 * When the device is unplugged, the server now correctly finds two
	 * devices on the real fd and releases them in order.
	 */
	shared_device->enabled_count++;
	if (shared_device->enabled_count > 1) {
		if (pInfo->flags & XI86_SERVER_FD) {
			pInfo->options = xf86ReplaceIntOption(pInfo->options,
							      "fd",
							      shared_device->server_fd);
		}

		return shared_device->device;
	}

	device = libinput_path_add_device(libinput, path);
	if (!device)
		return NULL;

	libinput_device_set_user_data(device, shared_device);
	shared_device->device = libinput_device_ref(device);

	if (pInfo->flags & XI86_SERVER_FD)
		shared_device->server_fd = xf86CheckIntOption(pInfo->options,
							      "fd",
							      -1);
	return device;
}

static inline void
xf86libinput_shared_disable(struct xf86libinput_device *shared_device)
{
	struct libinput_device *device = shared_device->device;

	shared_device->enabled_count--;

	if (shared_device->enabled_count > 0)
		return;

	if (!device)
		return;

	libinput_device_set_user_data(device, NULL);
	libinput_path_remove_device(device);
	device = libinput_device_unref(device);
	shared_device->device = NULL;
}

static inline bool
xf86libinput_shared_is_enabled(struct xf86libinput_device *shared_device)
{
	return shared_device->enabled_count > 0;
}

418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
static inline bool
xf86libinput_set_pressurecurve(struct xf86libinput *driver_data,
			       const struct bezier_control_point controls[4])
{
	if (memcmp(controls, bezier_defaults, sizeof(bezier_defaults)) == 0) {
		free(driver_data->pressurecurve.values);
		driver_data->pressurecurve.values = NULL;
		return true;
	}

	if (!driver_data->pressurecurve.values) {
		int *vals = calloc(TABLET_PRESSURE_AXIS_MAX + 1, sizeof(int));
		if (!vals)
			return false;

		driver_data->pressurecurve.values = vals;
		driver_data->pressurecurve.sz = TABLET_PRESSURE_AXIS_MAX + 1;
	}

	return cubic_bezier(controls,
			    driver_data->pressurecurve.values,
			    driver_data->pressurecurve.sz);
}

442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
static inline void
xf86libinput_set_area_ratio(struct xf86libinput *driver_data,
			    const struct ratio *ratio)
{
	double f;
	double w, h;

	if (libinput_device_get_size(driver_data->shared_device->device, &w, &h) != 0)
		return;

	driver_data->options.area = *ratio;

	if (ratio->y == 0) {
		driver_data->area_scale_factor.x = 1.0;
		driver_data->area_scale_factor.y = 1.0;
		return;
	}

	f = 1.0 * (ratio->x * h)/(ratio->y * w);

	if (f <= 1.0) {
		driver_data->area_scale_factor.x = 1.0/f;
		driver_data->area_scale_factor.y = 1.0;
	} else {
		driver_data->area_scale_factor.x = 1.0;
		driver_data->area_scale_factor.y = f;
	}
}

471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
/**
 * returns true if the device has one or more of the given capabilities or
 * if the device isn't a subdevice
 */
static inline bool
subdevice_has_capabilities(DeviceIntPtr dev, uint32_t capabilities)
{
	InputInfoPtr pInfo  = dev->public.devicePrivate;
	struct xf86libinput *driver_data = pInfo->private;

	if (!xf86libinput_is_subdevice(pInfo))
		return true;

	return !!(driver_data->capabilities & capabilities);
}

487 488 489 490 491 492
static int
LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
                 BOOL checkonly);
static void
LibinputInitProperty(DeviceIntPtr dev);

493 494 495 496
static void
LibinputApplyConfigSendEvents(DeviceIntPtr dev,
			      struct xf86libinput *driver_data,
			      struct libinput_device *device)
497 498 499 500 501 502 503
{
	InputInfoPtr pInfo = dev->public.devicePrivate;

	if (libinput_device_config_send_events_get_modes(device) != LIBINPUT_CONFIG_SEND_EVENTS_ENABLED &&
	    libinput_device_config_send_events_set_mode(device,
							driver_data->options.sendevents) != LIBINPUT_CONFIG_STATUS_SUCCESS)
		xf86IDrvMsg(pInfo, X_ERROR,
504
			    "Failed to set SendEventsMode %u\n",
505
			    driver_data->options.sendevents);
506 507 508 509 510 511 512 513
}

static void
LibinputApplyConfigNaturalScroll(DeviceIntPtr dev,
				 struct xf86libinput *driver_data,
				 struct libinput_device *device)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
514

515 516 517
	if (!subdevice_has_capabilities(dev, CAP_POINTER))
		return;

518 519 520 521 522 523
	if (libinput_device_config_scroll_has_natural_scroll(device) &&
	    libinput_device_config_scroll_set_natural_scroll_enabled(device,
								     driver_data->options.natural_scrolling) != LIBINPUT_CONFIG_STATUS_SUCCESS)
		xf86IDrvMsg(pInfo, X_ERROR,
			    "Failed to set NaturalScrolling to %d\n",
			    driver_data->options.natural_scrolling);
524 525 526 527 528 529 530 531
}

static void
LibinputApplyConfigAccel(DeviceIntPtr dev,
			 struct xf86libinput *driver_data,
			 struct libinput_device *device)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
532

533 534 535
	if (!subdevice_has_capabilities(dev, CAP_POINTER))
		return;

536 537 538 539 540 541
	if (libinput_device_config_accel_is_available(device) &&
	    libinput_device_config_accel_set_speed(device,
						   driver_data->options.speed) != LIBINPUT_CONFIG_STATUS_SUCCESS)
			xf86IDrvMsg(pInfo, X_ERROR,
				    "Failed to set speed %.2f\n",
				    driver_data->options.speed);
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556

	if (libinput_device_config_accel_get_profiles(device) &&
	    driver_data->options.accel_profile != LIBINPUT_CONFIG_ACCEL_PROFILE_NONE  &&
	    libinput_device_config_accel_set_profile(device,
						     driver_data->options.accel_profile) !=
			    LIBINPUT_CONFIG_STATUS_SUCCESS) {
		const char *profile;

		switch (driver_data->options.accel_profile) {
		case LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE:
			profile = "adaptive";
			break;
		case LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT:
			profile = "flat";
			break;
557 558 559 560 561
#if HAVE_LIBINPUT_CUSTOM_ACCEL_CURVE
		case LIBINPUT_CONFIG_ACCEL_PROFILE_DEVICE_SPEED_CURVE:
			profile = "device-speed-curve";
			break;
#endif
562 563 564 565 566 567
		default:
			profile = "unknown";
			break;
		}
		xf86IDrvMsg(pInfo, X_ERROR, "Failed to set profile %s\n", profile);
	}
568 569 570 571 572 573 574 575
}

static inline void
LibinputApplyConfigTap(DeviceIntPtr dev,
		       struct xf86libinput *driver_data,
		       struct libinput_device *device)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
576

577 578 579
	if (!subdevice_has_capabilities(dev, CAP_POINTER))
		return;

580 581 582 583 584 585 586
	if (libinput_device_config_tap_get_finger_count(device) > 0 &&
	    libinput_device_config_tap_set_enabled(device,
						   driver_data->options.tapping) != LIBINPUT_CONFIG_STATUS_SUCCESS)
		xf86IDrvMsg(pInfo, X_ERROR,
			    "Failed to set Tapping to %d\n",
			    driver_data->options.tapping);

587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
	if (libinput_device_config_tap_get_finger_count(device) > 0 &&
	    libinput_device_config_tap_set_button_map(device,
						      driver_data->options.tap_button_map) != LIBINPUT_CONFIG_STATUS_SUCCESS) {
		const char *map;

		switch(driver_data->options.tap_button_map) {
		case LIBINPUT_CONFIG_TAP_MAP_LRM: map = "lrm"; break;
		case LIBINPUT_CONFIG_TAP_MAP_LMR: map = "lmr"; break;
		default: map = "unknown"; break;
		}
		xf86IDrvMsg(pInfo, X_ERROR,
			    "Failed to set Tapping ButtonMap to %s\n",
			    map);
	}

602 603 604 605 606 607 608
	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);

609 610 611 612 613 614
	if (libinput_device_config_tap_get_finger_count(device) > 0 &&
	    libinput_device_config_tap_set_drag_enabled(device,
							driver_data->options.tap_drag) != LIBINPUT_CONFIG_STATUS_SUCCESS)
		xf86IDrvMsg(pInfo, X_ERROR,
			    "Failed to set Tapping Drag to %d\n",
			    driver_data->options.tap_drag);
615 616 617 618 619 620 621 622
}

static void
LibinputApplyConfigCalibration(DeviceIntPtr dev,
			       struct xf86libinput *driver_data,
			       struct libinput_device *device)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
623

624 625 626
	if (!subdevice_has_capabilities(dev, CAP_TOUCH|CAP_TABLET))
		return;

627 628 629 630 631 632 633 634 635 636 637
	if (libinput_device_config_calibration_has_matrix(device) &&
	    libinput_device_config_calibration_set_matrix(device,
							  driver_data->options.matrix) != LIBINPUT_CONFIG_STATUS_SUCCESS)
		xf86IDrvMsg(pInfo, X_ERROR,
			    "Failed to apply matrix: "
			    "%.2f %.2f %.2f %2.f %.2f %.2f %.2f %.2f %.2f\n",
			    driver_data->options.matrix[0], driver_data->options.matrix[1],
			    driver_data->options.matrix[2], driver_data->options.matrix[3],
			    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]);
638 639 640 641 642 643 644 645
}

static void
LibinputApplyConfigLeftHanded(DeviceIntPtr dev,
			       struct xf86libinput *driver_data,
			       struct libinput_device *device)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
646

647 648 649
	if (!subdevice_has_capabilities(dev, CAP_POINTER|CAP_TABLET))
		return;

650 651
	if (libinput_device_config_left_handed_is_available(device) &&
	    libinput_device_config_left_handed_set(device,
652
						   driver_data->options.left_handed) != LIBINPUT_CONFIG_STATUS_SUCCESS)
653 654 655
		xf86IDrvMsg(pInfo, X_ERROR,
			    "Failed to set LeftHanded to %d\n",
			    driver_data->options.left_handed);
656 657 658 659 660 661 662 663
}

static void
LibinputApplyConfigScrollMethod(DeviceIntPtr dev,
				struct xf86libinput *driver_data,
				struct libinput_device *device)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
664

665 666 667
	if (!subdevice_has_capabilities(dev, CAP_POINTER))
		return;

668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
	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);
	}
685

686
	if (libinput_device_config_scroll_get_methods(device) & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) {
687 688
		unsigned int scroll_button;

689 690 691
		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,
692
				    "Failed to set ScrollButton to %u\n",
693 694
				    driver_data->options.scroll_button);
	}
695 696 697 698 699 700 701 702
}

static void
LibinputApplyConfigClickMethod(DeviceIntPtr dev,
			       struct xf86libinput *driver_data,
			       struct libinput_device *device)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
703

704 705 706
	if (!subdevice_has_capabilities(dev, CAP_POINTER))
		return;

707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
	if (libinput_device_config_click_set_method(device,
						    driver_data->options.click_method) != LIBINPUT_CONFIG_STATUS_SUCCESS) {
		const char *method;

		switch (driver_data->options.click_method) {
		case LIBINPUT_CONFIG_CLICK_METHOD_NONE: method = "none"; break;
		case LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS: method = "buttonareas"; break;
		case LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER: method = "clickfinger"; break;
		default:
			method = "unknown"; break;
		}

		xf86IDrvMsg(pInfo, X_ERROR,
			    "Failed to set click method to %s\n",
			    method);
	}
723 724 725 726 727 728 729 730
}

static void
LibinputApplyConfigMiddleEmulation(DeviceIntPtr dev,
				   struct xf86libinput *driver_data,
				   struct libinput_device *device)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
731

732 733 734
	if (!subdevice_has_capabilities(dev, CAP_POINTER))
		return;

735 736 737 738 739 740
	if (libinput_device_config_middle_emulation_is_available(device) &&
	    libinput_device_config_middle_emulation_set_enabled(device,
								driver_data->options.middle_emulation) != LIBINPUT_CONFIG_STATUS_SUCCESS)
		xf86IDrvMsg(pInfo, X_ERROR,
			    "Failed to set MiddleEmulation to %d\n",
			    driver_data->options.middle_emulation);
741 742 743 744 745 746 747 748
}

static void
LibinputApplyConfigDisableWhileTyping(DeviceIntPtr dev,
				      struct xf86libinput *driver_data,
				      struct libinput_device *device)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
749

750 751 752
	if (!subdevice_has_capabilities(dev, CAP_POINTER))
		return;

753 754 755 756 757 758
	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);
759 760 761 762 763 764 765 766
}

static void
LibinputApplyConfigRotation(DeviceIntPtr dev,
			    struct xf86libinput *driver_data,
			    struct libinput_device *device)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
767

768 769 770
	if (!subdevice_has_capabilities(dev, CAP_POINTER))
		return;

771 772 773 774 775
	if (libinput_device_config_rotation_is_available(device) &&
	    libinput_device_config_rotation_set_angle(device, driver_data->options.rotation_angle) != LIBINPUT_CONFIG_STATUS_SUCCESS)
		xf86IDrvMsg(pInfo, X_ERROR,
			    "Failed to set RotationAngle to %.2f\n",
			    driver_data->options.rotation_angle);
776 777
}

778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801
static void
LibinputApplyConfigAccelCurvePoints(DeviceIntPtr dev,
				    struct xf86libinput *driver_data,
				    struct libinput_device *device)
{
#if HAVE_LIBINPUT_CUSTOM_ACCEL_CURVE
	struct curve_point *p;

	if (!subdevice_has_capabilities(dev, CAP_POINTER))
		return;

	if (!libinput_device_config_accel_is_available(device))
		return;

	if (libinput_device_config_accel_get_profile(device) !=
	    LIBINPUT_CONFIG_ACCEL_PROFILE_DEVICE_SPEED_CURVE)
		return;

	xorg_list_for_each_entry(p, &driver_data->options.curve_points, node) {
		libinput_device_config_accel_set_curve_point(device, p->x, p->fx);
	}
#endif
}

802 803 804 805 806 807
static inline void
LibinputApplyConfig(DeviceIntPtr dev)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
	struct xf86libinput *driver_data = pInfo->private;
	struct libinput_device *device = driver_data->shared_device->device;
808

809 810 811 812 813 814 815 816 817 818 819
	LibinputApplyConfigSendEvents(dev, driver_data, device);
	LibinputApplyConfigNaturalScroll(dev, driver_data, device);
	LibinputApplyConfigAccel(dev, driver_data, device);
	LibinputApplyConfigTap(dev, driver_data, device);
	LibinputApplyConfigCalibration(dev, driver_data, device);
	LibinputApplyConfigLeftHanded(dev, driver_data, device);
	LibinputApplyConfigScrollMethod(dev, driver_data, device);
	LibinputApplyConfigClickMethod(dev, driver_data, device);
	LibinputApplyConfigMiddleEmulation(dev, driver_data, device);
	LibinputApplyConfigDisableWhileTyping(dev, driver_data, device);
	LibinputApplyConfigRotation(dev, driver_data, device);
820
	LibinputApplyConfigAccelCurvePoints(dev, driver_data, device);
821 822
}

823 824 825 826 827
static int
xf86libinput_on(DeviceIntPtr dev)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
	struct xf86libinput *driver_data = pInfo->private;
828
	struct xf86libinput_device *shared_device = driver_data->shared_device;
Peter Hutterer's avatar
Peter Hutterer committed
829
	struct libinput *libinput = driver_context.libinput;
830
	struct libinput_device *device;
831

832 833 834
	device = xf86libinput_shared_enable(pInfo,
					    shared_device,
					    driver_data->path);
Peter Hutterer's avatar
Peter Hutterer committed
835
	if (!device)
836
		return !Success;
Peter Hutterer's avatar
Peter Hutterer committed
837 838 839 840 841

	/* 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 */
842
	pInfo->fd = libinput_get_fd(libinput);
843 844

	if (driver_context.device_enabled_count == 0) {
845 846
#if HAVE_THREADED_INPUT
		xf86AddEnabledDevice(pInfo);
847
		driver_context.registered_InputInfoPtr = pInfo;
848
#else
849 850
		/* Can't use xf86AddEnabledDevice on an epollfd */
		AddEnabledDevice(pInfo->fd);
851
#endif
852 853 854
	}

	driver_context.device_enabled_count++;
855 856
	dev->public.on = TRUE;

857 858
	LibinputApplyConfig(dev);

859 860 861 862 863 864 865 866
	return Success;
}

static int
xf86libinput_off(DeviceIntPtr dev)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
	struct xf86libinput *driver_data = pInfo->private;
867
	struct xf86libinput_device *shared_device = driver_data->shared_device;
868

869
	if (--driver_context.device_enabled_count == 0) {
870 871 872
#if HAVE_THREADED_INPUT
		xf86RemoveEnabledDevice(pInfo);
#else
873
		RemoveEnabledDevice(pInfo->fd);
874
#endif
875 876
	}

Peter Hutterer's avatar
Peter Hutterer committed
877 878 879 880 881 882
	if (use_server_fd(pInfo)) {
		pInfo->fd = xf86SetIntOption(pInfo->options, "fd", -1);
	} else {
		pInfo->fd = -1;
	}

883
	dev->public.on = FALSE;
Peter Hutterer's avatar
Peter Hutterer committed
884

885
	xf86libinput_shared_disable(shared_device);
Peter Hutterer's avatar
Peter Hutterer committed
886

887 888 889 890 891 892 893 894 895 896 897 898 899 900
	return Success;
}

static void
xf86libinput_ptr_ctl(DeviceIntPtr dev, PtrCtrl *ctl)
{
}

static void
init_button_map(unsigned char *btnmap, size_t size)
{
	int i;

	memset(btnmap, 0, size);
901
	for (i = 0; i < size; i++)
902 903 904 905 906 907
		btnmap[i] = i;
}

static void
init_button_labels(Atom *labels, size_t size)
{
908 909
	assert(size > 10);

910 911 912 913 914 915 916 917
	memset(labels, 0, size * sizeof(Atom));
	labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
	labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
	labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
	labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
	labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
	labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
	labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
918 919
	labels[7] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_SIDE);
	labels[8] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_EXTRA);
920 921
	labels[9] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_FORWARD);
	labels[10] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_BACK);
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938
}

static void
init_axis_labels(Atom *labels, size_t size)
{
	memset(labels, 0, size * sizeof(Atom));
	labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
	labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
	labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
	labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
}

static int
xf86libinput_init_pointer(InputInfoPtr pInfo)
{
	DeviceIntPtr dev= pInfo->dev;
	struct xf86libinput *driver_data = pInfo->private;
939
	struct libinput_device *device = driver_data->shared_device->device;
940
	int min, max, res;
941
	int nbuttons = 7;
942
	int i;
943

944
	Atom btnlabels[MAX_BUTTONS];
945 946
	Atom axislabels[TOUCHPAD_NUM_AXES];

947
	for (i = BTN_JOYSTICK - 1; i >= BTN_SIDE; i--) {
948
		if (libinput_device_pointer_has_button(device, i)) {
949 950 951 952 953
			nbuttons += i - BTN_SIDE + 1;
			break;
		}
	}

954 955 956
	init_button_labels(btnlabels, ARRAY_SIZE(btnlabels));
	init_axis_labels(axislabels, ARRAY_SIZE(axislabels));

957 958
	InitPointerDeviceStruct((DevicePtr)dev,
				driver_data->options.btnmap,
959
				nbuttons,
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975
				btnlabels,
				xf86libinput_ptr_ctl,
				GetMotionHistorySize(),
				TOUCHPAD_NUM_AXES,
				axislabels);
	min = -1;
	max = -1;
	res = 0;

	xf86InitValuatorAxisStruct(dev, 0,
			           XIGetKnownProperty(AXIS_LABEL_PROP_REL_X),
				   min, max, res * 1000, 0, res * 1000, Relative);
	xf86InitValuatorAxisStruct(dev, 1,
			           XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y),
				   min, max, res * 1000, 0, res * 1000, Relative);

976 977
	SetScrollValuator(dev, 2, SCROLL_TYPE_HORIZONTAL, driver_data->scroll.hdist, 0);
	SetScrollValuator(dev, 3, SCROLL_TYPE_VERTICAL, driver_data->scroll.vdist, 0);
978 979 980 981

	return Success;
}

982 983 984 985 986
static int
xf86libinput_init_pointer_absolute(InputInfoPtr pInfo)
{
	DeviceIntPtr dev= pInfo->dev;
	struct xf86libinput *driver_data = pInfo->private;
987
	struct libinput_device *device = driver_data->shared_device->device;
988 989 990 991 992 993 994 995
	int min, max, res;
	int nbuttons = 7;
	int i;

	Atom btnlabels[MAX_BUTTONS];
	Atom axislabels[TOUCHPAD_NUM_AXES];

	for (i = BTN_BACK; i >= BTN_SIDE; i--) {
996
		if (libinput_device_pointer_has_button(device, i)) {
997 998 999 1000 1001 1002 1003 1004
			nbuttons += i - BTN_SIDE + 1;
			break;
		}
	}

	init_button_labels(btnlabels, ARRAY_SIZE(btnlabels));
	init_axis_labels(axislabels, ARRAY_SIZE(axislabels));

1005 1006
	InitPointerDeviceStruct((DevicePtr)dev,
				driver_data->options.btnmap,
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
				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);

1024 1025
	SetScrollValuator(dev, 2, SCROLL_TYPE_HORIZONTAL, driver_data->scroll.hdist, 0);
	SetScrollValuator(dev, 3, SCROLL_TYPE_VERTICAL, driver_data->scroll.vdist, 0);
1026

1027 1028
	driver_data->has_abs = TRUE;

1029 1030
	return Success;
}
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
static void
xf86libinput_kbd_ctrl(DeviceIntPtr device, KeybdCtrl *ctrl)
{
#define CAPSFLAG	1
#define NUMFLAG		2
#define SCROLLFLAG	4

    static struct { int xbit, code; } bits[] = {
        { CAPSFLAG,	LIBINPUT_LED_CAPS_LOCK },
        { NUMFLAG,	LIBINPUT_LED_NUM_LOCK },
        { SCROLLFLAG,	LIBINPUT_LED_SCROLL_LOCK },
	{ 0, 0 },
    };
    int i = 0;
    enum libinput_led leds = 0;
    InputInfoPtr pInfo = device->public.devicePrivate;
    struct xf86libinput *driver_data = pInfo->private;
1048
    struct libinput_device *ldevice = driver_data->shared_device->device;
1049

1050 1051 1052
    if (!device->enabled)
	    return;

1053
    while (bits[i].xbit) {
1054 1055
	    if (ctrl->leds & bits[i].xbit)
		    leds |= bits[i].code;
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
	    i++;
    }

    libinput_device_led_update(ldevice, leds);
}

static void
xf86libinput_init_keyboard(InputInfoPtr pInfo)
{
	DeviceIntPtr dev= pInfo->dev;
1066
	XkbRMLVOSet rmlvo = {0};
1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
	XkbRMLVOSet defaults = {0};

	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);
1086 1087

	InitKeyboardDeviceStruct(dev, &rmlvo, NULL,
1088
				 xf86libinput_kbd_ctrl);
1089
	XkbFreeRMLVOSet(&rmlvo, FALSE);
1090
	XkbFreeRMLVOSet(&defaults, FALSE);
1091 1092
}

Peter Hutterer's avatar
Peter Hutterer committed
1093 1094 1095 1096
static void
xf86libinput_init_touch(InputInfoPtr pInfo)
{
	DeviceIntPtr dev = pInfo->dev;
1097
	struct xf86libinput *driver_data = pInfo->private;
Peter Hutterer's avatar
Peter Hutterer committed
1098
	int min, max, res;
1099 1100
	unsigned char btnmap[MAX_BUTTONS + 1];
	Atom btnlabels[MAX_BUTTONS];
Peter Hutterer's avatar
Peter Hutterer committed
1101
	Atom axislabels[TOUCHPAD_NUM_AXES];
1102
	int nbuttons = 7;
Peter Hutterer's avatar
Peter Hutterer committed
1103 1104 1105 1106 1107

	init_button_map(btnmap, ARRAY_SIZE(btnmap));
	init_button_labels(btnlabels, ARRAY_SIZE(btnlabels));
	init_axis_labels(axislabels, ARRAY_SIZE(axislabels));

1108 1109
	InitPointerDeviceStruct((DevicePtr)dev,
				driver_data->options.btnmap,
1110
				nbuttons,
Peter Hutterer's avatar
Peter Hutterer committed
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
				btnlabels,
				xf86libinput_ptr_ctl,
				GetMotionHistorySize(),
				TOUCHPAD_NUM_AXES,
				axislabels);
	min = 0;
	max = TOUCH_AXIS_MAX;
	res = 0;

	xf86InitValuatorAxisStruct(dev, 0,
1121
			           XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_X),
Peter Hutterer's avatar
Peter Hutterer committed
1122 1123
				   min, max, res * 1000, 0, res * 1000, Absolute);
	xf86InitValuatorAxisStruct(dev, 1,
1124
			           XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_Y),
Peter Hutterer's avatar
Peter Hutterer committed
1125 1126 1127 1128 1129
				   min, max, res * 1000, 0, res * 1000, Absolute);
	InitTouchClassDeviceStruct(dev, TOUCH_MAX_SLOTS, XIDirectTouch, 2);

}

1130
static int
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
xf86libinput_init_tablet_pen_or_eraser(InputInfoPtr pInfo,
				       struct libinput_tablet_tool *tool)
{
	DeviceIntPtr dev = pInfo->dev;
	int min, max, res;
	int axis;

	min = 0;
	max = TABLET_PRESSURE_AXIS_MAX;
	res = 0;
	axis = 2;
	if (libinput_tablet_tool_has_pressure(tool))
		xf86InitValuatorAxisStruct(dev, axis++,
					   XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE),
					   min, max, res * 1000, 0, res * 1000, Absolute);
	max = TABLET_TILT_AXIS_MAX;
	min = -TABLET_TILT_AXIS_MAX;
	if (libinput_tablet_tool_has_tilt(tool)) {
		xf86InitValuatorAxisStruct(dev, axis++,
					   XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X),
					   min, max, res * 1000, 0, res * 1000, Absolute);
		xf86InitValuatorAxisStruct(dev, axis++,
					   XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y),
					   min, max, res * 1000, 0, res * 1000, Absolute);
	}
1156

1157 1158 1159 1160 1161 1162
	min = -TABLET_AXIS_MAX;
	max = TABLET_AXIS_MAX;
	if (libinput_tablet_tool_has_rotation(tool))
		xf86InitValuatorAxisStruct(dev, axis++,
					   XIGetKnownProperty(AXIS_LABEL_PROP_ABS_RZ),
					   min, max, res * 1000, 0, res * 1000, Absolute);
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
	return axis;
}

static void
xf86libinput_init_tablet_airbrush(InputInfoPtr pInfo,
				  struct libinput_tablet_tool *tool)
{
	DeviceIntPtr dev = pInfo->dev;
	int min, max, res;
	int axis;

	/* first axes are shared */
	axis = xf86libinput_init_tablet_pen_or_eraser(pInfo, tool);
	if (axis < 5) {
		xf86IDrvMsg(pInfo, X_ERROR, "Airbrush tool has missing pressure or tilt axes\n");
		return;
	}

	if (!libinput_tablet_tool_has_slider(tool)) {
		xf86IDrvMsg(pInfo, X_ERROR, "Airbrush tool is missing the slider axis\n");
		return;
	}

	min = -TABLET_AXIS_MAX;
	max = TABLET_AXIS_MAX;
	res = 0;

	xf86InitValuatorAxisStruct(dev, axis,
				   XIGetKnownProperty(AXIS_LABEL_PROP_ABS_THROTTLE),
				   min, max, res * 1000, 0, res * 1000, Absolute);
1193 1194
}

1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
static void
xf86libinput_init_tablet_mouse(InputInfoPtr pInfo,
			       struct libinput_tablet_tool *tool)
{
	DeviceIntPtr dev = pInfo->dev;
	int min, max, res;
	int axis;

	if (!libinput_tablet_tool_has_rotation(tool)) {
		xf86IDrvMsg(pInfo, X_ERROR, "Mouse tool is missing the rotation axis\n");
		return;
	}

	min = 0;
	max = TABLET_AXIS_MAX;
	res = 0;

	/* The mouse/lens tool don't have pressure, but for backwards-compat
	   with the xorg wacom driver we initialize the the axis anyway */
	axis = 2;
	xf86InitValuatorAxisStruct(dev, axis,
				   XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE),
				   min, max, res * 1000, 0, res * 1000, Absolute);

	axis = 3;
	min = -TABLET_AXIS_MAX;
	max = TABLET_AXIS_MAX;
	xf86InitValuatorAxisStruct(dev, axis,
				   XIGetKnownProperty(AXIS_LABEL_PROP_ABS_RZ),
				   min, max, res * 1000, 0, res * 1000, Absolute);
	return;
}

1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
static void
xf86libinput_init_tablet(InputInfoPtr pInfo)
{
	DeviceIntPtr dev = pInfo->dev;
	struct xf86libinput *driver_data = pInfo->private;
	struct libinput_tablet_tool *tool;
	int min, max, res;
	unsigned char btnmap[TABLET_NUM_BUTTONS];
	Atom btnlabels[TABLET_NUM_BUTTONS] = {0};
	Atom axislabels[TOUCHPAD_NUM_AXES] = {0};
	int nbuttons = TABLET_NUM_BUTTONS;
	int naxes = 2;

	BUG_RETURN(driver_data->tablet_tool == NULL);

	tool = driver_data->tablet_tool;

	init_button_map(btnmap, ARRAY_SIZE(btnmap));

	if (libinput_tablet_tool_has_pressure(tool))
		naxes++;
	if (libinput_tablet_tool_has_tilt(tool))
		naxes += 2;
1251 1252
	if (libinput_tablet_tool_has_slider(tool))
		naxes++;
1253 1254
	if (libinput_tablet_tool_has_rotation(tool))
		naxes++;
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279

	InitPointerDeviceStruct((DevicePtr)dev,
				driver_data->options.btnmap,
				nbuttons,
				btnlabels,
				xf86libinput_ptr_ctl,
				GetMotionHistorySize(),
				naxes,
				axislabels);

	min = 0;
	max = TABLET_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);

	switch (libinput_tablet_tool_get_type(tool)) {
	case LIBINPUT_TABLET_TOOL_TYPE_PEN:
	case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
		xf86libinput_init_tablet_pen_or_eraser(pInfo, tool);
		break;
1280 1281 1282
	case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
		xf86libinput_init_tablet_airbrush(pInfo, tool);
		break;
1283 1284 1285 1286
	case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
	case LIBINPUT_TABLET_TOOL_TYPE_LENS:
		xf86libinput_init_tablet_mouse(pInfo, tool);
		break;
1287 1288 1289 1290 1291 1292 1293 1294
	default:
		xf86IDrvMsg(pInfo, X_ERROR, "Tool type not supported yet\n");
		break;
	}

	InitProximityClassDeviceStruct(dev);
}

Peter Hutterer's avatar
Peter Hutterer committed
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307
static void
xf86libinput_init_tablet_pad(InputInfoPtr pInfo)
{
	DeviceIntPtr dev = pInfo->dev;
	struct xf86libinput *driver_data = pInfo->private;
	struct libinput_device *device = driver_data->shared_device->device;
	int min, max, res;
	unsigned char btnmap[MAX_BUTTONS];
	Atom btnlabels[MAX_BUTTONS] = {0};
	Atom axislabels[TOUCHPAD_NUM_AXES] = {0};
	int nbuttons;
	int naxes = 7;

1308
	nbuttons = libinput_device_tablet_pad_get_num_buttons(device) + 4;
Peter Hutterer's avatar
Peter Hutterer committed
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354
	init_button_map(btnmap, nbuttons);

	InitPointerDeviceStruct((DevicePtr)dev,
				driver_data->options.btnmap,
				nbuttons,
				btnlabels,
				xf86libinput_ptr_ctl,
				GetMotionHistorySize(),
				naxes,
				axislabels);

	/* For compat with xf86-input-wacom we init x, y, pressure, followed
	 * by strip x, strip y, ring, ring2*/
	min = 0;
	max = TABLET_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);
	xf86InitValuatorAxisStruct(dev, 2,
			           XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE),
				   min, max, res * 1000, 0, res * 1000, Absolute);

	/* strip x */
	max = TABLET_STRIP_AXIS_MAX;
	xf86InitValuatorAxisStruct(dev, 3,
			           None,
				   min, max, res * 1000, 0, res * 1000, Absolute);
	/* strip y */
	xf86InitValuatorAxisStruct(dev, 4,
			           None,
				   min, max, res * 1000, 0, res * 1000, Absolute);
	/* first ring */
	max = TABLET_RING_AXIS_MAX;
	xf86InitValuatorAxisStruct(dev, 5,
			           XIGetKnownProperty(AXIS_LABEL_PROP_ABS_WHEEL),
				   min, max, res * 1000, 0, res * 1000, Absolute);
	/* second ring */
	xf86InitValuatorAxisStruct(dev, 6,
			           None,
				   min, max, res * 1000, 0, res * 1000, Absolute);
}

1355 1356 1357 1358 1359
static int
xf86libinput_init(DeviceIntPtr dev)
{
	InputInfoPtr pInfo = dev->public.devicePrivate;
	struct xf86libinput *driver_data = pInfo->private;
1360 1361 1362 1363
	struct xf86libinput_device *shared_device = driver_data->shared_device;
	struct libinput_device *device = shared_device->device;

	BUG_RETURN_VAL(device == NULL, !Success);
1364 1365 1366

	dev->public.on = FALSE;

1367
	if (driver_data->capabilities & CAP_KEYBOARD)
Peter Hutterer's avatar
Peter Hutterer committed
1368
		xf86libinput_init_keyboard(pInfo);
1369
	if (driver_data->capabilities & CAP_POINTER) {
1370 1371
		if (libinput_device_config_calibration_has_matrix(device) &&
		    !libinput_device_config_accel_is_available(device))
1372 1373 1374 1375
			xf86libinput_init_pointer_absolute(pInfo);
		else
			xf86libinput_init_pointer(pInfo);
	}
1376
	if (driver_data->capabilities & CAP_TOUCH)
Peter Hutterer's avatar
Peter Hutterer committed
1377
		xf86libinput_init_touch(pInfo);
1378 1379
	if (driver_data->capabilities & CAP_TABLET_TOOL)
		xf86libinput_init_tablet(pInfo);
Peter Hutterer's avatar
Peter Hutterer committed
1380 1381
	if (driver_data->capabilities & CAP_TABLET_PAD)
		xf86libinput_init_tablet_pad(pInfo);
1382

1383
	LibinputApplyConfig(dev);
1384 1385 1386
	LibinputInitProperty(dev);
	XIRegisterPropertyHandler(dev, LibinputSetProperty, NULL, NULL);

1387 1388 1389 1390 1391 1392 1393 1394
	/* If we have a device but it's not yet enabled it's the
	 * already-removed device from PreInit. Drop the ref to clean up,
	 * we'll get a new libinput_device during DEVICE_ON when we re-add
	 * it. */
	if (!xf86libinput_shared_is_enabled(shared_device)) {
		libinput_device_unref(device);
		shared_device->device = NULL;
	}
1395 1396 1397 1398

	return 0;
}

1399 1400 1401 1402 1403 1404 1405
static bool
is_libinput_device(InputInfoPtr pInfo)
{
	char *driver;
	BOOL rc;

	driver = xf86CheckStrOption(pInfo->options, "driver", "");
1406
	rc = streq(driver, "libinput");
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423
	free(driver);

	return rc;
}

static void
swap_registered_device(InputInfoPtr pInfo)
{
	InputInfoPtr next;

	if (pInfo != driver_context.registered_InputInfoPtr)
		return;

	next = xf86FirstLocalDevice();
	while (next == pInfo || !is_libinput_device(next))
		next = next->next;

1424
#if HAVE_THREADED_INPUT
1425
	input_lock();
1426 1427 1428
#else
	int sigstate = xf86BlockSIGIO();
#endif
1429
	xf86RemoveEnabledDevice(pInfo);
1430
	xf86AddEnabledDevice(next);
1431
	driver_context.registered_InputInfoPtr = next;
1432
#if HAVE_THREADED_INPUT
1433
	input_unlock();
1434 1435 1436
#else
	xf86UnblockSIGIO(sigstate);
#endif
1437 1438
}

1439 1440 1441
static void
xf86libinput_destroy(DeviceIntPtr dev)
{
1442 1443 1444 1445
	InputInfoPtr pInfo = dev->public.devicePrivate;
	struct xf86libinput *driver_data = pInfo->private;
	struct xf86libinput_device *shared_device = driver_data->shared_device;

1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456
	/* If the device being destroyed is the one we used for
	 * xf86AddEnabledDevice(), we need to swap it out for one that is
	 * still live. xf86AddEnabledDevice() buffers some data and once the
	 * deletes pInfo (when DEVICE_OFF completes) the thread will keep
	 * calling that struct's read_input because we never removed it.
	 * Avoid this by removing ours and substituting one that's still
	 * valid, the fd is the same anyway (libinput's epollfd).
	 */
	if (driver_context.device_enabled_count > 0)
		swap_registered_device(pInfo);

1457 1458
	xorg_list_del(&driver_data->shared_device_link);

1459 1460 1461
	if (driver_data->tablet_tool)
		libinput_tablet_tool_unref(driver_data->tablet_tool);

1462
	xf86libinput_shared_unref(shared_device);
1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
}

static int
xf86libinput_device_control(DeviceIntPtr dev, int mode)
{
	int rc = BadValue;

	switch(mode) {
		case DEVICE_INIT:
			rc = xf86libinput_init(dev);
			break;
		case DEVICE_ON:
			rc = xf86libinput_on(dev);
			break;
		case DEVICE_OFF:
			rc = xf86libinput_off(dev);
			break;
		case DEVICE_CLOSE:
			xf86libinput_destroy(dev);
Peter Hutterer's avatar
Peter Hutterer committed
1482
			rc = Success;
1483 1484 1485 1486 1487 1488 1489
			break;
	}

	return rc;
}

static void
Peter Hutterer's avatar
Peter Hutterer committed
1490
xf86libinput_handle_motion(InputInfoPtr pInfo, struct libinput_event_pointer *event)
1491 1492
{
	DeviceIntPtr dev = pInfo->dev;
1493 1494
	struct xf86libinput *driver_data = pInfo->private;
	ValuatorMask *mask = driver_data->valuators;
1495
	double x, y;
1496

1497 1498 1499
	if ((driver_data->capabilities & CAP_POINTER) == 0)
		return;

1500 1501
	x = libinput_event_pointer_get_dx(event);
	y = libinput_event_pointer_get_dy(event);
1502

1503
	valuator_mask_zero(mask);
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515

#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
1516 1517
	valuator_mask_set_double(mask, 0, x);
	valuator_mask_set_double(mask, 1, y);
1518
#endif
1519
	xf86PostMotionEventM(dev, Relative, mask);
1520 1521
}

1522 1523 1524 1525 1526 1527 1528 1529
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;

1530 1531 1532 1533 1534 1535 1536
	if (!driver_data->has_abs) {
		xf86IDrvMsg(pInfo, X_ERROR,
			    "Discarding absolute event from relative device. "
			    "Please file a bug\n");
		return;
	}

1537 1538 1539
	if ((driver_data->capabilities & CAP_POINTER) == 0)
		return;

1540 1541 1542 1543 1544 1545 1546 1547 1548 1549
	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);
}

1550
static void
Peter Hutterer's avatar
Peter Hutterer committed
1551
xf86libinput_handle_button(InputInfoPtr pInfo, struct libinput_event_pointer *event)
1552 1553
{
	DeviceIntPtr dev = pInfo->dev;
Peter Hutterer's avatar
Peter Hutterer committed
1554
	struct xf86libinput *driver_data = pInfo->private;
1555 1556 1557
	int button;
	int is_press;

1558 1559 1560
	if ((driver_data->capabilities & CAP_POINTER) == 0)
		return;

1561
	button = btn_linux2xorg(libinput_event_pointer_get_button(event));
Peter Hutterer's avatar
Peter Hutterer committed
1562
	is_press = (libinput_event_pointer_get_button_state(event) == LIBINPUT_BUTTON_STATE_PRESSED);
Peter Hutterer's avatar
Peter Hutterer committed
1563 1564 1565 1566

	if (draglock_get_mode(&driver_data->draglock) != DRAGLOCK_DISABLED)
		draglock_filter_button(&driver_data->draglock, &button, &is_press);

Peter Hutterer's avatar
Peter Hutterer committed
1567
	if (button && button < 256)
Peter Hutterer's avatar
Peter Hutterer committed
1568
		xf86PostButtonEvent(dev, Relative, button, is_press, 0, 0);
1569 1570 1571
}

static void
Peter Hutterer's avatar
Peter Hutterer committed
1572
xf86libinput_handle_key(InputInfoPtr pInfo, struct libinput_event_keyboard *event)
1573 1574
{
	DeviceIntPtr dev = pInfo->dev;
1575
	struct xf86libinput *driver_data = pInfo->private;
1576
	int is_press;
Peter Hutterer's avatar
Peter Hutterer committed
1577
	int key = libinput_event_keyboard_get_key(event);
1578

1579 1580 1581
	if ((driver_data->capabilities & CAP_KEYBOARD) == 0)
		return;

1582 1583
	key += XORG_KEYCODE_OFFSET;

1584
	is_press = (libinput_event_keyboard_get_key_state(event) == LIBINPUT_KEY_STATE_PRESSED);
1585 1586 1587
	xf86PostKeyboardEvent(dev, key, is_press);
}

1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645
/*
 * The scroll fraction is the value we divide the scroll dist with to
 * accommodate for wheels with a small click angle. On these devices,
 * multiple clicks of small angle accumulate to the XI 2.1 scroll distance.
 * This gives us smooth scrolling on those wheels for small movements, the
 * legacy button events are generated whenever the full distance is reached.
 * e.g. a 2 degree click angle requires 8 clicks before a legacy event is
 * sent, but each of those clicks will send XI2.1 smooth scroll data for
 * compatible clients.
 */
static inline double
get_scroll_fraction(struct xf86libinput *driver_data,
		    struct libinput_event_pointer *event,
		    enum libinput_pointer_axis axis)
{
	double *fraction;
	double f;
	double angle;
	int discrete;

	switch (axis) {
	case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
		fraction = &driver_data->scroll.hdist_fraction;
		break;
	case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
		fraction = &driver_data->scroll.vdist_fraction;
		break;
	default:
		return 0.0;
	}

	if (*fraction != 0.0)
		return *fraction;

	/* Calculate the angle per single scroll event */
	angle = libinput_event_pointer_get_axis_value(event, axis);
	discrete = libinput_event_pointer_get_axis_value_discrete(event, axis);
	angle /= discrete;

	/* We only do magic for click angles smaller than 10 degrees */
	if (angle >= 10) {
		*fraction = 1.0;
		return 1.0;
	}

	/* Figure out something that gets close to 15 degrees (the general
	 * wheel default) with a number of clicks. This formula gives us
	 * between 12 and and 20 degrees for the range of 1-10. See
	 * https://bugs.freedesktop.org/attachment.cgi?id=128256 for a
	 * graph.
	 */
	f = round(15.0/angle);

	*fraction = f;

	return f;
}

1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659
static inline bool
calculate_axis_value(struct xf86libinput *driver_data,
		     enum libinput_pointer_axis axis,
		     struct libinput_event_pointer *event,
		     double *value_out)
{
	enum libinput_pointer_axis_source source;
	double value;

	if (!libinput_event_pointer_has_axis(event, axis))
		return false;

	source = libinput_event_pointer_get_axis_source(event);
	if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) {
1660 1661
		double scroll_fraction;

1662
		value = libinput_event_pointer_get_axis_value_discrete(event, axis);
1663 1664
		scroll_fraction = get_scroll_fraction(driver_data, event, axis);
		value *= driver_data->scroll.vdist/scroll_fraction;
1665 1666 1667 1668 1669 1670 1671 1672 1673
	} else {
		value = libinput_event_pointer_get_axis_value(event, axis);
	}

	*value_out = value;

	return true;
}

Peter Hutterer's avatar
Peter Hutterer committed
1674
static void
Peter Hutterer's avatar
Peter Hutterer committed
1675
xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *event)
Peter Hutterer's avatar
Peter Hutterer committed
1676 1677
{
	DeviceIntPtr dev = pInfo->dev;
1678 1679
	struct xf86libinput *driver_data = pInfo->private;
	ValuatorMask *mask = driver_data->valuators;
1680
	double value;
1681
	enum libinput_pointer_axis_source source;
Peter Hutterer's avatar
Peter Hutterer committed
1682

1683 1684 1685
	if ((driver_data->capabilities & CAP_POINTER) == 0)
		return;

1686
	valuator_mask_zero(mask);
Peter Hutterer's avatar
Peter Hutterer committed
1687

1688 1689 1690 1691 1692 1693 1694 1695 1696
	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;
	}
1697

1698 1699 1700 1701
	if (calculate_axis_value(driver_data,
				 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
				 event,
				 &value))
1702
		valuator_mask_set_double(mask, 3, value);
1703 1704 1705 1706

	if (!driver_data->options.horiz_scrolling_enabled)
		goto out;

1707 1708 1709 1710
	if (calculate_axis_value(driver_data,
				 LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
				 event,
				 &value))
1711
		valuator_mask_set_double(mask, 2, value);
1712

1713
out:
1714
	xf86PostMotionEventM(dev, Relative, mask);
Peter Hutterer's avatar
Peter Hutterer committed
1715 1716
}

Peter Hutterer's avatar
Peter Hutterer committed
1717
static void
1718 1719 1720
xf86libinput_handle_touch(InputInfoPtr pInfo,
			  struct libinput_event_touch *event,
			  enum libinput_event_type event_type)
Peter Hutterer's avatar
Peter Hutterer committed
1721 1722
{
	DeviceIntPtr dev = pInfo->dev;
1723
	struct xf86libinput *driver_data = pInfo->private;
Peter Hutterer's avatar
Peter Hutterer committed
1724 1725
	int type;
	int slot;
1726
	ValuatorMask *m = driver_data->valuators;
1727
	double val;
Peter Hutterer's avatar
Peter Hutterer committed
1728 1729 1730

	/* libinput doesn't give us hw touch ids which X expects, so
	   emulate them here */
1731 1732
	static unsigned int next_touchid;
	static unsigned int touchids[TOUCH_MAX_SLOTS] = {0};
Peter Hutterer's avatar
Peter Hutterer committed
1733

1734 1735 1736
	if ((driver_data->capabilities & CAP_TOUCH) == 0)
		return;