summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2024-06-07 11:08:50 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2024-06-10 09:27:57 +0000
commit72c8eb25f80fa286d945bc5ab086ba1978446687 (patch)
tree40baebe8443c8cce13d694cc22174b47209ce063
parent74335c6fd697a60976d52786598a7dd4ba17405a (diff)
Implement tablet tool pressure range support
-rw-r--r--configure.ac11
-rw-r--r--include/libinput-properties.h9
-rw-r--r--man/libinput.man8
-rw-r--r--meson.build4
-rw-r--r--src/xf86libinput.c165
5 files changed, 197 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index b9ac4b4..a2e6e15 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/include/libinput-properties.h b/include/libinput-properties.h
index d5b5197..505259f 100644
--- a/include/libinput-properties.h
+++ b/include/libinput-properties.h
@@ -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"
diff --git a/man/libinput.man b/man/libinput.man
index f907766..46a8ef2 100644
--- a/man/libinput.man
+++ b/man/libinput.man
@@ -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
diff --git a/meson.build b/meson.build
index 4c2a821..101ee89 100644
--- a/meson.build
+++ b/meson.build
@@ -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 == ''
diff --git a/src/xf86libinput.c b/src/xf86libinput.c
index 91af896..26e8959 100644
--- a/src/xf86libinput.c
+++ b/src/xf86libinput.c
@@ -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;
@@ -5111,6 +5198,42 @@ LibinputSetPropertyPressureCurve(DeviceIntPtr dev,
}
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,
XIPropertyValuePtr val,
@@ -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 ||
@@ -6264,6 +6390,44 @@ LibinputInitPressureCurveProperty(DeviceIntPtr dev,
}
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);