From f18bf988f764a159fea3d603f33e2a7e4dd15967 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 27 Oct 2025 15:29:37 +1000 Subject: [PATCH] lua: drop the log global in favor of libinput:log_* The existence of the log global was in part due to early (pre-merge) versions of the Lua plugins supporting multiple libinput plugin objects per file. This is no longer the case and integrating the log functions into the (single) libinput object makes the code more obvious (we're calling libinput:log_debug() now, so it's obviously a libinput log function) and we no longer mix dot with colon notations. Part-of: --- doc/user/lua-plugins.rst | 45 +++++++++------------ plugins/10-disable-feature.lua | 2 +- plugins/10-dwt.lua | 6 +-- plugins/10-example.lua | 2 +- src/libinput-plugin-lua.c | 74 +++++++++++++++++----------------- test/test-plugins-lua.c | 44 ++++++++++---------- 6 files changed, 82 insertions(+), 91 deletions(-) diff --git a/doc/user/lua-plugins.rst b/doc/user/lua-plugins.rst index 3e5b84c3..ba5a62fd 100644 --- a/doc/user/lua-plugins.rst +++ b/doc/user/lua-plugins.rst @@ -244,32 +244,6 @@ See :ref:`plugins_api_evdev_global` for a list of known usages. events can be added to a single frame. This limit should never be hit by valid plugins. -.. _plugins_api_logglobal: - -................................................................................ -The ``log`` global -................................................................................ - -The ``log`` global is used to log messages from the plugin through libinput. -Whether a message is displayed in the log depends on libinput's log priority, -set by the caller. - -.. function:: log.debug(message) - - Log a debug message. - -.. function:: log.info(message) - - Log an info message. - -.. function:: log.error(message) - - Log an error message. - -A compositor may disable stdout and stderr. Log messages should be preferred -over Lua's ``print()`` function to ensure the messages end up in the same -location as other libinput log messages and are not discarded. - .. _plugins_api_libinputglobal: ................................................................................ @@ -312,6 +286,25 @@ All libinput-specific APIs can be accessed through the ``libinput`` object. in your plugin, it is effectively equivalent to Lua's `os.exit() `_. +.. function:: libinput::log_debug(message) + + Log a message at the libinput debug log priority. See + ``libinput::log_error()`` for details. + +.. function:: libinput::log_info(message) + + Log a message at the libinput info log priority. See + ``libinput::log_error()`` for details. + +.. function:: libinput::log_error(message) + + Log a message at the libinput error log priority. Whether a message is + displayed in the log depends on libinput's log priority, set by the caller. + + A compositor may disable stdout and stderr. Log messages should be preferred + over Lua's ``print()`` function to ensure the messages end up in the same + location as other libinput log messages and are not discarded. + .. function:: libinput:now() Returns the current time in microseconds in ``CLOCK_MONOTONIC``. This is diff --git a/plugins/10-disable-feature.lua b/plugins/10-disable-feature.lua index 4ea16ec4..2f723003 100644 --- a/plugins/10-disable-feature.lua +++ b/plugins/10-disable-feature.lua @@ -10,7 +10,7 @@ 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()) + libinput:log_info("Disabling palm detection on " .. device:name()) device:disable_feature("touchpad-palm-detection") end end) diff --git a/plugins/10-dwt.lua b/plugins/10-dwt.lua index 7d81864c..3be7b704 100644 --- a/plugins/10-dwt.lua +++ b/plugins/10-dwt.lua @@ -14,7 +14,7 @@ tp_enabled = true libinput:connect("timer-expired", function(now) - log.debug("touchpad enabled") + libinput:log_debug("touchpad enabled") tp_enabled = true end) @@ -24,12 +24,12 @@ libinput:connect("new-evdev-device", function (device) device:connect("evdev-frame", function (device, frame, timestamp) libinput:timer_set_relative(2000000) if tp_enabled then - log.debug("touchpad disabled") + libinput:log_debug("touchpad disabled") tp_enabled = false end end) elseif props.ID_INPUT_TOUCHPAD then - log.debug("Touchpad detected: " .. device:name()) + libinput:log_debug("Touchpad detected: " .. device:name()) device:connect("evdev-frame", function (device, frame, timestamp) if not tp_enabled then -- Returning an empty table discards the event. diff --git a/plugins/10-example.lua b/plugins/10-example.lua index 9fe7c6ba..957cfc96 100644 --- a/plugins/10-example.lua +++ b/plugins/10-example.lua @@ -70,7 +70,7 @@ function device_new(device) -- If this is empty we know libinput will ignore this device anyway local udev_info = device:udev_properties() for k, v in pairs(udev_info) do - log.debug(k .. "=" .. v) + libinput:log_debug(k .. "=" .. v) end end diff --git a/src/libinput-plugin-lua.c b/src/libinput-plugin-lua.c index 20ddc22e..1f7d8b76 100644 --- a/src/libinput-plugin-lua.c +++ b/src/libinput-plugin-lua.c @@ -625,6 +625,39 @@ libinputplugin_timer_cancel(lua_State *L) return 0; } +static int +libinputplugin_log(lua_State *L, enum libinput_log_priority pri) +{ + LibinputPlugin *p = luaL_checkudata(L, 1, PLUGIN_METATABLE); + luaL_argcheck(L, p != NULL, 1, PLUGIN_METATABLE " expected"); + + const char *message = luaL_checkstring(L, 2); + + auto plugin = lua_get_libinput_lua_plugin(L); + + plugin_log_msg(plugin->parent, pri, "%s\n", message); + + return 0; +} + +static int +libinputplugin_log_debug(lua_State *L) +{ + return libinputplugin_log(L, LIBINPUT_LOG_PRIORITY_DEBUG); +} + +static int +libinputplugin_log_info(lua_State *L) +{ + return libinputplugin_log(L, LIBINPUT_LOG_PRIORITY_INFO); +} + +static int +libinputplugin_log_error(lua_State *L) +{ + return libinputplugin_log(L, LIBINPUT_LOG_PRIORITY_ERROR); +} + static const struct luaL_Reg libinputplugin_vtable[] = { { "now", libinputplugin_now }, { "version", libinputplugin_version }, @@ -634,6 +667,9 @@ static const struct luaL_Reg libinputplugin_vtable[] = { { "timer_cancel", libinputplugin_timer_cancel }, { "timer_set_absolute", libinputplugin_timer_set_absolute }, { "timer_set_relative", libinputplugin_timer_set_relative }, + { "log_debug", libinputplugin_log_debug }, + { "log_info", libinputplugin_log_info }, + { "log_error", libinputplugin_log_error }, { "__gc", libinputplugin_gc }, { NULL, NULL } }; @@ -1048,42 +1084,6 @@ evdevdevice_init(lua_State *L) luaL_setfuncs(L, evdevdevice_vtable, 0); } -static int -logfunc(lua_State *L, enum libinput_log_priority pri) -{ - auto plugin = lua_get_libinput_lua_plugin(L); - - const char *message = luaL_checkstring(L, 1); - - plugin_log_msg(plugin->parent, pri, "%s\n", message); - - return 0; -} - -static int -log_lua_error(lua_State *L) -{ - return logfunc(L, LIBINPUT_LOG_PRIORITY_ERROR); -} - -static int -log_lua_info(lua_State *L) -{ - return logfunc(L, LIBINPUT_LOG_PRIORITY_INFO); -} - -static int -log_lua_debug(lua_State *L) -{ - return logfunc(L, LIBINPUT_LOG_PRIORITY_DEBUG); -} - -/* Exposes log.debug, log.info, log.error() */ -static const struct luaL_Reg log_funcs[] = { { "debug", log_lua_debug }, - { "info", log_lua_info }, - { "error", log_lua_error }, - { NULL, NULL } }; - static void libinput_lua_plugin_destroy(struct libinput_lua_plugin *plugin) { @@ -1255,8 +1255,6 @@ libinput_lua_plugin_init_lua(struct libinput *libinput, /* Our globals */ lua_newtable(L); - luaL_register(L, "log", log_funcs); - lua_setfield(L, sandbox_table_idx, "log"); libinput_lua_init_evdev_global(L, sandbox_table_idx); /* The libinput global object */ diff --git a/test/test-plugins-lua.c b/test/test-plugins-lua.c index 32dbe4b1..1ae5a37d 100644 --- a/test/test-plugins-lua.c +++ b/test/test-plugins-lua.c @@ -163,8 +163,8 @@ START_TEST(lua_unregister_is_last) _destroy_(tmpdir) *tmpdir = tmpdir_create(NULL); _autofree_ char *lua = strdup_printf( "libinput:register({1})\n" - "libinput:connect(\"new-evdev-device\", function(device)\n %s\n log.error(\"abort abort\")\nend)\n" - "%slog.error(\"must not happen\")", + "libinput:connect(\"new-evdev-device\", function(device)\n %s\n libinput:log_error(\"abort abort\")\nend)\n" + "%slibinput:log_error(\"must not happen\")", streq(when, "connect") ? "libinput:unregister()" : "", streq(when, "run") ? "libinput:unregister()\n" : "--"); _autofree_ char *path = litest_write_plugin(tmpdir->path, lua); @@ -181,7 +181,7 @@ START_TEST(lua_unregister_is_last) } END_TEST -START_TEST(lua_test_log_global) +START_TEST(lua_test_logging) { _destroy_(tmpdir) *tmpdir = tmpdir_create(NULL); @@ -191,13 +191,13 @@ START_TEST(lua_test_log_global) const char *lua = NULL; switch (priority) { case LIBINPUT_LOG_PRIORITY_DEBUG: - lua = "log.debug(\"deb-ug\");"; + lua = "libinput:log_debug(\"deb-ug\");"; break; case LIBINPUT_LOG_PRIORITY_INFO: - lua = "log.info(\"inf-o\");"; + lua = "libinput:log_info(\"inf-o\");"; break; case LIBINPUT_LOG_PRIORITY_ERROR: - lua = "log.error(\"err-or\");"; + lua = "libinput:log_error(\"err-or\");"; break; default: litest_assert_not_reached(); @@ -268,7 +268,7 @@ END_TEST START_TEST(lua_test_libinput_now) { _destroy_(tmpdir) *tmpdir = tmpdir_create(NULL); - const char *lua = "log.error(\">>>\" .. libinput:now())"; + const char *lua = "libinput:log_error(\">>>\" .. libinput:now())"; _autofree_ char *path = litest_write_plugin(tmpdir->path, lua); _litest_context_destroy_ struct libinput *li = litest_create_context_with_plugindir(tmpdir->path); @@ -318,7 +318,7 @@ START_TEST(lua_test_libinput_timer) "libinput:register({1})\n" "libinput:connect(\"timer-expired\",\n" " function(t)\n" - " log.error(\">>>\" .. t)\n" + " libinput:log_error(\">>>\" .. t)\n" " %s\n" " end)\n" "libinput:timer_set_%s(%s)\n", @@ -394,10 +394,10 @@ START_TEST(lua_bad_connect) func = "a"; break; case TOO_FEW_ARGS: - func = "function(p) log.debug(\"few\"); end"; + func = "function(p) libinput:log_debug(\"few\"); end"; break; case TOO_MANY_ARGS: - func = "function(p, a, b) log.debug(\"many\"); end"; + func = "function(p, a, b) libinput:log_debug(\"many\"); end"; break; } @@ -437,7 +437,7 @@ START_TEST(lua_register_multiversions) _destroy_(tmpdir) *tmpdir = tmpdir_create(NULL); const char *lua = - "v = libinput:register({1, 3, 4, 10, 15})\nlog.info(\"VERSION:\" .. v)\n"; + "v = libinput:register({1, 3, 4, 10, 15})\nlibinput:log_info(\"VERSION:\" .. v)\n"; _autofree_ char *path = litest_write_plugin(tmpdir->path, lua); _litest_context_destroy_ struct libinput *li = litest_create_context_with_plugindir(tmpdir->path); @@ -526,9 +526,9 @@ START_TEST(lua_frame_handler) const char *lua = "libinput:register({1})\n" "function frame_handler(_, frame, timestamp)\n" - " log.info(\"T:\" .. timestamp)\n" + " libinput:log_info(\"T:\" .. timestamp)\n" " for _, e in ipairs(frame) do\n" - " log.info(\"E:\" .. e.usage .. \":\" .. e.value)\n" + " libinput:log_info(\"E:\" .. e.usage .. \":\" .. e.value)\n" " end\n" "end\n" "libinput:connect(\"new-evdev-device\", function(device) device:connect(\"evdev-frame\", frame_handler) end)\n"; @@ -593,9 +593,9 @@ START_TEST(lua_device_info) "libinput:register({1})\n" "function info_printer(device)\n" " local info = device:info()\n" - " log.info(\"BUS:\" .. info.bustype)\n" - " log.info(\"VID:\" .. info.vid)\n" - " log.info(\"PID:\" .. info.pid)\n" + " libinput:log_info(\"BUS:\" .. info.bustype)\n" + " libinput:log_info(\"VID:\" .. info.vid)\n" + " libinput:log_info(\"PID:\" .. info.pid)\n" "end\n" "libinput:connect(\"new-evdev-device\", info_printer)\n"; @@ -628,7 +628,7 @@ START_TEST(lua_set_absinfo) "function absinfo_setter(device)\n" " local absinfos = device:absinfos()\n" " for u, a in pairs(absinfos) do\n" - " log.info(\"A:\" .. u .. \":\" .. a.minimum .. \":\" .. a.maximum .. \":\" .. a.resolution .. \":\" .. a.fuzz .. \":\" .. a.flat)\n" + " libinput:log_info(\"A:\" .. u .. \":\" .. a.minimum .. \":\" .. a.maximum .. \":\" .. a.resolution .. \":\" .. a.fuzz .. \":\" .. a.flat)\n" " end\n" " device:set_absinfo(evdev.ABS_X, { minimum = 0, maximum = 1000, resolution = 100 })\n" " device:set_absinfo(evdev.ABS_Y, { minimum = 0, maximum = 200, resolution = 10 })\n" @@ -711,13 +711,13 @@ START_TEST(lua_enable_disable_evdev_usage) const char *lua2 = "libinput:register({1})\n" "function frame_handler(_, frame, timestamp)\n" - " log.info(\"frame\")\n" + " libinput:log_info(\"frame\")\n" " for _, e in ipairs(frame) do\n" - " log.info(\"E:\" .. e.usage .. \":\" .. e.value)\n" + " libinput:log_info(\"E:\" .. e.usage .. \":\" .. e.value)\n" " end\n" "end\n" "function f(device)\n" - " log.info(\"F: \" .. device:name())\n" + " libinput:log_info(\"F: \" .. device:name())\n" " device:connect(\"evdev-frame\", frame_handler)\n" "end\n" "libinput:connect(\"new-evdev-device\", f)\n"; @@ -768,7 +768,7 @@ START_TEST(lua_udev_properties) "function prop_printer(device)\n" " local properties = device:udev_properties()\n" " for k, v in pairs(properties) do\n" - " log.info(k .. \"=\" .. v)\n" + " libinput:log_info(k .. \"=\" .. v)\n" " end\n" "end\n" "libinput:connect(\"new-evdev-device\", prop_printer)\n"; @@ -1076,7 +1076,7 @@ TEST_COLLECTION(lua) litest_named_i32(LIBINPUT_LOG_PRIORITY_DEBUG), litest_named_i32(LIBINPUT_LOG_PRIORITY_INFO), litest_named_i32(LIBINPUT_LOG_PRIORITY_ERROR)) { - litest_add_parametrized_no_device(lua_test_log_global, params); + litest_add_parametrized_no_device(lua_test_logging, params); } litest_with_parameters(params,