Как вызывать методы dbus в Awesome WM?

Я хочу отправлять сообщения dbus другим приложениям из Awesome WM. Однако документация по интерфейсу Awesome dbus довольно минималистична, и я не могу найти никаких примеров. Как это сделать? Например, я хочу использовать функцию Inhibit в org.freedesktop.login1.


person petersohn    schedule 24.04.2017    source источник
comment
Используйте D-Feet, чтобы получить хороший список доступных интерфейсов и их методов, что позволит вам также поиграть с этими методами.   -  person AndreLDM    schedule 24.04.2017


Ответы (1)


Встроенная оболочка DBus для бедных в Awesome едва содержит достаточную поддержку DBus, чтобы его встроенный демон уведомлений (непослушный) работал: c#L858-L870" rel="nofollow noreferrer">https://github.com/awesomeWM/awesome/blob/259c4f716fbd08b4507ebb4cb4d40fe5cbabed0f/dbus.c#L858-L870

Этот API позволяет реализовать объект, доступный через DBus, и генерировать сигналы, но не вызывать методы DBus. Глядя на некоторые документы, кажется, что интерфейс 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 вокруг всего.

person Uli Schlachter    schedule 29.04.2017