summaryrefslogtreecommitdiffstats
path: root/extensions/hibernate-status/extension.js
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/hibernate-status/extension.js')
-rw-r--r--extensions/hibernate-status/extension.js248
1 files changed, 248 insertions, 0 deletions
diff --git a/extensions/hibernate-status/extension.js b/extensions/hibernate-status/extension.js
new file mode 100644
index 0000000..6e0b248
--- /dev/null
+++ b/extensions/hibernate-status/extension.js
@@ -0,0 +1,248 @@
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Mainloop = imports.mainloop;
+
+const ExtensionUtils = imports.misc.extensionUtils;
+const LoginManager = imports.misc.loginManager;
+const Main = imports.ui.main;
+const StatusSystem = imports.ui.status.system;
+const PopupMenu = imports.ui.popupMenu;
+const Me = imports.misc.extensionUtils.getCurrentExtension();
+const ExtensionSystem = imports.ui.extensionSystem;
+const ConfirmDialog = Me.imports.confirmDialog;
+const Prefs = new Me.imports.prefs.Prefs();
+
+
+// Use __ () and N__() for the extension gettext domain, and reuse
+// the shell domain with the default _() and N_()
+const Gettext = imports.gettext.domain('hibernate-status-button');
+const __ = Gettext.gettext;
+const N__ = function(e) { return e };
+ExtensionUtils.initTranslations('hibernate-status-button');
+
+const HIBERNATE_CHECK_TIMEOUT = 20000;
+
+class Extension {
+ _loginManagerCanHibernate(asyncCallback) {
+ if (this._loginManager._proxy) {
+ // systemd path
+ this._loginManager._proxy.call("CanHibernate",
+ null,
+ Gio.DBusCallFlags.NONE,
+ -1, null, function (proxy, asyncResult) {
+ let result, error;
+
+ try {
+ result = proxy.call_finish(asyncResult).deep_unpack();
+ } catch (e) {
+ error = e;
+ }
+
+ if (error)
+ asyncCallback(false);
+ else
+ asyncCallback(result[0] != 'no');
+ });
+ } else {
+ Mainloop.idle_add(() => {
+ asyncCallback(false);
+ return false;
+ });
+ }
+ }
+
+ _loginManagerHibernate() {
+ if (Prefs.getHibernateWorksCheckEnabled()) {
+ this._hibernateStarted = new Date();
+ GLib.timeout_add(GLib.PRIORITY_DEFAULT, HIBERNATE_CHECK_TIMEOUT,
+ () => this._checkDidHibernate());
+ }
+ if (this._loginManager._proxy) {
+ // systemd path
+ this._loginManager._proxy.call("Hibernate",
+ GLib.Variant.new('(b)', [true]),
+ Gio.DBusCallFlags.NONE,
+ -1, null, null);
+ } else {
+ // Can't do in ConsoleKit
+ this._loginManager.emit('prepare-for-sleep', true);
+ this._loginManager.emit('prepare-for-sleep', false);
+ }
+ }
+
+ _loginManagerCanHybridSleep(asyncCallback) {
+ if (this._loginManager._proxy) {
+ // systemd path
+ this._loginManager._proxy.call("CanHybridSleep",
+ null,
+ Gio.DBusCallFlags.NONE,
+ -1, null, function (proxy, asyncResult) {
+ let result, error;
+
+ try {
+ result = proxy.call_finish(asyncResult).deep_unpack();
+ } catch (e) {
+ error = e;
+ }
+
+ if (error)
+ asyncCallback(false);
+ else
+ asyncCallback(result[0] != 'no');
+ });
+ } else {
+ Mainloop.idle_add(() => {
+ asyncCallback(false);
+ return false;
+ });
+ }
+ }
+
+ _loginManagerHybridSleep() {
+ if (this._loginManager._proxy) {
+ // systemd path
+ this._loginManager._proxy.call("HybridSleep",
+ GLib.Variant.new('(b)', [true]),
+ Gio.DBusCallFlags.NONE,
+ -1, null, null);
+ } else {
+ // Can't do in ConsoleKit
+ this._loginManager.emit('prepare-for-sleep', true);
+ this._loginManager.emit('prepare-for-sleep', false);
+ }
+ }
+ _updateHaveHibernate() {
+ this._loginManagerCanHibernate((result) => {
+ log(`have hibernate ${result}`);
+ this._haveHibernate = result;
+ this._updateHibernate();
+ });
+ }
+
+ _updateHibernate() {
+ this._hibernateMenuItem.visible = this._haveHibernate && !Main.sessionMode.isLocked;
+ }
+
+ _updateHaveHybridSleep() {
+ this._loginManagerCanHybridSleep((result) => {
+ this._haveHybridSleep = result;
+ this._updateHybridSleep();
+ });
+ }
+
+ _updateHybridSleep() {
+ this._hybridSleepMenuItem.visible = this._haveHybridSleep && !Main.sessionMode.isLocked;
+ }
+
+ _onHibernateClicked() {
+ this.systemMenu._systemItem.menu.itemActivated();
+ this._dialog = new ConfirmDialog.ConfirmDialog(ConfirmDialog.HibernateDialogContent);
+ this._dialog.connect('ConfirmedHibernate', () => this._loginManagerHibernate());
+ this._dialog.open();
+ }
+
+ _onHybridSleepClicked() {
+ this.systemMenu._systemItem.menu.itemActivated();
+ this._loginManagerHybridSleep();
+ }
+
+ _disableExtension() {
+ let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY);
+ enabledExtensions.splice(enabledExtensions.indexOf(Me.uuid), 1);
+ global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions);
+ }
+
+ _cancelDisableExtension(notAgain) {
+ if (notAgain)
+ Prefs.setHibernateWorksCheckEnabled(false);
+ }
+
+ _checkRequirements() {
+ if (!LoginManager.haveSystemd()) {
+ this._dialog = new ConfirmDialog.ConfirmDialog(ConfirmDialog.SystemdMissingDialogContent);
+ this._dialog.connect('DisableExtension', this._disableExtension);
+ this._dialog.open();
+ }
+ }
+
+ _checkDidHibernate() {
+ /* This function is called HIBERNATE_CHECK_TIMEOUT ms after
+ * hibernate started. If it is successful, at that point the GS
+ * process is already frozen; so when this function is actually
+ * called, way more than HIBERNATE_CHECK_TIMEOUT ms are passed*/
+ if (new Date() - this._hibernateStarted > HIBERNATE_CHECK_TIMEOUT + 5000) {
+ // hibernate succeeded
+ return;
+ }
+ // hibernate failed
+ this._dialog = new ConfirmDialog.ConfirmDialog(ConfirmDialog.HibernateFailedDialogContent);
+ this._dialog.connect('DisableExtension', this._disableExtension);
+ this._dialog.connect('Cancel', this._cancelDisableExtension);
+ this._dialog.open();
+ }
+
+ enable() {
+ this._checkRequirements();
+ this._loginManager = LoginManager.getLoginManager();
+ this.systemMenu = Main.panel.statusArea.quickSettings._system;
+
+ this._hibernateMenuItem = new PopupMenu.PopupMenuItem(__('Hibernate'));
+ this._hibernateMenuItemId = this._hibernateMenuItem.connect('activate', () => this._onHibernateClicked());
+
+ this._hybridSleepMenuItem = new PopupMenu.PopupMenuItem(__('Hybrid Sleep'));
+ this._hybridSleepMenuItemId = this._hybridSleepMenuItem.connect('activate', () => this._onHybridSleepClicked());
+
+ let afterSuspendPosition = this.systemMenu._systemItem.menu.numMenuItems - 5;
+
+ this.systemMenu._systemItem.menu.addMenuItem(this._hybridSleepMenuItem, afterSuspendPosition);
+ this.systemMenu._systemItem.menu.addMenuItem(this._hibernateMenuItem, afterSuspendPosition);
+
+ this._menuOpenStateChangedId = this.systemMenu._systemItem.menu.connect('open-state-changed',
+ (menu, open) => {
+ if (!open)
+ return;
+ this._updateHaveHibernate();
+ this._updateHaveHybridSleep();
+ });
+ }
+
+ disable() {
+ if (this._menuOpenStateChangedId) {
+ this.systemMenu._systemItem.menu.disconnect(this._menuOpenStateChangedId);
+ this._menuOpenStateChangedId = 0;
+ }
+
+ if (this._hybridSleepMenuItemId) {
+ this._hybridSleepMenuItem.disconnect(this._hybridSleepMenuItemId);
+ this._hybridSleepMenuItemId = 0;
+ }
+
+ if (this._hibernateMenuItemId) {
+ this._hibernateMenuItem.disconnect(this._hibernateMenuItemId);
+ this._hibernateMenuItemId = 0;
+ }
+
+ if (this._hybridSleepMenuItem) {
+ this._hybridSleepMenuItem.destroy();
+ this._hybridSleepMenuItem = 0;
+ }
+
+ if (this._hibernateMenuItem) {
+ this._hibernateMenuItem.destroy();
+ this._hibernateMenuItem = 0;
+ }
+ }
+}
+
+let extension;
+function init() {
+ extension = new Extension();
+}
+
+function enable() {
+ extension.enable();
+}
+
+function disable() {
+ extension.disable();
+}