appDisplay: Replace AppIconMenu
We are finally ready to share the app menu between the top bar and context menus in the dash/app grid. Notably that means that it is now possible to quit an app from its context menu. https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2875 Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1948>
This commit is contained in:
parent
414ed9128f
commit
b496c9f956
@ -108,8 +108,7 @@ $app_grid_fg_color: #fff;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// right-click app menu
|
// right-click app menu
|
||||||
.app-menu,
|
.app-menu {
|
||||||
.app-well-menu {
|
|
||||||
max-width: 27.25em;
|
max-width: 27.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
const { Clutter, Gio, GLib, GObject, Graphene, Meta,
|
const { Clutter, Gio, GLib, GObject, Graphene, Meta,
|
||||||
Pango, Shell, St } = imports.gi;
|
Pango, Shell, St } = imports.gi;
|
||||||
const Signals = imports.signals;
|
|
||||||
|
|
||||||
const AppFavorites = imports.ui.appFavorites;
|
const AppFavorites = imports.ui.appFavorites;
|
||||||
|
const { AppMenu } = imports.ui.appMenu;
|
||||||
const BoxPointer = imports.ui.boxpointer;
|
const BoxPointer = imports.ui.boxpointer;
|
||||||
const DND = imports.ui.dnd;
|
const DND = imports.ui.dnd;
|
||||||
const GrabHelper = imports.ui.grabHelper;
|
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_NORMAL = Clutter.Color.from_pixel(0x000000cc);
|
||||||
const DIALOG_SHADE_HIGHLIGHT = Clutter.Color.from_pixel(0x00000055);
|
const DIALOG_SHADE_HIGHLIGHT = Clutter.Color.from_pixel(0x00000055);
|
||||||
|
|
||||||
let discreteGpuAvailable = false;
|
|
||||||
|
|
||||||
var SidePages = {
|
var SidePages = {
|
||||||
NONE: 0,
|
NONE: 0,
|
||||||
PREVIOUS: 1 << 0,
|
PREVIOUS: 1 << 0,
|
||||||
@ -1453,20 +1451,6 @@ class AppDisplay extends BaseAppView {
|
|||||||
this._viewIsReady = false;
|
this._viewIsReady = false;
|
||||||
Main.queueDeferredWork(this._redisplayWorkId);
|
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() {
|
_onDestroy() {
|
||||||
@ -3248,10 +3232,11 @@ var AppIcon = GObject.registerClass({
|
|||||||
this.fake_release();
|
this.fake_release();
|
||||||
|
|
||||||
if (!this._menu) {
|
if (!this._menu) {
|
||||||
this._menu = new AppIconMenu(this, side);
|
this._menu = new AppMenu(this, side, {
|
||||||
this._menu.connect('activate-window', (menu, window) => {
|
favoritesSection: true,
|
||||||
this.activateWindow(window);
|
showSingleWindows: true,
|
||||||
});
|
});
|
||||||
|
this._menu.setApp(this.app);
|
||||||
this._menu.connect('open-state-changed', (menu, isPoppedUp) => {
|
this._menu.connect('open-state-changed', (menu, isPoppedUp) => {
|
||||||
if (!isPoppedUp)
|
if (!isPoppedUp)
|
||||||
this._onMenuPoppedDown();
|
this._onMenuPoppedDown();
|
||||||
@ -3263,26 +3248,23 @@ var AppIcon = GObject.registerClass({
|
|||||||
Main.overview.disconnect(id);
|
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._menuManager.addMenu(this._menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit('menu-state-changed', true);
|
this.emit('menu-state-changed', true);
|
||||||
|
|
||||||
this.set_hover(true);
|
this.set_hover(true);
|
||||||
this._menu.popup();
|
this._menu.open(BoxPointer.PopupAnimation.FULL);
|
||||||
this._menuManager.ignoreRelease();
|
this._menuManager.ignoreRelease();
|
||||||
this.emit('sync-tooltip');
|
this.emit('sync-tooltip');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
activateWindow(metaWindow) {
|
|
||||||
if (metaWindow)
|
|
||||||
Main.activateWindow(metaWindow);
|
|
||||||
else
|
|
||||||
Main.overview.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMenuPoppedDown() {
|
_onMenuPoppedDown() {
|
||||||
this.sync_hover();
|
this.sync_hover();
|
||||||
this.emit('menu-state-changed', false);
|
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(
|
var SystemActionIcon = GObject.registerClass(
|
||||||
class SystemActionIcon extends Search.GridSearchResult {
|
class SystemActionIcon extends Search.GridSearchResult {
|
||||||
activate() {
|
activate() {
|
||||||
|
Loading…
Reference in New Issue
Block a user