[PATCH xf86-input-libinput] Support for rel+abs composite devices on the same node

Peter Hutterer peter.hutterer at who-t.net
Wed Mar 15 22:37:33 UTC 2017


On Sat, Mar 11, 2017 at 12:26:38PM +0100, Gergely Nagy wrote:
> Largely based on work by Peter Hutterer, this patch makes composite relative +
> absolute devices work with the driver. Such devices are anything that presents
> itself as both a mouse, and - for example - a touch screen, like the Keyboardio
> Model 01 (or anything that uses Nico Hood's HID library for Arduino).
> 
> If a device has both capabilities present, we split them into two separate
> devices for X (see xf86libinput_pre_init()), like we do with the composite
> keyboard + mouse devices. Then, we route absolute events to the absolute
> subdevice (see xf86libinput_pick_device()). The rest of the patch is mostly
> small updates to support the newly introduced CAP_POINTER_ABSOLUTE flag.
> 
> There's one missing thing, however: event routing for buttons. At the moment,
> button routing is simply not done, but in practice, this does not seem to have
> any ill side effects.

Most likely because the buttons are merged in the virtual core pointer in X.
But to an XI2 application they still look different which may cause some
problems down the road.

I think the best option here is to route BTN_LEFT to exclusing BTN_JOYSTICK
through the relative device and all others through the absolute device. Any
device that needs special routing can be fixed as it comes.

Cheers,
   Peter

> 
> https://bugs.freedesktop.org/show_bug.cgi?id=99914
> 
> Signed-off-by: Gergely Nagy <algernon at madhouse-project.org>
> ---
>  src/xf86libinput.c | 81 ++++++++++++++++++++++++++++++++++++++----------------
>  1 file changed, 58 insertions(+), 23 deletions(-)
> 
> diff --git a/src/xf86libinput.c b/src/xf86libinput.c
> index 888c8f2..a099c5b 100644
> --- a/src/xf86libinput.c
> +++ b/src/xf86libinput.c
> @@ -87,6 +87,7 @@
>  #define CAP_TABLET	0x8
>  #define CAP_TABLET_TOOL	0x10
>  #define CAP_TABLET_PAD	0x20
> +#define CAP_POINTER_ABSOLUTE	0x40
>  
>  struct xf86libinput_driver {
>  	struct libinput *libinput;
> @@ -805,6 +806,20 @@ xf86libinput_init_pointer_absolute(InputInfoPtr pInfo)
>  	Atom btnlabels[MAX_BUTTONS];
>  	Atom axislabels[TOUCHPAD_NUM_AXES];
>  
> +	/* We always initialize rel as parent on absrel devices */
> +	if (xf86libinput_is_subdevice(pInfo)) {
> +		/*
> +		 * FIXME: well, we can't really know which buttons belong to
> +		 * which device here, but adding it to both doesn't make
> +		 * sense either. Options are: assume LMR is on rel, BTN_0
> +		 * and friends on absolute. That's not always correct but
> +		 * that's as best as we can do.
> +		 *
> +		 * FIXME: event routing for buttons isn't set up correctly
> +		 * yet.
> +		 */
> +	}
> +
>  	for (i = BTN_BACK; i >= BTN_SIDE; i--) {
>  		if (libinput_device_pointer_has_button(device, i)) {
>  			nbuttons += i - BTN_SIDE + 1;
> @@ -1179,13 +1194,10 @@ xf86libinput_init(DeviceIntPtr dev)
>  
>  	if (driver_data->capabilities & CAP_KEYBOARD)
>  		xf86libinput_init_keyboard(pInfo);
> -	if (driver_data->capabilities & CAP_POINTER) {
> -		if (libinput_device_config_calibration_has_matrix(device) &&
> -		    !libinput_device_config_accel_is_available(device))
> -			xf86libinput_init_pointer_absolute(pInfo);
> -		else
> -			xf86libinput_init_pointer(pInfo);
> -	}
> +	if (driver_data->capabilities & CAP_POINTER)
> +		xf86libinput_init_pointer(pInfo);
> +	if (driver_data->capabilities & CAP_POINTER_ABSOLUTE)
> +		xf86libinput_init_pointer_absolute(pInfo);
>  	if (driver_data->capabilities & CAP_TOUCH)
>  		xf86libinput_init_touch(pInfo);
>  	if (driver_data->capabilities & CAP_TABLET_TOOL)
> @@ -1347,7 +1359,7 @@ xf86libinput_handle_absmotion(InputInfoPtr pInfo, struct libinput_event_pointer
>  		return;
>  	}
>  
> -	if ((driver_data->capabilities & CAP_POINTER) == 0)
> +	if ((driver_data->capabilities & CAP_POINTER_ABSOLUTE) == 0)
>  		return;
>  
>  	x = libinput_event_pointer_get_absolute_x_transformed(event, TOUCH_AXIS_MAX);
> @@ -1368,7 +1380,7 @@ xf86libinput_handle_button(InputInfoPtr pInfo, struct libinput_event_pointer *ev
>  	int button;
>  	int is_press;
>  
> -	if ((driver_data->capabilities & CAP_POINTER) == 0)
> +	if ((driver_data->capabilities & (CAP_POINTER|CAP_POINTER_ABSOLUTE)) == 0)
>  		return;
>  
>  	button = btn_linux2xorg(libinput_event_pointer_get_button(event));
> @@ -1493,7 +1505,7 @@ xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *even
>  	double value;
>  	enum libinput_pointer_axis_source source;
>  
> -	if ((driver_data->capabilities & CAP_POINTER) == 0)
> +	if ((driver_data->capabilities & (CAP_POINTER|CAP_POINTER_ABSOLUTE)) == 0)
>  		return;
>  
>  	valuator_mask_zero(mask);
> @@ -1600,6 +1612,9 @@ xf86libinput_pick_device(struct xf86libinput_device *shared_device,
>  	case LIBINPUT_EVENT_TABLET_TOOL_TIP:
>  		needed_cap = CAP_TABLET_TOOL;
>  		break;
> +	case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
> +		needed_cap = CAP_POINTER_ABSOLUTE;
> +		break;
>  	default:
>  		needed_cap = ~CAP_KEYBOARD;
>  		break;
> @@ -2940,7 +2955,7 @@ xf86libinput_get_type_name(struct libinput_device *device,
>  	/* now pick an actual type */
>  	if (libinput_device_config_tap_get_finger_count(device) > 0)
>  		type_name = XI_TOUCHPAD;
> -	else if (driver_data->capabilities & CAP_TOUCH)
> +	else if (driver_data->capabilities & (CAP_TOUCH|CAP_POINTER_ABSOLUTE))
>  		type_name = XI_TOUCHSCREEN;
>  	else if (driver_data->capabilities & CAP_POINTER)
>  		type_name = XI_MOUSE;
> @@ -3054,6 +3069,8 @@ xf86libinput_create_subdevice(InputInfoPtr pInfo,
>  		options = xf86ReplaceBoolOption(options, "_libinput/cap-keyboard", 1);
>  	if (capabilities & CAP_POINTER)
>  		options = xf86ReplaceBoolOption(options, "_libinput/cap-pointer", 1);
> +	if (capabilities & CAP_POINTER_ABSOLUTE)
> +		options = xf86ReplaceBoolOption(options, "_libinput/cap-pointer-absolute", 1);
>  	if (capabilities & CAP_TOUCH)
>  		options = xf86ReplaceBoolOption(options, "_libinput/cap-touch", 1);
>  	if (capabilities & CAP_TABLET_TOOL)
> @@ -3092,6 +3109,8 @@ caps_from_options(InputInfoPtr pInfo)
>  		capabilities |= CAP_KEYBOARD;
>  	if (xf86CheckBoolOption(pInfo->options, "_libinput/cap-pointer", 0))
>  		capabilities |= CAP_POINTER;
> +	if (xf86CheckBoolOption(pInfo->options, "_libinput/cap-pointer-absolute", 0))
> +		capabilities |= CAP_POINTER_ABSOLUTE;
>  	if (xf86CheckBoolOption(pInfo->options, "_libinput/cap-touch", 0))
>  		capabilities |= CAP_TOUCH;
>  	if (xf86CheckBoolOption(pInfo->options, "_libinput/cap-tablet-tool", 0))
> @@ -3230,8 +3249,13 @@ xf86libinput_pre_init(InputDriverPtr drv,
>  	driver_data->scroll.hdist = 15;
>  
>  	if (!is_subdevice) {
> -		if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER))
> -			driver_data->capabilities |= CAP_POINTER;
> +		if (libinput_device_has_capability(device,
> +						   LIBINPUT_DEVICE_CAP_POINTER)) {
> +			if (libinput_device_config_calibration_has_matrix(device))
> +				driver_data->capabilities |= CAP_POINTER_ABSOLUTE;
> +			if (libinput_device_config_accel_is_available(device))
> +				driver_data->capabilities |= CAP_POINTER;
> +		}
>  		if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD))
>  			driver_data->capabilities |= CAP_KEYBOARD;
>  		if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH))
> @@ -3254,15 +3278,26 @@ xf86libinput_pre_init(InputDriverPtr drv,
>  
>  	xf86libinput_parse_options(pInfo, driver_data, device);
>  
> -	/* Device is both keyboard and pointer. Drop the keyboard cap from
> -	 * this device, create a separate device instead */
> -	if (!is_subdevice &&
> -	    driver_data->capabilities & CAP_KEYBOARD &&
> -	    driver_data->capabilities & (CAP_POINTER|CAP_TOUCH)) {
> -		driver_data->capabilities &= ~CAP_KEYBOARD;
> -		xf86libinput_create_subdevice(pInfo,
> -					      CAP_KEYBOARD,
> -					      NULL);
> +	if (!is_subdevice) {
> +		/* Device is both keyboard and pointer. Drop the keyboard cap from
> +		 * this device, create a separate device instead */
> +		if (driver_data->capabilities & CAP_KEYBOARD &&
> +		    driver_data->capabilities & (CAP_POINTER|CAP_POINTER_ABSOLUTE|CAP_TOUCH)) {
> +			driver_data->capabilities &= ~CAP_KEYBOARD;
> +			xf86libinput_create_subdevice(pInfo,
> +						      CAP_KEYBOARD,
> +						      NULL);
> +		}
> +		/* Device is both relative and absolute. Drop the absolute
> +		 * cap from this device, create a separate device instead */
> +		if (driver_data->capabilities & CAP_POINTER &&
> +		    driver_data->capabilities & CAP_POINTER_ABSOLUTE) {
> +			driver_data->capabilities &= ~CAP_POINTER_ABSOLUTE;
> +			xf86libinput_create_subdevice(pInfo,
> +						      CAP_POINTER_ABSOLUTE,
> +						      NULL);
> +		}
> +
>  	}
>  
>  	pInfo->type_name = xf86libinput_get_type_name(device, driver_data);
> @@ -4571,7 +4606,7 @@ LibinputInitAccelProperty(DeviceIntPtr dev,
>  	BOOL profiles[2] = {FALSE};
>  
>  	if (!libinput_device_config_accel_is_available(device) ||
> -	    driver_data->capabilities & CAP_TABLET)
> +	    driver_data->capabilities & (CAP_TABLET|CAP_POINTER_ABSOLUTE))
>  		return;
>  
>  	prop_accel = LibinputMakeProperty(dev,
> -- 
> 2.11.0
> 
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: https://lists.x.org/mailman/listinfo/xorg-devel
> 


More information about the xorg-devel mailing list