[gnome-shell] appMenu: Split out from panel



commit 1550976c51542c935471e54c5fba67eae36c6d09
Author: Florian Müllner <fmuellner gnome org>
Date:   Wed Aug 11 19:40:52 2021 +0200

    appMenu: Split out from panel
    
    There is a big overlap between the app menu in the top bar and the
    context menu of app icons. It makes sense to unify the two both
    from a design- and from a code perspective, so split out the more
    modern one into a separate module as basis for a shared class.
    
    Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1948>

 js/js-resources.gresource.xml |   1 +
 js/ui/appMenu.js              | 137 ++++++++++++++++++++++++++++++++++++++++++
 js/ui/panel.js                | 128 +--------------------------------------
 po/POTFILES.in                |   1 +
 4 files changed, 141 insertions(+), 126 deletions(-)
---
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index 6d7940f06b..6dc01b9240 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -40,6 +40,7 @@
     <file>ui/animation.js</file>
     <file>ui/appDisplay.js</file>
     <file>ui/appFavorites.js</file>
+    <file>ui/appMenu.js</file>
     <file>ui/audioDeviceSelection.js</file>
     <file>ui/backgroundMenu.js</file>
     <file>ui/background.js</file>
diff --git a/js/ui/appMenu.js b/js/ui/appMenu.js
new file mode 100644
index 0000000000..ae6aa16a0f
--- /dev/null
+++ b/js/ui/appMenu.js
@@ -0,0 +1,137 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+/* exported AppMenu */
+const { Gio, GLib, Shell, St } = imports.gi;
+
+const PopupMenu = imports.ui.popupMenu;
+const Main = imports.ui.main;
+
+var AppMenu = class AppMenu extends PopupMenu.PopupMenu {
+    /**
+     * @param {Clutter.Actor} sourceActor - actor the menu is attached to
+     */
+    constructor(sourceActor) {
+        super(sourceActor, 0.5, St.Side.TOP);
+
+        this.actor.add_style_class_name('app-menu');
+
+        this._app = null;
+        this._appSystem = Shell.AppSystem.get_default();
+
+        this._windowsChangedId = 0;
+
+        /* Translators: This is the heading of a list of open windows */
+        this._openWindowsHeader = new PopupMenu.PopupSeparatorMenuItem(_('Open Windows'));
+        this.addMenuItem(this._openWindowsHeader);
+
+        this._windowSection = new PopupMenu.PopupMenuSection();
+        this.addMenuItem(this._windowSection);
+
+        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+
+        this._newWindowItem = this.addAction(_('New Window'), () => {
+            this._app.open_new_window(-1);
+        });
+
+        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+
+        this._actionSection = new PopupMenu.PopupMenuSection();
+        this.addMenuItem(this._actionSection);
+
+        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+
+        this._detailsItem = this.addAction(_('Show Details'), async () => {
+            const id = this._app.get_id();
+            const args = GLib.Variant.new('(ss)', [id, '']);
+            const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
+            bus.call(
+                'org.gnome.Software',
+                '/org/gnome/Software',
+                'org.gtk.Actions', 'Activate',
+                new GLib.Variant('(sava{sv})', ['details', [args], null]),
+                null, 0, -1, null);
+        });
+
+        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+
+        this.addAction(_('Quit'), () => this._app.request_quit());
+
+        this._appSystem.connect('installed-changed',
+            () => this._updateDetailsVisibility());
+        this._updateDetailsVisibility();
+    }
+
+    _updateDetailsVisibility() {
+        const sw = this._appSystem.lookup_app('org.gnome.Software.desktop');
+        this._detailsItem.visible = sw !== null;
+    }
+
+    /**
+     * @returns {bool} - true if the menu is empty
+     */
+    isEmpty() {
+        if (!this._app)
+            return true;
+        return super.isEmpty();
+    }
+
+    /**
+     * @param {Shell.App} app - the app the menu represents
+     */
+    setApp(app) {
+        if (this._app === app)
+            return;
+
+        if (this._windowsChangedId)
+            this._app.disconnect(this._windowsChangedId);
+        this._windowsChangedId = 0;
+
+        this._app = app;
+
+        if (app) {
+            this._windowsChangedId = app.connect('windows-changed', () => {
+                this._updateWindowsSection();
+            });
+        }
+
+        this._updateWindowsSection();
+
+        const appInfo = app?.app_info;
+        const actions = appInfo?.list_actions() ?? [];
+
+        this._actionSection.removeAll();
+        actions.forEach(action => {
+            const label = appInfo.get_action_name(action);
+            this._actionSection.addAction(label, event => {
+                this._app.launch_action(action, event.get_time(), -1);
+            });
+        });
+
+        this._newWindowItem.visible =
+            app && app.can_open_new_window() && !actions.includes('new-window');
+    }
+
+    _updateWindowsSection() {
+        this._windowSection.removeAll();
+        this._openWindowsHeader.hide();
+
+        if (!this._app)
+            return;
+
+        const windows = this._app.get_windows();
+        if (windows.length < 2)
+            return;
+
+        this._openWindowsHeader.show();
+
+        windows.forEach(window => {
+            const title = window.title || this._app.get_name();
+            const item = this._windowSection.addAction(title, event => {
+                Main.activateWindow(window, event.get_time());
+            });
+            const id = window.connect('notify::title', () => {
+                item.label.text = window.title || this._app.get_name();
+            });
+            item.connect('destroy', () => window.disconnect(id));
+        });
+    }
+};
diff --git a/js/ui/panel.js b/js/ui/panel.js
index c039112d7a..89b082ad05 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -1,10 +1,11 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 /* exported Panel */
 
-const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
+const { Atk, Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
 const Cairo = imports.cairo;
 
 const Animation = imports.ui.animation;
+const { AppMenu } = imports.ui.appMenu;
 const Config = imports.misc.config;
 const CtrlAltTab = imports.ui.ctrlAltTab;
 const DND = imports.ui.dnd;
@@ -18,131 +19,6 @@ var APP_MENU_ICON_MARGIN = 0;
 
 var BUTTON_DND_ACTIVATION_TIMEOUT = 250;
 
-class AppMenu extends PopupMenu.PopupMenu {
-    constructor(sourceActor) {
-        super(sourceActor, 0.5, St.Side.TOP);
-
-        this.actor.add_style_class_name('app-menu');
-
-        this._app = null;
-        this._appSystem = Shell.AppSystem.get_default();
-
-        this._windowsChangedId = 0;
-
-        /* Translators: This is the heading of a list of open windows */
-        this._openWindowsHeader = new PopupMenu.PopupSeparatorMenuItem(_('Open Windows'));
-        this.addMenuItem(this._openWindowsHeader);
-
-        this._windowSection = new PopupMenu.PopupMenuSection();
-        this.addMenuItem(this._windowSection);
-
-        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
-
-        this._newWindowItem = this.addAction(_("New Window"), () => {
-            this._app.open_new_window(-1);
-        });
-
-        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
-
-        this._actionSection = new PopupMenu.PopupMenuSection();
-        this.addMenuItem(this._actionSection);
-
-        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
-
-        this._detailsItem = this.addAction(_('Show Details'), async () => {
-            let id = this._app.get_id();
-            let args = GLib.Variant.new('(ss)', [id, '']);
-            const bus = await Gio.DBus.get(Gio.BusType.SESSION, null);
-            bus.call(
-                'org.gnome.Software',
-                '/org/gnome/Software',
-                'org.gtk.Actions', 'Activate',
-                new GLib.Variant('(sava{sv})', ['details', [args], null]),
-                null, 0, -1, null);
-        });
-
-        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
-
-        this.addAction(_("Quit"), () => {
-            this._app.request_quit();
-        });
-
-        this._appSystem.connect('installed-changed', () => {
-            this._updateDetailsVisibility();
-        });
-        this._updateDetailsVisibility();
-    }
-
-    _updateDetailsVisibility() {
-        let sw = this._appSystem.lookup_app('org.gnome.Software.desktop');
-        this._detailsItem.visible = sw != null;
-    }
-
-    isEmpty() {
-        if (!this._app)
-            return true;
-        return super.isEmpty();
-    }
-
-    setApp(app) {
-        if (this._app == app)
-            return;
-
-        if (this._windowsChangedId)
-            this._app.disconnect(this._windowsChangedId);
-        this._windowsChangedId = 0;
-
-        this._app = app;
-
-        if (app) {
-            this._windowsChangedId = app.connect('windows-changed', () => {
-                this._updateWindowsSection();
-            });
-        }
-
-        this._updateWindowsSection();
-
-        const appInfo = app?.app_info;
-        const actions = appInfo?.list_actions() ?? [];
-
-        this._actionSection.removeAll();
-        actions.forEach(action => {
-            let label = appInfo.get_action_name(action);
-            this._actionSection.addAction(label, event => {
-                this._app.launch_action(action, event.get_time(), -1);
-            });
-        });
-
-        this._newWindowItem.visible =
-            app && app.can_open_new_window() && !actions.includes('new-window');
-    }
-
-    _updateWindowsSection() {
-        this._windowSection.removeAll();
-        this._openWindowsHeader.hide();
-
-        if (!this._app)
-            return;
-
-        let windows = this._app.get_windows();
-        if (windows.length < 2)
-            return;
-
-        this._openWindowsHeader.show();
-
-        windows.forEach(window => {
-            let title = window.title || this._app.get_name();
-            let item = this._windowSection.addAction(title, event => {
-                Main.activateWindow(window, event.get_time());
-            });
-            let id = window.connect('notify::title', () => {
-                item.label.text = window.title || this._app.get_name();
-            });
-            item.connect('destroy', () => window.disconnect(id));
-        });
-    }
-}
-
 /**
  * AppMenuButton:
  *
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 8e763c8f24..6340bff17a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -15,6 +15,7 @@ js/portalHelper/main.js
 js/ui/accessDialog.js
 js/ui/appDisplay.js
 js/ui/appFavorites.js
+js/ui/appMenu.js
 js/ui/audioDeviceSelection.js
 js/ui/backgroundMenu.js
 js/ui/calendar.js


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]