Implement tablet tool pressure range support

This commit is contained in:
Peter Hutterer
2024-06-07 11:08:50 +10:00
parent 74335c6fd6
commit 72c8eb25f8
5 changed files with 197 additions and 0 deletions

View File

@@ -88,6 +88,17 @@ AC_LINK_IFELSE(
[libinput_have_custom_accel=yes]],
[AC_MSG_RESULT([no])
[libinput_have_custom_accel=no]])
AC_MSG_CHECKING([if libinput_tablet_tool_config_pressure_range_set is available])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[#include <libinput.h>]],
[[libinput_tablet_tool_config_pressure_range_set(0)]])],
[AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_LIBINPUT_PRESURE_RANGE, [1],
[libinput_tablet_tool_config_pressure_range_set() is available])
[libinput_have_pressure_range=yes]],
[AC_MSG_RESULT([no])
[libinput_have_pressure_range=no]])
LIBS=$OLD_LIBS
CFLAGS=$OLD_CFLAGS

View File

@@ -222,6 +222,15 @@
*/
#define LIBINPUT_PROP_TABLET_TOOL_PRESSURECURVE "libinput Tablet Tool Pressurecurve"
/* Tablet tool pressure range: float, 2 values, 32 bit
* Value range is [0.0, 1.0] for min and max physical pressure to map to the logical range
* Default value: 0.0 1.0
*/
#define LIBINPUT_PROP_TABLET_TOOL_PRESSURE_RANGE "libinput Tablet Tool Pressure Range"
/* Tablet tool pressure range: float, 2 values, 32 bit, read-only */
#define LIBINPUT_PROP_TABLET_TOOL_PRESSURE_RANGE_DEFAULT "libinput Tablet Tool Pressure Range Default"
/* Tablet tool area ratio: CARD32, 2 values, w and h */
#define LIBINPUT_PROP_TABLET_TOOL_AREA_RATIO "libinput Tablet Tool Area Ratio"

View File

@@ -210,6 +210,14 @@ points. The respective x/y coordinate must be in the [0.0, 1.0] range. For
more information see section
.B TABLET STYLUS PRESSURE CURVE.
.TP 7
.BI "Option \*qTabletToolPressureRange\*q \*q" "min max" \*q
Set the pressure range for a tablet stylus to the given subset of the physical
range. The min/max values must be in the [0.0, 1.0] range. For
example a min of 0.3 means the tablet will send 0 pressure for anything equal
or below 30% of the physical pressure range and a max of 0.7 means
the tablet sends its maximum pressure value for any pressure equal or higher to
70% of the physical pressure range.
.TP 7
.BI "Option \*qTabletToolAreaRatio\*q \*q" "w:h" \*q
Sets the area ratio for a tablet tool. The area always starts at the
origin (0/0) and expands to the largest available area with the specified

View File

@@ -57,6 +57,10 @@ if cc.has_function('libinput_config_accel_create',
dependencies: dep_libinput)
config_h.set('HAVE_LIBINPUT_CUSTOM_ACCEL', 1)
endif
if cc.has_function('libinput_tablet_tool_config_pressure_range_set',
dependencies: dep_libinput)
config_h.set('HAVE_LIBINPUT_PRESSURE_RANGE', 1)
endif
dir_headers = get_option('sdkdir')
if dir_headers == ''

View File

@@ -192,6 +192,9 @@ struct xf86libinput {
float rotation_angle;
struct bezier_control_point pressurecurve[4];
struct range {
float min, max;
} pressure_range;
struct ratio {
int x, y;
} area;
@@ -455,6 +458,25 @@ xf86libinput_set_pressurecurve(struct xf86libinput *driver_data,
driver_data->pressurecurve.sz);
}
static inline bool
xf86libinput_set_pressure_range(struct xf86libinput *driver_data,
const struct range *range)
{
#if HAVE_LIBINPUT_PRESSURE_RANGE
struct libinput_tablet_tool *tool = driver_data->tablet_tool;
if (!tool)
return FALSE;
return libinput_tablet_tool_config_pressure_range_is_available(tool) &&
libinput_tablet_tool_config_pressure_range_set(tool,
range->min,
range->max) == LIBINPUT_CONFIG_STATUS_SUCCESS;
#else
return FALSE;
#endif
}
static inline void
xf86libinput_set_area_ratio(struct xf86libinput *driver_data,
const struct ratio *ratio)
@@ -879,6 +901,27 @@ LibinputApplyConfigRotation(DeviceIntPtr dev,
driver_data->options.rotation_angle);
}
static void
LibinputApplyConfigPressureRange(DeviceIntPtr dev,
struct xf86libinput *driver_data,
struct libinput_device *device)
{
#if HAVE_LIBINPUT_PRESSURE_RANGE
InputInfoPtr pInfo = dev->public.devicePrivate;
struct libinput_tablet_tool *tool = driver_data->tablet_tool;
struct range *range = &driver_data->options.pressure_range;
if (!subdevice_has_capabilities(dev, CAP_TABLET_TOOL))
return;
if (tool && libinput_tablet_tool_config_pressure_range_is_available(tool) &&
libinput_tablet_tool_config_pressure_range_set(tool, range->min, range->max) != LIBINPUT_CONFIG_STATUS_SUCCESS)
xf86IDrvMsg(pInfo, X_ERROR,
"Failed to set PressureRange to %.2f..%.2f\n",
range->min, range->max);
#endif
}
static inline void
LibinputApplyConfig(DeviceIntPtr dev)
{
@@ -897,6 +940,7 @@ LibinputApplyConfig(DeviceIntPtr dev)
LibinputApplyConfigMiddleEmulation(dev, driver_data, device);
LibinputApplyConfigDisableWhileTyping(dev, driver_data, device);
LibinputApplyConfigRotation(dev, driver_data, device);
LibinputApplyConfigPressureRange(dev, driver_data, device);
}
static int
@@ -3539,6 +3583,46 @@ out:
xf86libinput_set_pressurecurve(driver_data, controls);
}
static void
xf86libinput_parse_pressure_range_option(InputInfoPtr pInfo,
struct xf86libinput *driver_data,
struct range *range)
{
#if HAVE_LIBINPUT_PRESSURE_RANGE
struct libinput_tablet_tool *tool = driver_data->tablet_tool;
float min, max;
char *str;
int rc;
range->min = 0.0;
range->max = 1.0;
if ((driver_data->capabilities & CAP_TABLET_TOOL) == 0)
return;
if (!tool || !libinput_tablet_tool_config_pressure_range_is_available(tool))
return;
str = xf86SetStrOption(pInfo->options,
"TabletToolPressureRange",
NULL);
if (!str)
return;
rc = sscanf(str, "%f %f", &min, &max);
if (rc != 2)
goto out;
if (min < 0.0 || max > 1.0 || min >= max)
goto out;
range->min = min;
range->max = max;
out:
free(str);
#endif
}
static inline bool
want_area_handling(struct xf86libinput *driver_data)
{
@@ -3629,6 +3713,7 @@ xf86libinput_parse_options(InputInfoPtr pInfo,
xf86libinput_parse_pressurecurve_option(pInfo,
driver_data,
options->pressurecurve);
xf86libinput_parse_pressure_range_option(pInfo, driver_data, &options->pressure_range);
xf86libinput_parse_tablet_area_option(pInfo,
driver_data,
&options->area);
@@ -4103,6 +4188,8 @@ static Atom prop_mode_groups_rings;
static Atom prop_mode_groups_strips;
static Atom prop_rotation_angle;
static Atom prop_rotation_angle_default;
static Atom prop_pressure_range;
static Atom prop_pressure_range_default;
/* driver properties */
static Atom prop_draglock;
@@ -5110,6 +5197,42 @@ LibinputSetPropertyPressureCurve(DeviceIntPtr dev,
return Success;
}
static inline int
LibinputSetPropertyPressureRange(DeviceIntPtr dev,
Atom atom,
XIPropertyValuePtr val,
BOOL checkonly)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
struct xf86libinput *driver_data = pInfo->private;
float *vals;
struct range range = { 0.0, 1.0 };
if (val->format != 32 || val->size != 2 || val->type != prop_float)
return BadMatch;
vals = val->data;
range.min = vals[0];
range.max = vals[1];
if (checkonly) {
if (range.min < 0.0 || range.max > 1.0 || range.min >= range.max)
return BadValue;
/* Disallow reducing the range to less than 20% of the range, mostly
* to avoid footguns */
if (range.max - range.min < 0.2)
return BadValue;
if (!xf86libinput_check_device(dev, atom))
return BadMatch;
} else {
driver_data->options.pressure_range = range;
}
return Success;
}
static inline int
LibinputSetPropertyAreaRatio(DeviceIntPtr dev,
Atom atom,
@@ -5261,6 +5384,8 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
rc = LibinputSetPropertyRotationAngle(dev, atom, val, checkonly);
else if (atom == prop_pressurecurve)
rc = LibinputSetPropertyPressureCurve(dev, atom, val, checkonly);
else if (atom == prop_pressure_range)
rc = LibinputSetPropertyPressureRange(dev, atom, val, checkonly);
else if (atom == prop_area_ratio)
rc = LibinputSetPropertyAreaRatio(dev, atom, val, checkonly);
else if (atom == prop_hires_scroll)
@@ -5279,6 +5404,7 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
atom == prop_mode_groups_strips ||
atom == prop_natural_scroll_default ||
atom == prop_product_id ||
atom == prop_pressure_range_default ||
atom == prop_rotation_angle_default ||
atom == prop_scroll_button_default ||
atom == prop_scroll_buttonlock_default ||
@@ -6263,6 +6389,44 @@ LibinputInitPressureCurveProperty(DeviceIntPtr dev,
8, data);
}
static void
LibinputInitPressureRangeProperty(DeviceIntPtr dev,
struct xf86libinput *driver_data)
{
#if HAVE_LIBINPUT_PRESSURE_RANGE
struct libinput_tablet_tool *tool = driver_data->tablet_tool;
const struct range *range = &driver_data->options.pressure_range;
float data[2] = {
range->min,
range->max,
};
if ((driver_data->capabilities & CAP_TABLET_TOOL) == 0)
return;
if (!tool || !libinput_tablet_tool_config_pressure_range_is_available(tool))
return;
prop_pressure_range = LibinputMakeProperty(dev,
LIBINPUT_PROP_TABLET_TOOL_PRESSURE_RANGE,
prop_float, 32,
2, &data);
if (!prop_pressure_range)
return;
data[0] = libinput_tablet_tool_config_pressure_range_get_default_minimum(tool);
data[1] = libinput_tablet_tool_config_pressure_range_get_default_maximum(tool);
prop_pressure_range_default = LibinputMakeProperty(dev,
LIBINPUT_PROP_TABLET_TOOL_PRESSURE_RANGE_DEFAULT,
prop_float, 32,
2, &data);
if (!prop_pressure_range_default)
return;
#endif
}
static void
LibinputInitTabletAreaRatioProperty(DeviceIntPtr dev,
struct xf86libinput *driver_data)
@@ -6386,6 +6550,7 @@ LibinputInitProperty(DeviceIntPtr dev)
LibinputInitHorizScrollProperty(dev, driver_data);
LibinputInitScrollPixelDistanceProperty(dev, driver_data, device);
LibinputInitPressureCurveProperty(dev, driver_data);
LibinputInitPressureRangeProperty(dev, driver_data);
LibinputInitTabletAreaRatioProperty(dev, driver_data);
LibinputInitTabletSerialProperty(dev, driver_data);
LibinputInitHighResolutionScrollProperty(dev, driver_data, device);