Question

I would like to write a gnome-shell extension, which involves some dbus calling in gjs.

I have learned that Gio.DBus is the right module to use, but I failed to make it run correctly. To demonstrate what I mean, I prepared the following "incorrect" code, which attempts to call the ListNames method in org.freedesktop.DBus interface. I didn't see any output when I run this incorrect code.

Incorrect code:

const Gio = imports.gi.Gio;

const DBusDaemonIface = <interface name='org.freedesktop.DBus'>
    <method name='ListNames'>
        <arg type='as' direction='out'/>
    </method>
</interface>;

const DBusDaemonProxy = Gio.DBusProxy.makeProxyWrapper(DBusDaemonIface);

let main = function () {
    var gdbusProxy = new DBusDaemonProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
    gdbusProxy.ListNamesRemote(function(result, error){ print(result); });
};

main();

For comparison, the following code works. The difference I made is to define a TestApp class which extends Gio.Application, which gets instantiated in the main() function.

Correct code:

const Gio = imports.gi.Gio;
const Lang = imports.lang;

const DBusDaemonIface = <interface name='org.freedesktop.DBus'>
    <method name='ListNames'>
        <arg type='as' direction='out'/>
    </method>
</interface>;

const DBusDaemonProxy = Gio.DBusProxy.makeProxyWrapper(DBusDaemonIface);

TestApp = new Lang.Class({
    Name: 'TestApp',
    Extends: Gio.Application,

    _init: function() {
        this.parent({application_id: 'testapp_id',
            flags: Gio.ApplicationFlags.NON_UNIQUE });

        this._gdbusProxy = new DBusDaemonProxy(Gio.DBus.session,
            'org.freedesktop.DBus', '/org/freedesktop/DBus');
    this._gdbusProxy.ListNamesRemote(Lang.bind(this, this._listNames));
    },

    _listNames: function(result, error) {
    print(result);
    },

    vfunc_activate: function() {
        this.hold();
    },

});

let main = function () {
    let app = new TestApp();
    return app.run(ARGV);
};

main();

So my guess is to make GDBus work, you need a Gio.Application to run? This could be a very stupid question, because I have zero experience programming for GNOME. Thanks.

Was it helpful?

Solution

The code is fine except you don't have a main loop running, so the app just exits before the ListNamesRemote callback has time to run. app.run(ARGV) will give you a mainloop but you can do it with plain GLib as well:

const GLib = imports.gi.GLib;

// ... then in the end of your main() function:
var main_loop = new GLib.MainLoop(null, true);
main_loop.run();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top