From c2b70101f2004307f663908258eef378fb1371d4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 15 Aug 2018 15:03:56 +0200 Subject: [PATCH] endSessionDialog: Support rebooting into the bootloader menu aka ("Boot Options") This implements the "Alt" behavior for the "Reboot" button as outlined in the design here: https://wiki.gnome.org/Design/OS/BootOptions Note I've tried implemeting this with the AltSwitcher class from js/ui/status/system.js first, but that puts the button in a St.Bin() which causes the button to think it is the only button on the dialog and makes it have rounded corners on both of its bottom corners. https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/199 --- js/ui/endSessionDialog.js | 62 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js index cd8aeb55d..b3c6344e8 100644 --- a/js/ui/endSessionDialog.js +++ b/js/ui/endSessionDialog.js @@ -213,6 +213,11 @@ class EndSessionDialog extends ModalDialog.ModalDialog { destroyOnClose: false }); this._loginManager = LoginManager.getLoginManager(); + this._loginManager.canRebootToBootLoaderMenu( + (canRebootToBootLoaderMenu, unusedNeedsAuth) => { + this._canRebootToBootLoaderMenu = canRebootToBootLoaderMenu; + }); + this._userManager = AccountsService.UserManager.get_default(); this._user = this._userManager.get_user(GLib.get_user_name()); this._updatesPermission = null; @@ -239,6 +244,9 @@ class EndSessionDialog extends ModalDialog.ModalDialog { this._totalSecondsToStayOpen = 0; this._applications = []; this._sessions = []; + this._capturedEventId = 0; + this._rebootButton = null; + this._rebootButtonAlt = null; this.connect('destroy', this._onDestroy.bind(this)); @@ -363,6 +371,26 @@ class EndSessionDialog extends ModalDialog.ModalDialog { this._sessionSection.visible = hasSessions; } + _onCapturedEvent(actor, event) { + let altEnabled = false; + + let type = event.type(); + if (type !== Clutter.EventType.KEY_PRESS && type !== Clutter.EventType.KEY_RELEASE) + return Clutter.EVENT_PROPAGATE; + + let key = event.get_key_symbol(); + if (key !== Clutter.KEY_Alt_L && key !== Clutter.KEY_Alt_R) + return Clutter.EVENT_PROPAGATE; + + if (type === Clutter.EventType.KEY_PRESS) + altEnabled = true; + + this._rebootButton.visible = !altEnabled; + this._rebootButtonAlt.visible = altEnabled; + + return Clutter.EVENT_PROPAGATE; + } + _updateButtons() { this.clearButtons(); @@ -384,9 +412,36 @@ class EndSessionDialog extends ModalDialog.ModalDialog { }, label, }); + + // Add Alt "Boot Options" option to the Reboot button + if (this._canRebootToBootLoaderMenu && signal === 'ConfirmedReboot') { + this._rebootButton = button; + this._rebootButtonAlt = this.addButton({ + action: () => { + this.close(true); + let signalId = this.connect('closed', () => { + this.disconnect(signalId); + this._confirmRebootToBootLoaderMenu(); + }); + }, + label: C_('button', 'Boot Options'), + }); + this._rebootButtonAlt.visible = false; + this._capturedEventId = global.stage.connect('captured-event', + this._onCapturedEvent.bind(this)); + } } } + _stopAltCapture() { + if (this._capturedEventId > 0) { + global.stage.disconnect(this._capturedEventId); + this._capturedEventId = 0; + } + this._rebootButton = null; + this._rebootButtonAlt = null; + } + close(skipSignal) { super.close(); @@ -396,14 +451,21 @@ class EndSessionDialog extends ModalDialog.ModalDialog { cancel() { this._stopTimer(); + this._stopAltCapture(); this._dbusImpl.emit_signal('Canceled', null); this.close(); } + _confirmRebootToBootLoaderMenu() { + this._loginManager.setRebootToBootLoaderMenu(); + this._confirm('ConfirmedReboot'); + } + _confirm(signal) { let callback = () => { this._fadeOutDialog(); this._stopTimer(); + this._stopAltCapture(); this._dbusImpl.emit_signal(signal, null); };