mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-28 14:20:06 +01:00
lua: implement support for disabling of features
Because our lua hooks don't expose the device-added callback we need to cache any calls to disable a feature and then apply it quietly when the device is actually added. Any other call can go straight through. Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1249>
This commit is contained in:
parent
5b2a723a02
commit
347ff90871
5 changed files with 200 additions and 0 deletions
|
|
@ -631,3 +631,22 @@ a device's capabilities before the device is processed by libinput.
|
|||
function is identical to ``prepend_frame()``.
|
||||
|
||||
See ``prepend_frame()`` for more details.
|
||||
|
||||
.. function:: EvdevDevice:disable_feature(feature_name)
|
||||
|
||||
Disable the given libinput-internal feature for this device. This should be used
|
||||
by plugins that replace that feature with a custom implementation for this device.
|
||||
|
||||
libinput may have multiple internal implementations for any given feature, disabling
|
||||
it via this API disables any and all of those implementations, causing the feature to
|
||||
no longer work at all. It is up to the plugin implementation to re-implement that
|
||||
feature to match the user's expectation.
|
||||
|
||||
Version 1 of the plugin API supports the following features:
|
||||
|
||||
- ``button-debouncing``: see :ref:`button_debouncing`
|
||||
- ``touchpad-hysteresis``: see :ref:`touchpad_jitter`
|
||||
- ``touchpad-jump-detection``: see :ref:`touchpad_jumping_cursor`
|
||||
- ``touchpad-palm-detection``: see :ref:`palm_detection`
|
||||
- ``wheel-debouncing``: some high-resolution mouse wheel movements inside libinput
|
||||
are delayed and/or modified
|
||||
|
|
|
|||
16
plugins/10-disable-feature.lua
Normal file
16
plugins/10-disable-feature.lua
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
-- SPDX-License-Identifier: MIT
|
||||
--
|
||||
-- An example plugin to show how to disable an internal feature.
|
||||
--
|
||||
-- Typically one would expect the plugin to re-implement the feature
|
||||
-- in a more device-specific manner but that's not done here.
|
||||
|
||||
-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
|
||||
-- libinput:register({1})
|
||||
libinput:connect("new-evdev-device", function(device)
|
||||
local udev_info = device:udev_properties()
|
||||
if udev_info["ID_INPUT_TOUCHPAD"] then
|
||||
log.info("Disabling palm detection on " .. device:name())
|
||||
device:disable_feature("touchpad-palm-detection")
|
||||
end
|
||||
end)
|
||||
|
|
@ -5,6 +5,7 @@ plugins = [
|
|||
'10-pointer-go-faster.lua',
|
||||
'10-pointer-go-slower.lua',
|
||||
'10-delay-motion.lua',
|
||||
'10-disable-feature.lua',
|
||||
]
|
||||
|
||||
fs = import('fs')
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "util-strings.h"
|
||||
|
||||
#include "evdev-frame.h"
|
||||
#include "libinput-feature.h"
|
||||
#include "libinput-log.h"
|
||||
#include "libinput-plugin-lua.h"
|
||||
#include "libinput-plugin.h"
|
||||
|
|
@ -95,6 +96,10 @@ typedef struct {
|
|||
|
||||
int device_removed_refid;
|
||||
int frame_refid;
|
||||
|
||||
/* Caches any disable_feature calls during device_new */
|
||||
bool was_added;
|
||||
bitmask_t disabled_features;
|
||||
} EvdevDevice;
|
||||
|
||||
struct libinput_lua_plugin {
|
||||
|
|
@ -1011,6 +1016,44 @@ evdevdevice_append_frame(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
evdevdevice_disable_feature(lua_State *L)
|
||||
{
|
||||
EvdevDevice *device = luaL_checkudata(L, 1, EVDEV_DEVICE_METATABLE);
|
||||
luaL_argcheck(L, device != NULL, 1, EVDEV_DEVICE_METATABLE " expected");
|
||||
|
||||
const char *feature = luaL_checkstring(L, 2);
|
||||
|
||||
/* No refid means we got removed, so quietly
|
||||
* drop any call */
|
||||
if (device->refid == LUA_NOREF)
|
||||
return 0;
|
||||
|
||||
const struct {
|
||||
const char *name;
|
||||
enum libinput_feature feature;
|
||||
} map[] = {
|
||||
{ "button-debouncing", LIBINPUT_FEATURE_BUTTON_DEBOUNCING },
|
||||
{ "wheel-debouncing", LIBINPUT_FEATURE_WHEEL_DEBOUNCING },
|
||||
{ "touchpad-jump-detection", LIBINPUT_FEATURE_TOUCHPAD_JUMP_DETECTION },
|
||||
{ "touchpad-palm-detection", LIBINPUT_FEATURE_TOUCHPAD_PALM_DETECTION },
|
||||
{ "touchpad-hysteresis", LIBINPUT_FEATURE_TOUCHPAD_HYSTERESIS },
|
||||
};
|
||||
|
||||
ARRAY_FOR_EACH(map, m) {
|
||||
if (streq(feature, m->name)) {
|
||||
struct libinput_lua_plugin *plugin =
|
||||
lua_get_libinput_lua_plugin(L);
|
||||
libinput_plugin_disable_device_feature(plugin->parent,
|
||||
device->device,
|
||||
m->feature);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return luaL_error(L, "Unknown feature: %s", feature);
|
||||
}
|
||||
|
||||
static int
|
||||
evdevdevice_gc(lua_State *L)
|
||||
{
|
||||
|
|
@ -1041,6 +1084,7 @@ static const struct luaL_Reg evdevdevice_vtable[] = {
|
|||
{ "inject_frame", evdevdevice_inject_frame },
|
||||
{ "prepend_frame", evdevdevice_prepend_frame },
|
||||
{ "append_frame", evdevdevice_append_frame },
|
||||
{ "disable_feature", evdevdevice_disable_feature },
|
||||
{ "__gc", evdevdevice_gc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1026,6 +1026,119 @@ START_TEST(lua_inject_frame)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
enum when {
|
||||
DEVICE_NEW,
|
||||
FIRST_FRAME,
|
||||
};
|
||||
|
||||
START_TEST(lua_disable_button_debounce)
|
||||
{
|
||||
enum when when = litest_test_param_get_i32(test_env->params, "when");
|
||||
_destroy_(tmpdir) *tmpdir = tmpdir_create(NULL);
|
||||
_autofree_ char *lua = strdup_printf(
|
||||
"libinput:register({1})\n"
|
||||
"function frame_handler(device, _, _)\n"
|
||||
" device:disable_feature(\"button-debouncing\")\n"
|
||||
"end\n"
|
||||
"function new_device(device)\n"
|
||||
" %s device:disable_feature(\"button-debouncing\")\n"
|
||||
" %s device:connect(\"evdev-frame\", frame_handler)\n"
|
||||
"end\n"
|
||||
"libinput:connect(\"new-evdev-device\", new_device)\n",
|
||||
when == DEVICE_NEW ? "" : "--",
|
||||
when == FIRST_FRAME ? "" : "--");
|
||||
_autofree_ char *path = litest_write_plugin(tmpdir->path, lua);
|
||||
etrace("%s", lua);
|
||||
_litest_context_destroy_ struct libinput *li =
|
||||
litest_create_context_with_plugindir(tmpdir->path);
|
||||
|
||||
if (libinput_log_get_priority(li) > LIBINPUT_LOG_PRIORITY_DEBUG)
|
||||
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
|
||||
|
||||
litest_with_logcapture(li, capture) {
|
||||
libinput_plugin_system_load_plugins(li, LIBINPUT_PLUGIN_FLAG_NONE);
|
||||
litest_drain_events(li);
|
||||
|
||||
_destroy_(litest_device) *dev = litest_add_device(li, LITEST_MOUSE);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_disable_middleemu(dev);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_timeout_debounce(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_assert_strv_substring(capture->debugs,
|
||||
"disabled button debouncing on request");
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(lua_disable_touchpad_jump_detection)
|
||||
{
|
||||
enum when when = litest_test_param_get_i32(test_env->params, "when");
|
||||
_destroy_(tmpdir) *tmpdir = tmpdir_create(NULL);
|
||||
_autofree_ char *lua = strdup_printf(
|
||||
"libinput:register({1})\n"
|
||||
"function frame_handler(dev, f, ts)\n"
|
||||
" dev:disable_feature(\"touchpad-jump-detection\")\n"
|
||||
"end\n"
|
||||
"function new_device(device)\n"
|
||||
" %sdevice:disable_feature(\"touchpad-jump-detection\")\n"
|
||||
" %sdevice:connect(\"evdev-frame\", frame_handler)\n"
|
||||
"end\n"
|
||||
"libinput:connect(\"new-evdev-device\", new_device)\n",
|
||||
when == DEVICE_NEW ? "" : "-- ",
|
||||
when == FIRST_FRAME ? "" : "-- ");
|
||||
|
||||
etrace("plugin data:\n%s", lua);
|
||||
|
||||
_autofree_ char *path = litest_write_plugin(tmpdir->path, lua);
|
||||
_litest_context_destroy_ struct libinput *li =
|
||||
litest_create_context_with_plugindir(tmpdir->path);
|
||||
|
||||
if (libinput_log_get_priority(li) > LIBINPUT_LOG_PRIORITY_DEBUG)
|
||||
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
|
||||
|
||||
litest_with_logcapture(li, capture) {
|
||||
libinput_plugin_system_load_plugins(li, LIBINPUT_PLUGIN_FLAG_NONE);
|
||||
litest_drain_events(li);
|
||||
|
||||
_destroy_(litest_device) *dev =
|
||||
litest_add_device(li, LITEST_SYNAPTICS_RMI4);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 40, 50);
|
||||
litest_touch_move(dev, 0, 80, 80);
|
||||
litest_touch_move(dev, 0, 90, 90);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_assert(!strv_find_substring(capture->infos,
|
||||
"Touch jump detected and discarded",
|
||||
NULL));
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
TEST_COLLECTION(lua)
|
||||
{
|
||||
/* clang-format off */
|
||||
|
|
@ -1094,5 +1207,12 @@ TEST_COLLECTION(lua)
|
|||
litest_with_parameters(params, "in_timer", 'b') {
|
||||
litest_add_parametrized_no_device(lua_inject_frame, params);
|
||||
}
|
||||
|
||||
litest_with_parameters(params, "when", 'I', 2,
|
||||
litest_named_i32(DEVICE_NEW),
|
||||
litest_named_i32(FIRST_FRAME)) {
|
||||
litest_add_parametrized_no_device(lua_disable_button_debounce, params);
|
||||
litest_add_parametrized_no_device(lua_disable_touchpad_jump_detection, params);
|
||||
}
|
||||
/* clang-format on */
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue