From 0e9883b564ed19739cb4e85d658c0592542d31f0 Mon Sep 17 00:00:00 2001 From: Marcello Haddeman Date: Thu, 16 Apr 2026 19:44:17 +0200 Subject: [PATCH] Add TabletTool config options for eraser button and tool pressure Tested on a XP-Pen Artist Pro Gen 2. The eraser button mode has some quirks to it such as not being able to set keyboard buttons but otherwise works well. Krita recognizes keycode 332 as a right-click action for example. Pressure range seems to work without issue, a very low max range means it takes very minimal pressure to reach the maximum. While a very high min range means you need to put a lot of pressure before the input is even recognized. The exact moment these settings are set, happens within the `CInputManager::ensureTabletToolPresent()` function after a new TabletTool has been added. The newly created `setTabletToolconfigs()` function is called to set up the configuration. --- meta/hl.meta.lua | 8 ++++++++ src/config/legacy/ConfigManager.cpp | 4 ++++ src/config/values/ConfigValues.cpp | 19 +++++++++++++++++++ src/config/values/ConfigValues.hpp | 4 ++++ src/managers/input/InputManager.cpp | 24 ++++++++++++++++++++++++ src/managers/input/InputManager.hpp | 1 + src/managers/input/Tablets.cpp | 2 ++ 7 files changed, 62 insertions(+) diff --git a/meta/hl.meta.lua b/meta/hl.meta.lua index 6e34ff344..3ca04963b 100644 --- a/meta/hl.meta.lua +++ b/meta/hl.meta.lua @@ -269,6 +269,10 @@ ---| "input.tablet.region_size" ---| "input.tablet.relative_input" ---| "input.tablet.transform" +---| "input.tablettool.eraser_button_mode" +---| "input.tablettool.eraser_button_override" +---| "input.tablettool.pressure_range_max" +---| "input.tablettool.pressure_range_min" ---| "input.touchdevice.enabled" ---| "input.touchdevice.output" ---| "input.touchdevice.transform" @@ -1139,6 +1143,10 @@ hl = {} ---@field ['input.tablet.region_size'] HL.Vec2Like ---@field ['input.tablet.relative_input'] boolean ---@field ['input.tablet.transform'] integer|boolean +---@field ['input.tablettool.eraser_button_mode'] integer|boolean +---@field ['input.tablettool.eraser_button_override'] integer|boolean +---@field ['input.tablettool.pressure_range_max'] number|boolean +---@field ['input.tablettool.pressure_range_min'] number|boolean ---@field ['input.touchdevice.enabled'] boolean ---@field ['input.touchdevice.output'] string ---@field ['input.touchdevice.transform'] integer|boolean diff --git a/src/config/legacy/ConfigManager.cpp b/src/config/legacy/ConfigManager.cpp index bbb63daf7..8b99777ec 100644 --- a/src/config/legacy/ConfigManager.cpp +++ b/src/config/legacy/ConfigManager.cpp @@ -556,6 +556,10 @@ CConfigManager::CConfigManager() { m_config->addSpecialConfigValue("device", "share_states", Hyprlang::INT{0}); // only for virtualkeyboards m_config->addSpecialConfigValue("device", "release_pressed_on_close", Hyprlang::INT{0}); // only for virtualkeyboards m_config->addSpecialConfigValue("device", "tags", STRVAL_EMPTY); // only for keyboards and mice + m_config->addSpecialConfigValue("device", "eraser_button_mode", Hyprlang::INT{0}); // only for tablettools + m_config->addSpecialConfigValue("device", "eraser_button_override", Hyprlang::INT{0}); // only for tablettools + m_config->addSpecialConfigValue("device", "pressure_range_min", Hyprlang::FLOAT{-1.0}); // only for tablettools + m_config->addSpecialConfigValue("device", "pressure_range_max", Hyprlang::FLOAT{-1.0}); // only for tablettools m_config->addSpecialCategory("monitorv2", {.key = "output"}); m_config->addSpecialConfigValue("monitorv2", "disabled", Hyprlang::INT{0}); diff --git a/src/config/values/ConfigValues.cpp b/src/config/values/ConfigValues.cpp index abf8ecab5..f729e3f7b 100644 --- a/src/config/values/ConfigValues.cpp +++ b/src/config/values/ConfigValues.cpp @@ -360,6 +360,25 @@ std::vector> Values::getConfigValues() { MS("input:tablet:active_area_position", "position of the active area in mm", Config::VEC2{}, {.validator = vec2Range(0, 0, 500, 500), .refresh = Supplementary::REFRESH_INPUT_DEVICES}), + /* + * input:tablettool: + */ + + MS("input:tablettool:eraser_button_mode", + "Change the eraser button behavior on the tool. When set to 0, use the default hardware behavior of the tool. " + "When set to 1, the eraser button on the tool sends a button event instead.", + 0, {.min = 0, .max = 6, .refresh = Supplementary::REFRESH_INPUT_DEVICES}), + MS("input:tablettool:eraser_button_override", + "Set a button to be button event when eraser_button_mode is set to 1. Has to be an int, cannot be a string. Must be a valid button (e.g. BTN_STYLUS) " + "excluding fake buttons (e.g. BTN_TOOL_*) and keys (KEY_*). Check wev if you have any doubts regarding the ID. 0 means default.", + 0, {.min = 0, .refresh = Supplementary::REFRESH_INPUT_DEVICES}), + MS("input:tablettool:pressure_range_min", + "Set the minimum pressure range for the tool, a negative number will set the default minimum pressure value. This is usually 0.0", + -1.0, {.min = -1.0, .max = 1.0, .refresh = Supplementary::REFRESH_INPUT_DEVICES}), + MS("input:tablettool:pressure_range_max", + "Set the maximum pressure range for the tool, a negative number will set the default maximum pressure value. This is usually 1.0", + -1.0, {.min = -1.0, .max = 1.0, .refresh = Supplementary::REFRESH_INPUT_DEVICES}), + /* * gestures: */ diff --git a/src/config/values/ConfigValues.hpp b/src/config/values/ConfigValues.hpp index 812ee7d99..02329671d 100644 --- a/src/config/values/ConfigValues.hpp +++ b/src/config/values/ConfigValues.hpp @@ -163,6 +163,10 @@ namespace Config::Values { "input:tablet:relative_input", "input:tablet:active_area_position", "input:tablet:active_area_size", + "input:tablettool:eraser_button_mode", + "input:tablettool:eraser_button_override", + "input:tablettool:pressure_range_min", + "input:tablettool:pressure_range_max", "input:touchpad:flip_x", "input:touchpad:flip_y", "input:touchpad:drag_3fg", diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 85699b14c..617d8da89 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1952,6 +1952,30 @@ void CInputManager::setTabletConfigs() { } } +void CInputManager::setTabletToolConfigs() { + for (auto const& t : m_tabletTools) { + if (t->aq()->getLibinputTool()) { + const auto NAME = t->m_hlName; + const auto LIBINPUTTOOL = t->aq()->getLibinputTool(); + + if (Config::mgr()->getDeviceInt(NAME, "eraser_button_mode", "input:tablettool:eraser_button_mode") == 1) + libinput_tablet_tool_config_eraser_button_set_mode(LIBINPUTTOOL, LIBINPUT_CONFIG_ERASER_BUTTON_BUTTON); + else + libinput_tablet_tool_config_eraser_button_set_mode(LIBINPUTTOOL, LIBINPUT_CONFIG_ERASER_BUTTON_DEFAULT); + + const auto ERASER_BUTTON_OVERRIDE = Config::mgr()->getDeviceInt(NAME, "eraser_button_override", "input:tablettool:eraser_button_override"); + libinput_tablet_tool_config_eraser_button_set_button( + LIBINPUTTOOL, ERASER_BUTTON_OVERRIDE == 0 ? libinput_tablet_tool_config_eraser_button_get_default_button(LIBINPUTTOOL) : ERASER_BUTTON_OVERRIDE); + + const auto PRESSURE_RANGE_MIN = Config::mgr()->getDeviceFloat(NAME, "pressure_range_min", "input:tablettool:pressure_range_min"); + const auto PRESSURE_RANGE_MAX = Config::mgr()->getDeviceFloat(NAME, "pressure_range_max", "input:tablettool:pressure_range_max"); + libinput_tablet_tool_config_pressure_range_set( + LIBINPUTTOOL, PRESSURE_RANGE_MIN < 0.0 ? libinput_tablet_tool_config_pressure_range_get_default_minimum(LIBINPUTTOOL) : PRESSURE_RANGE_MIN, + PRESSURE_RANGE_MAX < 0.0 ? libinput_tablet_tool_config_pressure_range_get_default_maximum(LIBINPUTTOOL) : PRESSURE_RANGE_MAX); + } + } +} + void CInputManager::newSwitch(SP pDevice) { const auto PNEWDEV = &m_switches.emplace_back(); PNEWDEV->pDevice = pDevice; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 0727b7b1f..166cd6737 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -127,6 +127,7 @@ class CInputManager { void setPointerConfigs(); void setTouchDeviceConfigs(SP dev = nullptr); void setTabletConfigs(); + void setTabletToolConfigs(); void updateCapabilities(); void updateKeyboardsLeds(SP); diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index a2fec15c2..6799777b8 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -285,6 +285,8 @@ SP CInputManager::ensureTabletToolPresent(SP