[gnome-shell/T29763: 9/249] Add a dialog to force quit applications
- From: Matthew Leeds <mwleeds src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/T29763: 9/249] Add a dialog to force quit applications
- Date: Thu, 21 May 2020 18:09:52 +0000 (UTC)
commit 606b36cd4468d548e7d1c2cae20268b257e4684a
Author: Mario Sanchez Prada <mario endlessm com>
Date: Mon Sep 11 17:30:53 2017 +0100
Add a dialog to force quit applications
This is an escape hatch for users who are used to Ctrl+Alt+Del allowing
them to quit applications on their computer.
data/org.gnome.shell.gschema.xml.in | 8 ++
data/theme/gnome-shell-sass/_endless.scss | 42 +++++++++
js/js-resources.gresource.xml | 4 +
js/ui/forceAppExitDialog.js | 144 ++++++++++++++++++++++++++++++
js/ui/windowManager.js | 16 ++++
po/POTFILES.in | 2 +
6 files changed, 216 insertions(+)
---
diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in
index 49d38d7662..3d2d0cb200 100644
--- a/data/org.gnome.shell.gschema.xml.in
+++ b/data/org.gnome.shell.gschema.xml.in
@@ -186,6 +186,14 @@
<default>["<Super>9"]</default>
<summary>Switch to application 9</summary>
</key>
+
+ <!-- Endless-specific keys beyond this point -->
+
+ <key name="show-force-app-exit-dialog" type="as">
+ <default>["<Ctrl><Alt>Delete"]</default>
+ <summary>Keybinding that shows the force app exit dialog</summary>
+ <description></description>
+ </key>
</schema>
<schema id="org.gnome.shell.app-switcher"
diff --git a/data/theme/gnome-shell-sass/_endless.scss b/data/theme/gnome-shell-sass/_endless.scss
index 88cda2c0e1..b5daac4a97 100644
--- a/data/theme/gnome-shell-sass/_endless.scss
+++ b/data/theme/gnome-shell-sass/_endless.scss
@@ -16,3 +16,45 @@
#lockDialogGroup {
background: #12282e;
}
+
+// Force Apps dialog
+
+.force-app-exit-dialog {
+ max-height: 500px;
+ min-height: 450px;
+ min-width: 470px;
+ border: 1px solid rgba(238, 238, 236, 0.2);
+
+ .modal-dialog-content-box {
+ spacing: 20px;
+ padding: 20px 17px;
+
+ .force-app-exit-dialog-header {
+ font-weight: bold;
+ }
+
+ .force-app-exit-dialog-subtitle {
+ color: #ccc;
+ font-size: 12pt;
+ max-width: 370px;
+ }
+
+ .force-app-exit-dialog-scroll-view {
+ border: 2px solid #666;
+ border-radius: 6px;
+ height: 288px;
+
+ .force-app-exit-dialog-item {
+ border: solid #242424;
+ padding: 16px;
+ spacing: 16px;
+ border-bottom-width: 1px;
+ &:hover { background-color: rgba(255,255,255,0.1); }
+ &:selected {
+ background-color: $selected_bg_color;
+ color: $selected_fg_color;
+ }
+ }
+ }
+ }
+}
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index 302fdfb42e..b353ec8e3b 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -138,5 +138,9 @@
<file>ui/status/screencast.js</file>
<file>ui/status/system.js</file>
<file>ui/status/thunderbolt.js</file>
+
+ <!-- Endless-specific files beyond this point -->
+
+ <file>ui/forceAppExitDialog.js</file>
</gresource>
</gresources>
diff --git a/js/ui/forceAppExitDialog.js b/js/ui/forceAppExitDialog.js
new file mode 100644
index 0000000000..9997c6bc1a
--- /dev/null
+++ b/js/ui/forceAppExitDialog.js
@@ -0,0 +1,144 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+/* exported ForceAppExitDialog */
+
+const { Clutter, GObject, Gtk, Shell, St } = imports.gi;
+
+const Main = imports.ui.main;
+const ModalDialog = imports.ui.modalDialog;
+
+const GNOME_SYSTEM_MONITOR_DESKTOP_ID = 'gnome-system-monitor.desktop';
+const ICON_SIZE = 32;
+
+const ForceAppExitDialogItem = GObject.registerClass({
+ Signals: { 'selected': {} },
+}, class ForceAppExitDialogItem extends St.BoxLayout {
+ _init(app) {
+ super._init({
+ style_class: 'force-app-exit-dialog-item',
+ can_focus: true,
+ reactive: true,
+ track_hover: true,
+ });
+ this.app = app;
+
+ this.connect('key-focus-in', () => this.emit('selected'));
+ let action = new Clutter.ClickAction();
+ action.connect('clicked', this.grab_key_focus.bind(this));
+ this.add_action(action);
+
+ this._icon = this.app.create_icon_texture(ICON_SIZE);
+ this.add(this._icon);
+
+ this._label = new St.Label({
+ text: this.app.get_name(),
+ y_expand: true,
+ y_align: Clutter.ActorAlign.CENTER,
+ });
+ this.label_actor = this._label;
+ this.add(this._label);
+ }
+});
+
+var ForceAppExitDialog = GObject.registerClass(
+class ForceAppExitDialog extends ModalDialog.ModalDialog {
+ _init() {
+ super._init({ styleClass: 'force-app-exit-dialog' });
+
+ let title = new St.Label({
+ style_class: 'force-app-exit-dialog-header',
+ text: _('Quit applications'),
+ });
+ this.contentLayout.add(title);
+
+ let subtitle = new St.Label({
+ style_class: 'force-app-exit-dialog-subtitle',
+ text: _("If an application doesn't respond for a while, select its name and click Quit
Application."),
+ });
+ subtitle.clutter_text.line_wrap = true;
+ this.contentLayout.add(subtitle, {
+ x_fill: false,
+ x_align: St.Align.START,
+ });
+
+ this._itemBox = new St.BoxLayout({ vertical: true });
+ this._scrollView = new St.ScrollView({
+ style_class: 'force-app-exit-dialog-scroll-view',
+ hscrollbar_policy: Gtk.PolicyType.NEVER,
+ vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
+ overlay_scrollbars: true,
+ x_expand: true,
+ y_expand: true,
+ });
+ this._scrollView.add_actor(this._itemBox);
+
+ this.contentLayout.add(this._scrollView, { expand: true });
+
+ this._cancelButton = this.addButton({
+ action: this.close.bind(this),
+ label: _('Cancel'),
+ key: Clutter.Escape,
+ });
+
+ let appSystem = Shell.AppSystem.get_default();
+ if (appSystem.lookup_app(GNOME_SYSTEM_MONITOR_DESKTOP_ID)) {
+ this.addButton({
+ action: this._launchSystemMonitor.bind(this),
+ label: _('System Monitor'),
+ }, {
+ x_align: St.Align.END,
+ });
+ }
+
+ this._quitButton = this.addButton({
+ action: this._quitApp.bind(this),
+ label: _('Quit Application'),
+ key: Clutter.Return,
+ }, {
+ expand: true,
+ x_fill: false,
+ x_align: St.Align.END,
+ });
+
+ appSystem.get_running().forEach(app => {
+ let item = new ForceAppExitDialogItem(app);
+ item.connect('selected', this._selectApp.bind(this));
+ this._itemBox.add_child(item);
+ });
+
+ this._selectedAppItem = null;
+ this._updateSensitivity();
+ }
+
+ _updateSensitivity() {
+ let quitSensitive = this._selectedAppItem !== null;
+ this._quitButton.reactive = quitSensitive;
+ this._quitButton.can_focus = quitSensitive;
+ }
+
+ _launchSystemMonitor() {
+ let appSystem = Shell.AppSystem.get_default();
+ let systemMonitor = appSystem.lookup_app(GNOME_SYSTEM_MONITOR_DESKTOP_ID);
+ systemMonitor.activate();
+
+ this.close();
+ Main.overview.hide();
+ }
+
+ _quitApp() {
+ let app = this._selectedAppItem.app;
+ app.request_quit();
+ this.close();
+ }
+
+ _selectApp(appItem) {
+ if (this._selectedAppItem)
+ this._selectedAppItem.remove_style_pseudo_class('selected');
+
+ this._selectedAppItem = appItem;
+ this._updateSensitivity();
+
+ if (this._selectedAppItem)
+ this._selectedAppItem.add_style_pseudo_class('selected');
+ }
+});
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index 21c63b5c32..13ea29dbde 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -6,6 +6,7 @@ const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const AltTab = imports.ui.altTab;
const AppFavorites = imports.ui.appFavorites;
const Dialog = imports.ui.dialog;
+const ForceAppExitDialog = imports.ui.forceAppExitDialog;
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
const InhibitShortcutsDialog = imports.ui.inhibitShortcutsDialog;
const Main = imports.ui.main;
@@ -789,6 +790,13 @@ var WindowManager = class {
Shell.ActionMode.OVERVIEW,
this._startSwitcher.bind(this));
+ this.addKeybinding('show-force-app-exit-dialog',
+ new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
+ Meta.KeyBindingFlags.NONE,
+ Shell.ActionMode.NORMAL |
+ Shell.ActionMode.OVERVIEW,
+ this._showForceAppExitDialog.bind(this));
+
this.addKeybinding('open-application-menu',
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
@@ -2044,6 +2052,14 @@ var WindowManager = class {
app.activate();
}
+ _showForceAppExitDialog() {
+ if (!Main.sessionMode.hasOverview)
+ return;
+
+ let dialog = new ForceAppExitDialog.ForceAppExitDialog();
+ dialog.open();
+ }
+
_toggleAppMenu() {
Main.panel.toggleAppMenu();
}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 92cdaf5ce4..d4ab53a0ed 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -96,3 +96,5 @@ subprojects/extensions-tool/src/command-uninstall.c
subprojects/extensions-tool/src/main.c
# Please do not remove this file from POTFILES.in. Run "git submodule init && git submodule update" to get
it.
subprojects/gvc/gvc-mixer-control.c
+# Endless-specific files beyond this point
+js/ui/forceAppExitDialog.js
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]