如何在Awesome WM中调用dbus方法?

时间:2017-04-24 12:39:11

标签: dbus awesome-wm

我想从Awesome WM向其他应用程序发送dbus消息。但是,Awesome的dbus interfact的文档很简单,我找不到任何例子。怎么做?例如,我想在Inhibit中使用org.freedesktop.login1函数。

1 个答案:

答案 0 :(得分:3)

令人敬畏的内置穷人的DBus包装器几乎不足以支持DBus使其内置的通知守护程序(顽皮)工作:https://github.com/awesomeWM/awesome/blob/259c4f716fbd08b4507ebb4cb4d40fe5cbabed0f/dbus.c#L858-L870

此API允许您实现通过DBus可用的对象并发出信号,但不能调用DBus方法。查看some docs,似乎Inhibit接口是您必须调用的方法。更糟糕的是 - 它返回一个文件描述符!

通过大量阅读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()工作的黑客和围绕一切的Gio.Async.call包装。