如何在 Awesome WM 中调用 dbus 方法?
How to call dbus methods in Awesome WM?
我想从 Awesome WM 向其他应用程序发送 dbus 消息。但是,Awesome 的 dbus 接口的文档非常简单,我找不到任何示例。怎么做?比如我想在org.freedesktop.login1
.
中使用Inhibit
函数
Awesome 的内置穷人 DBus 包装器几乎不包含对 DBus 的足够支持以使其内置通知守护程序(顽皮)工作:https://github.com/awesomeWM/awesome/blob/259c4f716fbd08b4507ebb4cb4d40fe5cbabed0f/dbus.c#L858-L870
此 API 允许您通过 DBus 实现可用的对象并发出信号,但不能调用 DBus 方法。查看 some docs,似乎 Inhibit
接口是您必须调用的方法。更糟糕的是 - 它 returns 一个文件描述符!
通过大量阅读 GIO 的文档,我想到了以下(希望不言自明;但也请阅读 https://github.com/pavouk/lgi/blob/master/docs/gio.md)示例:
local lgi = require("lgi")
local Gio = lgi.require("Gio")
local GLib = lgi.require("GLib")
-- Workaround for https://github.com/pavouk/lgi/issues/142
local function bus_get_async(type)
Gio.bus_get(type, nil, coroutine.running())
local a, b = coroutine.yield()
return Gio.bus_get_finish(b)
end
local function inhibit(bus, what, who, why, mode)
local name = "org.freedesktop.login1"
local object = "/org/freedesktop/login1"
local interface = "org.freedesktop.login1.Manager"
local message = Gio.DBusMessage.new_method_call(name, object, interface, "Inhibit")
message:set_body(GLib.Variant("(ssss)",
{ what, who, why, mode }))
local timeout = -1 -- Just use the default
local result, err = bus:async_send_message_with_reply(message, Gio.DBusSendMessageFlags.NONE,
timeout, nil)
if err then
print("error: " .. tostring(err))
return
end
if result:get_message_type() == "ERROR" then
local _, err = result:to_gerror()
print("error: " .. tostring(err))
return
end
local fd_list = result:get_unix_fd_list()
local fd, err = fd_list:get(0)
if err then
print("error: " .. tostring(err))
return
end
-- Now... somehow turn this fd into something we can close
return Gio.UnixInputStream.new(fd, true)
end
Gio.Async.call(function()
local bus = bus_get_async(Gio.BusType.SYSTEM)
local a = inhibit(bus, "shutdown:sleep", "hi, it's me!", "Just because", "delay")
print("got lock")
io.popen("sleep 10"):read("*a")
a:async_close()
-- Speed up deletion of the GDBusMessage that still references the FD
collectgarbage("collect")
collectgarbage("collect")
print("released lock")
io.popen("sleep 10"):read("*a")
end)()
如果需要,您可以将对 async_foo
的调用替换为对 foo_sync
的调用,从而将上述内容变成同步的。这也允许摆脱使 bus_get_async()
工作的 hack 和 Gio.Async.call
包装一切。
我想从 Awesome WM 向其他应用程序发送 dbus 消息。但是,Awesome 的 dbus 接口的文档非常简单,我找不到任何示例。怎么做?比如我想在org.freedesktop.login1
.
Inhibit
函数
Awesome 的内置穷人 DBus 包装器几乎不包含对 DBus 的足够支持以使其内置通知守护程序(顽皮)工作:https://github.com/awesomeWM/awesome/blob/259c4f716fbd08b4507ebb4cb4d40fe5cbabed0f/dbus.c#L858-L870
此 API 允许您通过 DBus 实现可用的对象并发出信号,但不能调用 DBus 方法。查看 some docs,似乎 Inhibit
接口是您必须调用的方法。更糟糕的是 - 它 returns 一个文件描述符!
通过大量阅读 GIO 的文档,我想到了以下(希望不言自明;但也请阅读 https://github.com/pavouk/lgi/blob/master/docs/gio.md)示例:
local lgi = require("lgi")
local Gio = lgi.require("Gio")
local GLib = lgi.require("GLib")
-- Workaround for https://github.com/pavouk/lgi/issues/142
local function bus_get_async(type)
Gio.bus_get(type, nil, coroutine.running())
local a, b = coroutine.yield()
return Gio.bus_get_finish(b)
end
local function inhibit(bus, what, who, why, mode)
local name = "org.freedesktop.login1"
local object = "/org/freedesktop/login1"
local interface = "org.freedesktop.login1.Manager"
local message = Gio.DBusMessage.new_method_call(name, object, interface, "Inhibit")
message:set_body(GLib.Variant("(ssss)",
{ what, who, why, mode }))
local timeout = -1 -- Just use the default
local result, err = bus:async_send_message_with_reply(message, Gio.DBusSendMessageFlags.NONE,
timeout, nil)
if err then
print("error: " .. tostring(err))
return
end
if result:get_message_type() == "ERROR" then
local _, err = result:to_gerror()
print("error: " .. tostring(err))
return
end
local fd_list = result:get_unix_fd_list()
local fd, err = fd_list:get(0)
if err then
print("error: " .. tostring(err))
return
end
-- Now... somehow turn this fd into something we can close
return Gio.UnixInputStream.new(fd, true)
end
Gio.Async.call(function()
local bus = bus_get_async(Gio.BusType.SYSTEM)
local a = inhibit(bus, "shutdown:sleep", "hi, it's me!", "Just because", "delay")
print("got lock")
io.popen("sleep 10"):read("*a")
a:async_close()
-- Speed up deletion of the GDBusMessage that still references the FD
collectgarbage("collect")
collectgarbage("collect")
print("released lock")
io.popen("sleep 10"):read("*a")
end)()
如果需要,您可以将对 async_foo
的调用替换为对 foo_sync
的调用,从而将上述内容变成同步的。这也允许摆脱使 bus_get_async()
工作的 hack 和 Gio.Async.call
包装一切。