0

I'm trying to develop an extension for gnome, that allows me to inhibit system sleep when the lid is closed directly from the status bar without having to open tweaks.

Till now, I have a basic js script that successfully connect to the gdbus and is able to execute commands, but I can't get the inhibitor working. I believe the problem is I'm not handling the file descriptor that the inhibit function returns in the right way, because the documentation says the inhibitor is kept in place only while the file descriptor is referenced and open. But it's also possible that I'm not calling the function correctly.

If anyone could give me some advise I'd be really thankful. I'm running Ubuntu 18.04.4 and gnome 3.28.2

/* -*- mode: js2 - indent-tabs-mode: nil - js2-basic-offset: 4 -*- */
/*jshint multistr:true */
/*jshint esnext:true */
/*global imports: true */
/*global global: true */
/*global log: true */
'use strict';

const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Mainloop = imports.mainloop;
const Atk = imports.gi.Atk;


const DBusInterface = '<node>\
  <interface name="org.freedesktop.login1.Manager">\
    <method name="Inhibit">\
        <arg type="s" direction="in" />\
        <arg type="s" direction="in" />\
        <arg type="s" direction="in" />\
        <arg type="s" direction="in" />\
        <arg type="h" direction="out" />\
    </method>\
    <method name="ListInhibitors">\
      <arg type="a(ssssuu)" direction="out" />\
  </method>\
  </interface>\
</node>';

const DBusProxy = Gio.DBusProxy.makeProxyWrapper(DBusInterface);
let proxy = new DBusProxy(
    Gio.DBus.system,
    "org.freedesktop.login1",
    "/org/freedesktop/login1"
);

let inhibitors = proxy.ListInhibitorsSync();
print(inhibitors);


let fd = proxy.InhibitSync('handle-lid-switch',
                          'gnome-extension-lid-inhibitor',
                          'user preference',
                          'block');

inhibitors = proxy.ListInhibitorsSync();
print(inhibitors);

let loop = new GLib.MainLoop(null, false);
loop.run();

1 Answer 1

0

Ok, I was right that the FD was being closed at function end, releasing the inhibit. I couldn't find a way to keep the FD open, but I was able to keep the function running using it asynchronously.

Next step is to integrate this into my extension.

This is the the new code:

/*jshint multistr:true */
/*jshint esnext:true */
/*global imports: true */
/*global global: true */
/*global log: true */
'use strict';

const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Mainloop = imports.mainloop;
const Atk = imports.gi.Atk;


const DBusInterface = '<node>\
  <interface name="org.freedesktop.login1.Manager">\
    <method name="Inhibit">\
        <arg type="s" direction="in" />\
        <arg type="s" direction="in" />\
        <arg type="s" direction="in" />\
        <arg type="s" direction="in" />\
        <arg type="h" direction="out" />\
    </method>\
    </interface>\
  </node>';

const DBusProxy = Gio.DBusProxy.makeProxyWrapper(DBusInterface);
let proxy = new DBusProxy(
    Gio.DBus.system,
    "org.freedesktop.login1",
    "/org/freedesktop/login1"
);

var inhibitor = {loop:''};

/* Inhibit remote starts the inhibitor asynchronously and locks itself with
   a GLib.MainLoop assigned to inhibitor.loop.
   To release the inhibit just quit the loop at inhibitor.loop
*/
proxy.InhibitRemote('handle-lid-switch', 'lidsleep-inhibitor',
                    'el diego de la gente lo quiere', 'block',
                    (fileDescriptor) => {

                        if (fileDescriptor) {
                            let loop = new GLib.MainLoop(null, false);
                            inhibitor.loop = loop;
                            log("Inhibitor added to array");
                            loop.run();
                            log("Shutting down completed");
                            return;
                        }
                        else {
                            logError("Inhibit returned null");
                            return;
                        }
                    });


/* A ten second timer function */
Promise.timeoutSeconds = function(priority = GLib.PRIORITY_DEFAULT, interval = 10) {
    return new Promise(resolve => GLib.timeout_add_seconds(priority, interval, resolve));
};

/* A function that calls a timer and wait for it to finish. Then, if the arg
   cont is true it releases the inhibit and return false. Otherwise it quits  
   the main loop.
*/
async function asyncCall(cont) {
    try {
      log('Waiting 10 sec');
      await Promise.timeoutSeconds();
      if (cont){
        log('10 sec completed, inhibitor shut down starting');
        inhibitor.loop.quit();
        return !cont;
      } else {
        log('Quitting main loop');
        loop.quit();
        return;
      }
  } catch (e) {
      throw e;
  }
}


let loop = new GLib.MainLoop(null, false);

/* asyncCall is called twice.
   The first run releases the inhibit.
   The second run quits the main loop.
*/
asyncCall(true).
  then(asyncCall);

log("Starting main loop");
loop.run();

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .