diff --git a/js/ui/main.js b/js/ui/main.js index eebc2b502..fcffbf7cc 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -137,8 +137,10 @@ function start() { ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager(); overview = new Overview.Overview(); magnifier = new Magnifier.Magnifier(); - screenShield = new ScreenShield.ScreenShield(); - screenSaverDBus = new ShellDBus.ScreenSaverDBus(); + if (UnlockDialog.isSupported()) + screenShield = new ScreenShield.ScreenShield(); + else + screenShield = new ScreenShield.ScreenShieldFallback(); panel = new Panel.Panel(); wm = new WindowManager.WindowManager(); messageTray = new MessageTray.MessageTray(); diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js index ba4afeb1c..c2e7cb651 100644 --- a/js/ui/screenShield.js +++ b/js/ui/screenShield.js @@ -19,6 +19,7 @@ const Lightbox = imports.ui.lightbox; const Main = imports.ui.main; const Overview = imports.ui.overview; const MessageTray = imports.ui.messageTray; +const ShellDBus = imports.ui.shellDBus; const Tweener = imports.ui.tweener; const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver'; @@ -415,6 +416,8 @@ const ScreenShield = new Lang.Class({ this._onStatusChanged(status); })); + this._screenSaverDBus = new ShellDBus.ScreenSaverDBus(this); + this._loginManager = LoginManager.getLoginManager(); this._loginSession = this._loginManager.getCurrentSessionProxy(); this._loginSession.connectSignal('Lock', Lang.bind(this, function() { this.lock(false); })); @@ -827,3 +830,60 @@ const ScreenShield = new Lang.Class({ }, }); Signals.addSignalMethods(ScreenShield.prototype); + +/* Fallback code to handle session locking using gnome-screensaver, + in case the required GDM dependency is not there +*/ +const ScreenShieldFallback = new Lang.Class({ + Name: 'ScreenShieldFallback', + + _init: function() { + this._proxy = new Gio.DBusProxy({ g_connection: Gio.DBus.session, + g_name: 'org.gnome.ScreenSaver', + g_object_path: '/org/gnome/ScreenSaver', + g_interface_name: 'org.gnome.ScreenSaver', + g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START | + Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES), + }); + this._proxy.init(null); + + this._proxy.connect('g-signal', Lang.bind(this, this._onSignal)); + this._proxy.connect('notify::g-name-owner', Lang.bind(this, this._onNameOwnerChanged)); + }, + + _onNameOwnerChanged: function(object, pspec) { + if (this._proxy.g_name_owner) + [this._locked] = this._proxy.call_sync('GetActive', null, + Gio.DBusCallFlags.NONE, -1, null).deep_unpack(); + else + this._locked = false; + + this.emit('lock-status-changed', this._locked); + }, + + _onSignal: function(proxy, senderName, signalName, params) { + if (signalName == 'ActiveChanged') { + [this._locked] = params.deep_unpack(); + this.emit('lock-status-changed', this._locked); + } + }, + + get locked() { + return this._locked; + }, + + lock: function() { + this._proxy.call('Lock', null, Gio.DBusCallFlags.NONE, -1, null, + Lang.bind(this, function(proxy, result) { + proxy.call_finish(result); + + this.emit('lock-screen-shown'); + })); + }, + + unlock: function() { + this._proxy.call('SetActive', GLib.Variant.new('(b)', false), + Gio.DBusCallFlags.NONE, -1, null, null); + }, +}); +Signals.addSignalMethods(ScreenShieldFallback.prototype); diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js index 5a43353fa..0b403be8c 100644 --- a/js/ui/shellDBus.js +++ b/js/ui/shellDBus.js @@ -340,35 +340,38 @@ const GnomeShellExtensions = new Lang.Class({ const ScreenSaverDBus = new Lang.Class({ Name: 'ScreenSaverDBus', - _init: function() { + _init: function(screenShield) { this.parent(); - Main.screenShield.connect('lock-status-changed', Lang.bind(this, function(shield) { + this._screenShield = screenShield; + screenShield.connect('lock-status-changed', Lang.bind(this, function(shield) { this._dbusImpl.emit_signal('ActiveChanged', GLib.Variant.new('(b)', [shield.locked])); })); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenSaverIface, this); this._dbusImpl.export(Gio.DBus.session, '/org/gnome/ScreenSaver'); + + Gio.DBus.session.own_name('org.gnome.ScreenSaver', Gio.BusNameOwnerFlags.REPLACE, null, null); }, LockAsync: function(parameters, invocation) { - let tmpId = Main.screenShield.connect('lock-screen-shown', Lang.bind(this, function() { - Main.screenShield.disconnect(tmpId); + let tmpId = this._screenShield.connect('lock-screen-shown', Lang.bind(this, function() { + this._screenShield.disconnect(tmpId); invocation.return_value(null); })); - Main.screenShield.lock(true); + this._screenShield.lock(true); }, SetActive: function(active) { if (active) - Main.screenShield.lock(true); + this._screenShield.lock(true); else - Main.screenShield.unlock(); + this._screenShield.unlock(); }, GetActive: function() { - return Main.screenShield.locked; + return this._screenShield.locked; } }); diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js index 1ceb35a72..127a924c7 100644 --- a/js/ui/unlockDialog.js +++ b/js/ui/unlockDialog.js @@ -2,7 +2,7 @@ const AccountsService = imports.gi.AccountsService; const Clutter = imports.gi.Clutter; -const Gdm = imports.gi.Gdm; +const Gdm = imports.gi.Gdm; const Gio = imports.gi.Gio; const GLib = imports.gi.GLib; const Gtk = imports.gi.Gtk; @@ -23,6 +23,35 @@ const GdmUtil = imports.gdm.util; // The timeout before going back automatically to the lock screen (in seconds) const IDLE_TIMEOUT = 2 * 60; +function versionCompare(required, reference) { + required = required.split('.'); + reference = reference.split('.'); + + for (let i = 0; i < required.length; i++) { + if (required[i] != reference[i]) + return required[i] < reference[i]; + } + + return true; +} + +function isSupported() { + try { + let params = GLib.Variant.new('(ss)', ['org.gnome.DisplayManager.Manager', 'Version']); + let result = Gio.DBus.system.call_sync('org.gnome.DisplayManager', + '/org/gnome/DisplayManager/Manager', + 'org.freedesktop.DBus.Properties', + 'Get', params, null, + Gio.DBusCallFlags.NONE, + -1, null); + + let version = result.deep_unpack()[0].deep_unpack(); + return versionCompare('3.5.91', version); + } catch(e) { + return false; + } +} + // A widget showing the user avatar and name const UserWidget = new Lang.Class({ Name: 'UserWidget', diff --git a/src/main.c b/src/main.c index c4d2d28c3..ad4fb3ac5 100644 --- a/src/main.c +++ b/src/main.c @@ -34,7 +34,6 @@ extern GType gnome_shell_plugin_get_type (void); #define SHELL_DBUS_SERVICE "org.gnome.Shell" #define MAGNIFIER_DBUS_SERVICE "org.gnome.Magnifier" -#define SCREENSAVER_DBUS_SERVICE "org.gnome.ScreenSaver" #define OVERRIDES_SCHEMA "org.gnome.shell.overrides" @@ -153,8 +152,6 @@ shell_dbus_init (gboolean replace) MAGNIFIER_DBUS_SERVICE, FALSE, /* ...and the org.freedesktop.Notifications service. */ "org.freedesktop.Notifications", FALSE, - /* ...and the org.gnome.ScreenSaver service. */ - SCREENSAVER_DBUS_SERVICE, FALSE, NULL); /* ...and the on-screen keyboard service */ shell_dbus_acquire_name (bus,