From 2815f33458ef2ec6c3c7747440e125d05637e9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Tue, 11 Apr 2023 15:29:55 +0200 Subject: [PATCH] status/backgroundApps: Show spinner when closing It can take a little while for an app to quit after the user clicked the close button, and another for the portal to pick up the change. In order to provide feedback to the user that the request is being handled, replace the close button with a spinner. https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6441 Part-of: --- .../widgets/_quick-settings.scss | 3 ++ js/ui/status/backgroundApps.js | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/data/theme/gnome-shell-sass/widgets/_quick-settings.scss b/data/theme/gnome-shell-sass/widgets/_quick-settings.scss index 82a5e11aa..88d938409 100644 --- a/data/theme/gnome-shell-sass/widgets/_quick-settings.scss +++ b/data/theme/gnome-shell-sass/widgets/_quick-settings.scss @@ -183,6 +183,9 @@ @extend .icon-button; padding: $base_padding; } + & .spinner { + padding: $base_padding; + } &.popup-inactive-menu-item { color: $fg_color; } } diff --git a/js/ui/status/backgroundApps.js b/js/ui/status/backgroundApps.js index 49878c134..f5db92181 100644 --- a/js/ui/status/backgroundApps.js +++ b/js/ui/status/backgroundApps.js @@ -5,12 +5,15 @@ const Main = imports.ui.main; const PopupMenu = imports.ui.popupMenu; const Util = imports.misc.util; +const {Spinner} = imports.ui.animation; const {QuickToggle, SystemIndicator} = imports.ui.quickSettings; const {loadInterfaceXML} = imports.misc.dbusUtils; const DBUS_NAME = 'org.freedesktop.background.Monitor'; const DBUS_OBJECT_PATH = '/org/freedesktop/background/monitor'; +const SPINNER_TIMEOUT = 5; // seconds + const BackgroundMonitorIface = loadInterfaceXML('org.freedesktop.background.Monitor'); const BackgroundMonitorProxy = Gio.DBusProxy.makeProxyWrapper(BackgroundMonitorIface); @@ -76,6 +79,10 @@ var BackgroundAppMenuItem = GObject.registerClass({ this.set_child_above_sibling(this._ornamentLabel, null); + this._spinner = new Spinner(16, {hideOnStop: true}); + this._spinner.add_style_class_name('spinner'); + this.add_child(this._spinner); + const closeButton = new St.Button({ iconName: 'window-close-symbolic', styleClass: 'close-button', @@ -86,12 +93,34 @@ var BackgroundAppMenuItem = GObject.registerClass({ }); this.add_child(closeButton); + this._spinner.bind_property('visible', + closeButton, 'visible', + GObject.BindingFlags.INVERT_BOOLEAN); + closeButton.connect('clicked', () => this._quitApp().catch(logError)); + + this.connect('destroy', () => this._onDestroy()); + } + + _onDestroy() { + if (this._spinnerTimeoutId) + GLib.source_remove(this._spinnerTimeoutId); + delete this._spinnerTimeoutId; } async _quitApp() { const appId = this.app.get_id().replace(/\.desktop$/, ''); + this._spinner.play(); + this._spinnerTimeoutId = + GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, SPINNER_TIMEOUT, + () => { + // Assume the quit request has failed, stop the spinner + this._spinner.stop(); + delete this._spinnerTimeoutId; + return GLib.SOURCE_REMOVE; + }); + try { await Gio.DBus.session.call( appId,