mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-03 14:40:26 +01:00
lua: remove the inject_frame API
Injecting frame was the first implementation of adding event frames but it has since effectively been replaced by append/prepend_frame which are more predictable and easier to support. In the Lua API injecting frames was only possible within the timer and the only real use-case for this is to inject events that are then also seen by other plugins. But that can be achieved by simply ordering the plugin before the other plugins and using the append/prepend approach. Until we have a real use-case for injecting events let's remove the API so we don't lock ourselves into an API that may not do what it needs to but needs to be supported for a long time. Closes: #1210 Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1351>
This commit is contained in:
parent
2784973b4d
commit
6b9dbc2a25
3 changed files with 0 additions and 240 deletions
|
|
@ -604,24 +604,6 @@ methods will be noops.
|
|||
Disconnect the existing callback (if any) for the given event name. See
|
||||
``EvdevDevice:connect()`` for a list of supported names.
|
||||
|
||||
.. function:: EvdevDevice:inject_frame(frame)
|
||||
|
||||
.. warning:: This function is only available from inside a timer callback.
|
||||
|
||||
Inject an :ref:`evdev frame <plugins_api_evdev_frame>` into the event stream
|
||||
for this device. This emulates that same event frame being sent by the kernel
|
||||
immediately with the current time.
|
||||
|
||||
Assuming three plugins P1, P2 and P3, if P2 injects a frame the frame is
|
||||
seen by P1, P2 and P3.
|
||||
|
||||
This is rarely the right API to use. Injecting frames at the lowest level
|
||||
may make other plugins behave unexpectedly. Use ``prepend_frame`` or
|
||||
``append_frame`` instead.
|
||||
|
||||
.. warning:: The injected frame will be seen by all plugins, including the
|
||||
injecting frame. Ensure a guard is in place to prevent recursion.
|
||||
|
||||
.. function:: EvdevDevice:prepend_frame(frame)
|
||||
|
||||
Prepend an :ref:`evdev frame <plugins_api_evdev_frame>` for this device
|
||||
|
|
|
|||
|
|
@ -116,7 +116,6 @@ struct libinput_lua_plugin {
|
|||
|
||||
struct libinput_plugin_timer *timer;
|
||||
bool in_timer_func;
|
||||
struct list timer_injected_events;
|
||||
};
|
||||
|
||||
static struct libinput_lua_plugin *
|
||||
|
|
@ -566,12 +565,6 @@ libinputplugin_gc(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct timer_injected_event {
|
||||
struct list link;
|
||||
struct evdev_frame *frame;
|
||||
int device_refid;
|
||||
};
|
||||
|
||||
static void
|
||||
plugin_timer_func(struct libinput_plugin *libinput_plugin, uint64_t now, void *data)
|
||||
{
|
||||
|
|
@ -581,28 +574,7 @@ plugin_timer_func(struct libinput_plugin *libinput_plugin, uint64_t now, void *d
|
|||
lua_rawgeti(L, LUA_REGISTRYINDEX, plugin->timer_expired_refid);
|
||||
lua_pushinteger(L, now);
|
||||
|
||||
/* To allow for injecting events */
|
||||
plugin->in_timer_func = true;
|
||||
libinput_lua_pcall(plugin, 1, 0);
|
||||
plugin->in_timer_func = false;
|
||||
|
||||
struct timer_injected_event *injected_event;
|
||||
list_for_each_safe(injected_event, &plugin->timer_injected_events, link) {
|
||||
EvdevDevice *device;
|
||||
list_for_each(device, &plugin->evdev_devices, link) {
|
||||
if (device->refid == injected_event->device_refid) {
|
||||
libinput_plugin_inject_evdev_frame(
|
||||
plugin->parent,
|
||||
device->device,
|
||||
injected_event->frame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
list_remove(&injected_event->link);
|
||||
evdev_frame_unref(injected_event->frame);
|
||||
free(injected_event);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -951,36 +923,6 @@ evdevdevice_frame(lua_State *L, struct libinput_lua_plugin *plugin, EvdevDevice
|
|||
return frame;
|
||||
}
|
||||
|
||||
static int
|
||||
evdevdevice_inject_frame(lua_State *L)
|
||||
{
|
||||
EvdevDevice *device = luaL_checkudata(L, 1, EVDEV_DEVICE_METATABLE);
|
||||
luaL_argcheck(L, device != NULL, 1, EVDEV_DEVICE_METATABLE " expected");
|
||||
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
|
||||
/* No refid means we got removed, so quietly
|
||||
* drop any disconnect call */
|
||||
if (device->refid == LUA_NOREF)
|
||||
return 0;
|
||||
|
||||
struct libinput_lua_plugin *plugin = lua_get_libinput_lua_plugin(L);
|
||||
if (!plugin->in_timer_func) {
|
||||
return luaL_error(L, "Injecting events only possible in a timer func");
|
||||
}
|
||||
_unref_(evdev_frame) *frame = evdevdevice_frame(L, plugin, device);
|
||||
|
||||
/* Lua is unhappy if we inject an event which calls into our lua state
|
||||
* immediately so we need to queue this for later when we're out of the timer
|
||||
* func */
|
||||
struct timer_injected_event *event = zalloc(sizeof(*event));
|
||||
event->device_refid = device->refid;
|
||||
event->frame = steal(&frame);
|
||||
list_insert(&plugin->timer_injected_events, &event->link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
evdevdevice_prepend_frame(lua_State *L)
|
||||
{
|
||||
|
|
@ -1089,7 +1031,6 @@ static const struct luaL_Reg evdevdevice_vtable[] = {
|
|||
{ "set_absinfo", evdevdevice_set_absinfo },
|
||||
{ "connect", evdevdevice_connect },
|
||||
{ "disconnect", evdevdevice_disconnect },
|
||||
{ "inject_frame", evdevdevice_inject_frame },
|
||||
{ "prepend_frame", evdevdevice_prepend_frame },
|
||||
{ "append_frame", evdevdevice_append_frame },
|
||||
{ "disable_feature", evdevdevice_disable_feature },
|
||||
|
|
@ -1355,7 +1296,6 @@ libinput_lua_plugin_new_from_path(struct libinput *libinput, const char *path)
|
|||
plugin->device_new_refid = LUA_NOREF;
|
||||
plugin->timer_expired_refid = LUA_NOREF;
|
||||
list_init(&plugin->evdev_devices);
|
||||
list_init(&plugin->timer_injected_events);
|
||||
|
||||
_cleanup_(lua_closep) lua_State *L =
|
||||
libinput_lua_plugin_init_lua(libinput, plugin);
|
||||
|
|
|
|||
|
|
@ -929,164 +929,6 @@ START_TEST(lua_ignore_unsupported_codes)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(lua_inject_frame)
|
||||
{
|
||||
bool in_timer = litest_test_param_get_bool(test_env->params, "in_timer");
|
||||
_destroy_(tmpdir) *tmpdir = tmpdir_create(NULL);
|
||||
|
||||
/* Plugin 1 swaps left to right */
|
||||
const char *lua1 =
|
||||
"libinput:register({1})\n"
|
||||
"function frame_handler(device, frame, timestamp)\n"
|
||||
" for _, e in ipairs(frame) do\n"
|
||||
" if e.usage == evdev.BTN_LEFT then\n"
|
||||
" e.usage = evdev.BTN_RIGHT\n"
|
||||
" end\n"
|
||||
" end\n"
|
||||
" return frame\n"
|
||||
"end\n"
|
||||
"libinput:connect(\"new-evdev-device\", function(device)\n"
|
||||
" device:connect(\"evdev-frame\", frame_handler)\n"
|
||||
"end)\n";
|
||||
|
||||
/* Plugin 2 injects a left button if a middle button is pressed */
|
||||
_autofree_ char *lua2 = strdup_printf(
|
||||
"libinput:register({1})\n"
|
||||
"mydev = nil\n"
|
||||
"function frame_handler(device, frame, timestamp)\n"
|
||||
" for _, e in ipairs(frame) do\n"
|
||||
" if e.usage == evdev.BTN_SIDE then\n"
|
||||
" e.usage = evdev.BTN_EXTRA\n"
|
||||
" end\n"
|
||||
" if e.usage == evdev.BTN_MIDDLE then\n"
|
||||
" log.debug(\"Injecting frame BTN_LEFT value \" .. e.value)\n"
|
||||
" %sdevice:inject_frame({{ usage = evdev.BTN_LEFT, value = e.value }})\n"
|
||||
" %slibinput:timer_set_relative(200000)\n" /* commented out
|
||||
if !in_timer */
|
||||
" end\n"
|
||||
" end\n"
|
||||
" return frame\n"
|
||||
"end\n"
|
||||
"function timer_expired(t)\n"
|
||||
" log.debug(\"Injecting timer BTN_LEFT\")\n"
|
||||
" mydev:inject_frame({{ usage = evdev.BTN_LEFT, value = 1 }})\n"
|
||||
"end\n"
|
||||
"libinput:connect(\"new-evdev-device\", function(device)\n"
|
||||
" mydev = device\n"
|
||||
" device:connect(\"evdev-frame\", frame_handler)\n"
|
||||
"end)\n"
|
||||
"libinput:connect(\"timer-expired\", timer_expired)\n",
|
||||
in_timer ? "-- " : "",
|
||||
in_timer ? "" : "-- ");
|
||||
|
||||
_autofree_ char *p1 = litest_write_plugin(tmpdir->path, lua1);
|
||||
_autofree_ char *p2 = litest_write_plugin(tmpdir->path, lua2);
|
||||
_litest_context_destroy_ struct libinput *li =
|
||||
litest_create_context_with_plugindir(tmpdir->path);
|
||||
libinput_plugin_system_load_plugins(li, LIBINPUT_PLUGIN_SYSTEM_FLAG_NONE);
|
||||
litest_drain_events(li);
|
||||
|
||||
_destroy_(litest_device) *device = litest_add_device(li, LITEST_CYBORG_RAT);
|
||||
litest_drain_events(li);
|
||||
litest_dispatch(li);
|
||||
|
||||
litest_log_group("P1 should swap left to right") {
|
||||
litest_button_click_debounced(device, li, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(device, li, BTN_LEFT, 0);
|
||||
litest_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_drain_events(li);
|
||||
}
|
||||
|
||||
litest_log_group("P1/P2 should leave BTN_EXTRA untouched") {
|
||||
litest_button_click_debounced(device, li, BTN_EXTRA, 1);
|
||||
litest_button_click_debounced(device, li, BTN_EXTRA, 0);
|
||||
litest_dispatch(li);
|
||||
|
||||
/* This might be a false positive */
|
||||
litest_assert_button_event(li,
|
||||
BTN_EXTRA,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_EXTRA,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
|
||||
litest_log_group("P2 should map BTN_SIDE to BTN_EXTRA") {
|
||||
litest_button_click_debounced(device, li, BTN_SIDE, 1);
|
||||
litest_button_click_debounced(device, li, BTN_SIDE, 0);
|
||||
litest_dispatch(li);
|
||||
litest_timeout_debounce(li);
|
||||
litest_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_EXTRA,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_EXTRA,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
|
||||
if (in_timer) {
|
||||
litest_log_group(
|
||||
"P2 should inject left on middle via timer, P1 changes that left to right in timer") {
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, 1);
|
||||
litest_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, 0);
|
||||
litest_dispatch(li);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
/* We only inject BTN_RIGHT down, so the second inject should
|
||||
* get filtered */
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
} else {
|
||||
litest_log_group("P2 tries to inject during frame, gets unloaded") {
|
||||
litest_set_log_handler_bug(li);
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, 1);
|
||||
litest_restore_log_handler(li);
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, 0);
|
||||
litest_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
|
||||
litest_log_group("P2 is unloaded, expect BTN_SIDE") {
|
||||
litest_button_click_debounced(device, li, BTN_SIDE, 1);
|
||||
litest_button_click_debounced(device, li, BTN_SIDE, 0);
|
||||
litest_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_SIDE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_SIDE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
enum when {
|
||||
DEVICE_NEW,
|
||||
FIRST_FRAME,
|
||||
|
|
@ -1268,10 +1110,6 @@ TEST_COLLECTION(lua)
|
|||
litest_add_parametrized_no_device(lua_append_prepend_frame, params);
|
||||
}
|
||||
|
||||
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)) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue