8747c0c58d
If screen locking is enabled, the screen shield should drop down on suspend. Currently this is achieved by either explicitly locking the screen (when selecting "Suspend" from the user menu) or by relying on g-s-d delaying the suspension enough time for the shield to get into place (lid close, power button). Systemd inhibitors offer a safer way to ensure that the screen is locked before going to sleep, so add a small abstraction for them in the loginManager - with inhibitors being a systemd-only feature, the ConsoleKit path only has a dummy implementation. https://bugzilla.gnome.org/show_bug.cgi?id=686482
246 lines
7.5 KiB
JavaScript
246 lines
7.5 KiB
JavaScript
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
|
|
const GLib = imports.gi.GLib;
|
|
const Gio = imports.gi.Gio;
|
|
const Lang = imports.lang;
|
|
const Mainloop = imports.mainloop;
|
|
const Shell = imports.gi.Shell;
|
|
const Signals = imports.signals;
|
|
|
|
const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager'>
|
|
<method name='PowerOff'>
|
|
<arg type='b' direction='in'/>
|
|
</method>
|
|
<method name='Reboot'>
|
|
<arg type='b' direction='in'/>
|
|
</method>
|
|
<method name='Suspend'>
|
|
<arg type='b' direction='in'/>
|
|
</method>
|
|
<method name='CanPowerOff'>
|
|
<arg type='s' direction='out'/>
|
|
</method>
|
|
<method name='CanReboot'>
|
|
<arg type='s' direction='out'/>
|
|
</method>
|
|
<method name='CanSuspend'>
|
|
<arg type='s' direction='out'/>
|
|
</method>
|
|
<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>
|
|
<signal name='PrepareForSleep'>
|
|
<arg type='b' direction='out'/>
|
|
</signal>
|
|
</interface>;
|
|
|
|
const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
|
|
<signal name='Lock' />
|
|
<signal name='Unlock' />
|
|
</interface>;
|
|
|
|
const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
|
|
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
|
|
|
|
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'>
|
|
<method name='CanRestart'>
|
|
<arg type='b' direction='out'/>
|
|
</method>
|
|
<method name='CanStop'>
|
|
<arg type='b' direction='out'/>
|
|
</method>
|
|
<method name='Restart' />
|
|
<method name='Stop' />
|
|
<method name='GetCurrentSession'>
|
|
<arg type='o' direction='out' />
|
|
</method>
|
|
</interface>;
|
|
|
|
const ConsoleKitSessionIface = <interface name='org.freedesktop.ConsoleKit.Session'>
|
|
<signal name='Lock' />
|
|
<signal name='Unlock' />
|
|
</interface>;
|
|
|
|
const ConsoleKitSession = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
|
|
const ConsoleKitManager = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
|
|
|
|
function haveSystemd() {
|
|
return GLib.access("/sys/fs/cgroup/systemd", 0) >= 0;
|
|
}
|
|
|
|
let _loginManager = null;
|
|
|
|
/**
|
|
* LoginManager:
|
|
* An abstraction over systemd/logind and ConsoleKit.
|
|
*
|
|
*/
|
|
function getLoginManager() {
|
|
if (_loginManager == null) {
|
|
if (haveSystemd())
|
|
_loginManager = new LoginManagerSystemd();
|
|
else
|
|
_loginManager = new LoginManagerConsoleKit();
|
|
}
|
|
|
|
return _loginManager;
|
|
}
|
|
|
|
const LoginManagerSystemd = new Lang.Class({
|
|
Name: 'LoginManagerSystemd',
|
|
|
|
_init: function() {
|
|
this._proxy = new SystemdLoginManager(Gio.DBus.system,
|
|
'org.freedesktop.login1',
|
|
'/org/freedesktop/login1');
|
|
this._proxy.connectSignal('PrepareForSleep',
|
|
Lang.bind(this, this._prepareForSleep));
|
|
},
|
|
|
|
// Having this function is a bit of a hack since the Systemd and ConsoleKit
|
|
// session objects have different interfaces - but in both cases there are
|
|
// Lock/Unlock signals, and that's all we count upon at the moment.
|
|
getCurrentSessionProxy: function() {
|
|
if (!this._currentSession) {
|
|
this._currentSession = new SystemdLoginSession(Gio.DBus.system,
|
|
'org.freedesktop.login1',
|
|
'/org/freedesktop/login1/session/' +
|
|
GLib.getenv('XDG_SESSION_ID'));
|
|
}
|
|
|
|
return this._currentSession;
|
|
},
|
|
|
|
canPowerOff: function(asyncCallback) {
|
|
this._proxy.CanPowerOffRemote(function(result, error) {
|
|
if (error)
|
|
asyncCallback(false);
|
|
else
|
|
asyncCallback(result[0] != 'no');
|
|
});
|
|
},
|
|
|
|
canReboot: function(asyncCallback) {
|
|
this._proxy.CanRebootRemote(function(result, error) {
|
|
if (error)
|
|
asyncCallback(false);
|
|
else
|
|
asyncCallback(result[0] != 'no');
|
|
});
|
|
},
|
|
|
|
canSuspend: function(asyncCallback) {
|
|
this._proxy.CanSuspendRemote(function(result, error) {
|
|
if (error)
|
|
asyncCallback(false);
|
|
else
|
|
asyncCallback(result[0] != 'no');
|
|
});
|
|
},
|
|
|
|
powerOff: function() {
|
|
this._proxy.PowerOffRemote(true);
|
|
},
|
|
|
|
reboot: function() {
|
|
this._proxy.RebootRemote(true);
|
|
},
|
|
|
|
suspend: function() {
|
|
this._proxy.SuspendRemote(true);
|
|
},
|
|
|
|
inhibit: function(reason, callback) {
|
|
let inVariant = GLib.Variant.new('(ssss)',
|
|
['sleep',
|
|
'GNOME Shell',
|
|
reason,
|
|
'delay']);
|
|
this._proxy.call_with_unix_fd_list('Inhibit', inVariant, 0, -1, null, null,
|
|
Lang.bind(this, function(proxy, result) {
|
|
let fd = -1;
|
|
try {
|
|
let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result);
|
|
fd = fdList.steal_fds(outVariant.deep_unpack())[0];
|
|
callback(new Gio.UnixInputStream({ fd: fd }));
|
|
} catch(e) {
|
|
logError(e, "Error getting systemd inhibitor");
|
|
callback(null);
|
|
}
|
|
}));
|
|
},
|
|
|
|
_prepareForSleep: function(proxy, sender, [aboutToSuspend]) {
|
|
this.emit('prepare-for-sleep', aboutToSuspend);
|
|
}
|
|
});
|
|
Signals.addSignalMethods(LoginManagerSystemd.prototype);
|
|
|
|
const LoginManagerConsoleKit = new Lang.Class({
|
|
Name: 'LoginManagerConsoleKit',
|
|
|
|
_init: function() {
|
|
this._proxy = new ConsoleKitManager(Gio.DBus.system,
|
|
'org.freedesktop.ConsoleKit',
|
|
'/org/freedesktop/ConsoleKit/Manager');
|
|
},
|
|
|
|
// Having this function is a bit of a hack since the Systemd and ConsoleKit
|
|
// session objects have different interfaces - but in both cases there are
|
|
// Lock/Unlock signals, and that's all we count upon at the moment.
|
|
getCurrentSessionProxy: function() {
|
|
if (!this._currentSession) {
|
|
let [currentSessionId] = this._proxy.GetCurrentSessionSync();
|
|
this._currentSession = new ConsoleKitSession(Gio.DBus.system,
|
|
'org.freedesktop.ConsoleKit',
|
|
currentSessionId);
|
|
}
|
|
|
|
return this._currentSession;
|
|
},
|
|
|
|
canPowerOff: function(asyncCallback) {
|
|
this._proxy.CanStopRemote(function(result, error) {
|
|
if (error)
|
|
asyncCallback(false);
|
|
else
|
|
asyncCallback(result[0]);
|
|
});
|
|
},
|
|
|
|
canReboot: function(asyncCallback) {
|
|
this._proxy.CanRestartRemote(function(result, error) {
|
|
if (error)
|
|
asyncCallback(false);
|
|
else
|
|
asyncCallback(result[0]);
|
|
});
|
|
},
|
|
|
|
canSuspend: function(asyncCallback) {
|
|
return false;
|
|
},
|
|
|
|
powerOff: function() {
|
|
this._proxy.StopRemote();
|
|
},
|
|
|
|
reboot: function() {
|
|
this._proxy.RestartRemote();
|
|
},
|
|
|
|
suspend: function() {
|
|
this.emit('prepare-for-sleep', true);
|
|
this.emit('prepare-for-sleep', false);
|
|
},
|
|
|
|
inhibit: function(reason, callback) {
|
|
callback(null);
|
|
}
|
|
});
|
|
Signals.addSignalMethods(LoginManagerConsoleKit.prototype);
|