diff --git a/data/theme/gnome-shell-sass/widgets/_app-grid.scss b/data/theme/gnome-shell-sass/widgets/_app-grid.scss index 626925ab6..2df691161 100644 --- a/data/theme/gnome-shell-sass/widgets/_app-grid.scss +++ b/data/theme/gnome-shell-sass/widgets/_app-grid.scss @@ -108,8 +108,7 @@ $app_grid_fg_color: #fff; } // right-click app menu -.app-menu, -.app-well-menu { +.app-menu { max-width: 27.25em; } diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index 950979647..d7dc25ee5 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -3,9 +3,9 @@ const { Clutter, Gio, GLib, GObject, Graphene, Meta, Pango, Shell, St } = imports.gi; -const Signals = imports.signals; const AppFavorites = imports.ui.appFavorites; +const { AppMenu } = imports.ui.appMenu; const BoxPointer = imports.ui.boxpointer; const DND = imports.ui.dnd; const GrabHelper = imports.ui.grabHelper; @@ -53,8 +53,6 @@ const DELAYED_MOVE_TIMEOUT = 200; const DIALOG_SHADE_NORMAL = Clutter.Color.from_pixel(0x000000cc); const DIALOG_SHADE_HIGHLIGHT = Clutter.Color.from_pixel(0x00000055); -let discreteGpuAvailable = false; - var SidePages = { NONE: 0, PREVIOUS: 1 << 0, @@ -1453,20 +1451,6 @@ class AppDisplay extends BaseAppView { this._viewIsReady = false; Main.queueDeferredWork(this._redisplayWorkId); }); - - this._switcherooNotifyId = global.connect('notify::switcheroo-control', - () => this._updateDiscreteGpuAvailable()); - this._updateDiscreteGpuAvailable(); - } - - _updateDiscreteGpuAvailable() { - this._switcherooProxy = global.get_switcheroo_control(); - if (this._switcherooProxy) { - let prop = this._switcherooProxy.get_cached_property('HasDualGpu'); - discreteGpuAvailable = prop?.unpack() ?? false; - } else { - discreteGpuAvailable = false; - } } _onDestroy() { @@ -3248,10 +3232,11 @@ var AppIcon = GObject.registerClass({ this.fake_release(); if (!this._menu) { - this._menu = new AppIconMenu(this, side); - this._menu.connect('activate-window', (menu, window) => { - this.activateWindow(window); + this._menu = new AppMenu(this, side, { + favoritesSection: true, + showSingleWindows: true, }); + this._menu.setApp(this.app); this._menu.connect('open-state-changed', (menu, isPoppedUp) => { if (!isPoppedUp) this._onMenuPoppedDown(); @@ -3263,26 +3248,23 @@ var AppIcon = GObject.registerClass({ Main.overview.disconnect(id); }); + // We want to keep the item hovered while the menu is up + this._menu.blockSourceEvents = true; + + Main.uiGroup.add_actor(this._menu.actor); this._menuManager.addMenu(this._menu); } this.emit('menu-state-changed', true); this.set_hover(true); - this._menu.popup(); + this._menu.open(BoxPointer.PopupAnimation.FULL); this._menuManager.ignoreRelease(); this.emit('sync-tooltip'); return false; } - activateWindow(metaWindow) { - if (metaWindow) - Main.activateWindow(metaWindow); - else - Main.overview.hide(); - } - _onMenuPoppedDown() { this.sync_hover(); this.emit('menu-state-changed', false); @@ -3410,155 +3392,6 @@ var AppIcon = GObject.registerClass({ } }); -var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu { - constructor(source, side) { - if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) { - if (side === St.Side.LEFT) - side = St.Side.RIGHT; - else if (side === St.Side.RIGHT) - side = St.Side.LEFT; - } - - super(source, 0.5, side); - - // We want to keep the item hovered while the menu is up - this.blockSourceEvents = true; - - this._source = source; - - this._parentalControlsManager = ParentalControlsManager.getDefault(); - - this.actor.add_style_class_name('app-well-menu'); - - Main.uiGroup.add_actor(this.actor); - } - - _rebuildMenu() { - this.removeAll(); - - let windows = this._source.app.get_windows().filter( - w => !w.skip_taskbar); - - if (windows.length > 0) { - this.addMenuItem( - /* Translators: This is the heading of a list of open windows */ - new PopupMenu.PopupSeparatorMenuItem(_('Open Windows'))); - } - - windows.forEach(window => { - let title = window.title - ? window.title : this._source.app.get_name(); - let item = this._appendMenuItem(title); - item.connect('activate', () => { - this.emit('activate-window', window); - }); - }); - - if (!this._source.app.is_window_backed()) { - this._appendSeparator(); - - let appInfo = this._source.app.get_app_info(); - let actions = appInfo.list_actions(); - if (this._source.app.can_open_new_window() && - !actions.includes('new-window')) { - this._newWindowMenuItem = this._appendMenuItem(_("New Window")); - this._newWindowMenuItem.connect('activate', () => { - this._source.animateLaunch(); - this._source.app.open_new_window(-1); - this.emit('activate-window', null); - }); - this._appendSeparator(); - } - - if (discreteGpuAvailable && - this._source.app.state == Shell.AppState.STOPPED) { - const appPrefersNonDefaultGPU = appInfo.get_boolean('PrefersNonDefaultGPU'); - const gpuPref = appPrefersNonDefaultGPU - ? Shell.AppLaunchGpu.DEFAULT - : Shell.AppLaunchGpu.DISCRETE; - this._onGpuMenuItem = this._appendMenuItem(appPrefersNonDefaultGPU - ? _('Launch using Integrated Graphics Card') - : _('Launch using Discrete Graphics Card')); - this._onGpuMenuItem.connect('activate', () => { - this._source.animateLaunch(); - this._source.app.launch(0, -1, gpuPref); - this.emit('activate-window', null); - }); - } - - for (let i = 0; i < actions.length; i++) { - let action = actions[i]; - let item = this._appendMenuItem(appInfo.get_action_name(action)); - item.connect('activate', (emitter, event) => { - if (action == 'new-window') - this._source.animateLaunch(); - - this._source.app.launch_action(action, event.get_time(), -1); - this.emit('activate-window', null); - }); - } - - let canFavorite = global.settings.is_writable('favorite-apps') && - this._parentalControlsManager.shouldShowApp(this._source.app.app_info); - - if (canFavorite) { - this._appendSeparator(); - - let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id()); - - if (isFavorite) { - let item = this._appendMenuItem(_("Remove from Favorites")); - item.connect('activate', () => { - let favs = AppFavorites.getAppFavorites(); - favs.removeFavorite(this._source.app.get_id()); - }); - } else { - let item = this._appendMenuItem(_("Add to Favorites")); - item.connect('activate', () => { - let favs = AppFavorites.getAppFavorites(); - favs.addFavorite(this._source.app.get_id()); - }); - } - } - - if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop')) { - this._appendSeparator(); - this.addAction(_('Show Details'), async () => { - let id = this._source.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.new( - '(sava{sv})', ['details', [args], null]), - null, 0, -1, null); - Main.overview.hide(); - }); - } - } - } - - _appendSeparator() { - let separator = new PopupMenu.PopupSeparatorMenuItem(); - this.addMenuItem(separator); - } - - _appendMenuItem(labelText) { - // FIXME: app-well-menu-item style - let item = new PopupMenu.PopupMenuItem(labelText); - this.addMenuItem(item); - return item; - } - - popup(_activatingButton) { - this._rebuildMenu(); - this.open(BoxPointer.PopupAnimation.FULL); - } -}; -Signals.addSignalMethods(AppIconMenu.prototype); - var SystemActionIcon = GObject.registerClass( class SystemActionIcon extends Search.GridSearchResult { activate() {