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: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1350>
This commit is contained in:
Peter Hutterer 2025-10-27 15:29:37 +10:00
parent 6b9dbc2a25
commit f18bf988f7
6 changed files with 82 additions and 91 deletions

View file

@ -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() <https://www.lua.org/manual/5.4/manual.html#pdf-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

View file

@ -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)

View file

@ -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.

View file

@ -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

View file

@ -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 */

View file

@ -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,