status/system: Port to quick settings
This port is a bit messier than the previous ones, because the existing menu section translates less directly to the new UI, which uses a row of individual toggles for settings, lock and shutdown. In order to not complicate the grid layout further by supporting rows with a different number of columns than the overall grid and children at their natural size, create a custom, non-reactive SystemItem item that spans an entire row, and contains the individual toggles. This works quite well, even with the shutdown item that uses a menu for the various actions. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2393>
This commit is contained in:
parent
62c62eced0
commit
ea00da7fd7
@ -83,3 +83,7 @@
|
||||
.quick-toggle-menu-container {
|
||||
padding: 2 * $base_padding $base_padding 0;
|
||||
}
|
||||
|
||||
.quick-settings-system-item {
|
||||
& > StBoxLayout { spacing: 2 * $base_padding; }
|
||||
}
|
||||
|
@ -378,18 +378,11 @@ class AggregateMenu extends PanelMenu.Button {
|
||||
else
|
||||
this._network = null;
|
||||
|
||||
this._system = new imports.ui.status.system.Indicator();
|
||||
|
||||
if (this._network)
|
||||
this._indicators.add_child(this._network);
|
||||
|
||||
if (this._network)
|
||||
this.menu.addMenuItem(this._network.menu);
|
||||
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addMenuItem(this._system.menu);
|
||||
|
||||
menuLayout.addSizeChild(this._system.menu.actor);
|
||||
}
|
||||
});
|
||||
|
||||
@ -410,6 +403,7 @@ class QuickSettings extends PanelMenu.Button {
|
||||
else
|
||||
this._bluetooth = null;
|
||||
|
||||
this._system = new imports.ui.status.system.Indicator();
|
||||
this._volume = new imports.ui.status.volume.Indicator();
|
||||
this._brightness = new imports.ui.status.brightness.Indicator();
|
||||
this._remoteAccess = new imports.ui.status.remoteAccess.RemoteAccessApplet();
|
||||
@ -437,7 +431,9 @@ class QuickSettings extends PanelMenu.Button {
|
||||
this._indicators.add_child(this._volume);
|
||||
this._indicators.add_child(this._unsafeMode);
|
||||
this._indicators.add_child(this._power);
|
||||
this._indicators.add_child(this._system);
|
||||
|
||||
this._addItems(this._system.quickSettingsItems, N_QUICK_SETTINGS_COLUMNS);
|
||||
this._addItems(this._volume.quickSettingsItems, N_QUICK_SETTINGS_COLUMNS);
|
||||
this._addItems(this._brightness.quickSettingsItems, N_QUICK_SETTINGS_COLUMNS);
|
||||
|
||||
|
@ -1,157 +1,181 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
/* exported Indicator */
|
||||
|
||||
const { GObject, Shell, St } = imports.gi;
|
||||
const {Clutter, GObject, Shell, St} = imports.gi;
|
||||
|
||||
const BoxPointer = imports.ui.boxpointer;
|
||||
const SystemActions = imports.misc.systemActions;
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const {QuickSettingsItem, SystemIndicator} = imports.ui.quickSettings;
|
||||
|
||||
var Indicator = GObject.registerClass(
|
||||
class Indicator extends PanelMenu.SystemIndicator {
|
||||
const SettingsItem = GObject.registerClass(
|
||||
class SettingsItem extends QuickSettingsItem {
|
||||
_init() {
|
||||
super._init();
|
||||
super._init({
|
||||
style_class: 'icon-button',
|
||||
can_focus: true,
|
||||
child: new St.Icon(),
|
||||
});
|
||||
|
||||
this._settingsApp = Shell.AppSystem.get_default().lookup_app(
|
||||
'org.gnome.Settings.desktop');
|
||||
|
||||
if (!this._settingsApp)
|
||||
console.warn('Missing required core component Settings, expect trouble…');
|
||||
|
||||
this.child.gicon = this._settingsApp?.get_icon() ?? null;
|
||||
this.accessible_name = this._settingsApp?.get_name() ?? null;
|
||||
|
||||
this.connect('clicked', () => {
|
||||
Main.overview.hide();
|
||||
Main.panel.closeQuickSettings();
|
||||
this._settingsApp.activate();
|
||||
});
|
||||
|
||||
Main.sessionMode.connectObject('updated', () => this._sync(), this);
|
||||
this._sync();
|
||||
}
|
||||
|
||||
_sync() {
|
||||
this.visible =
|
||||
this._settingsApp != null && Main.sessionMode.allowSettings;
|
||||
}
|
||||
});
|
||||
|
||||
const ShutdownItem = GObject.registerClass(
|
||||
class ShutdownItem extends QuickSettingsItem {
|
||||
_init() {
|
||||
super._init({
|
||||
style_class: 'icon-button',
|
||||
hasMenu: true,
|
||||
canFocus: true,
|
||||
child: new St.Icon({
|
||||
icon_name: 'system-shutdown-symbolic',
|
||||
}),
|
||||
accessible_name: _('Power Off Menu'),
|
||||
});
|
||||
|
||||
this._systemActions = new SystemActions.getDefault();
|
||||
this._items = [];
|
||||
|
||||
this._createSubMenu();
|
||||
this.menu.setHeader('system-shutdown-symbolic', 'Power Off');
|
||||
|
||||
this._addSystemAction(_('Suspend'), 'can-suspend', () => {
|
||||
this._systemActions.activateSuspend();
|
||||
Main.panel.closeQuickSettings();
|
||||
});
|
||||
|
||||
this._addSystemAction(_('Restart…'), 'can-restart', () => {
|
||||
this._systemActions.activateRestart();
|
||||
Main.panel.closeQuickSettings();
|
||||
});
|
||||
|
||||
this._addSystemAction(_('Power Off…'), 'can-power-off', () => {
|
||||
this._systemActions.activatePowerOff();
|
||||
Main.panel.closeQuickSettings();
|
||||
});
|
||||
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
this._addSystemAction(_('Log Out'), 'can-logout', () => {
|
||||
this._systemActions.activateLogout();
|
||||
Main.panel.closeQuickSettings();
|
||||
});
|
||||
|
||||
this._addSystemAction(_('Switch User…'), 'can-switch-user', () => {
|
||||
this._systemActions.activateSwitchUser();
|
||||
Main.panel.closeQuickSettings();
|
||||
});
|
||||
|
||||
this._loginScreenItem.connect('notify::visible',
|
||||
() => this._updateSessionSubMenu());
|
||||
this._logoutItem.connect('notify::visible',
|
||||
() => this._updateSessionSubMenu());
|
||||
this._suspendItem.connect('notify::visible',
|
||||
() => this._updateSessionSubMenu());
|
||||
this._powerOffItem.connect('notify::visible',
|
||||
() => this._updateSessionSubMenu());
|
||||
this._restartItem.connect('notify::visible',
|
||||
() => this._updateSessionSubMenu());
|
||||
// Whether shutdown is available or not depends on both lockdown
|
||||
// settings (disable-log-out) and Polkit policy - the latter doesn't
|
||||
// notify, so we update the menu item each time the menu opens or
|
||||
// notify, so we update the item each time we become visible or
|
||||
// the lockdown setting changes, which should be close enough.
|
||||
this.menu.connect('open-state-changed', (menu, open) => {
|
||||
if (!open)
|
||||
this.connect('notify::mapped', () => {
|
||||
if (!this.mapped)
|
||||
return;
|
||||
|
||||
this._systemActions.forceUpdate();
|
||||
});
|
||||
this._updateSessionSubMenu();
|
||||
|
||||
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
|
||||
this._sessionUpdated();
|
||||
this.connect('clicked', () => this.menu.open());
|
||||
this.connect('popup-menu', () => this.menu.open());
|
||||
}
|
||||
|
||||
_sessionUpdated() {
|
||||
this._settingsItem.visible = Main.sessionMode.allowSettings;
|
||||
_addSystemAction(label, propName, callback) {
|
||||
const item = this.menu.addAction(label, callback);
|
||||
this._items.push(item);
|
||||
|
||||
this._systemActions.bind_property(propName,
|
||||
item, 'visible',
|
||||
GObject.BindingFlags.DEFAULT | GObject.BindingFlags.SYNC_CREATE);
|
||||
item.connect('notify::visible', () => this._sync());
|
||||
}
|
||||
|
||||
_updateSessionSubMenu() {
|
||||
this._sessionSubMenu.visible =
|
||||
this._loginScreenItem.visible ||
|
||||
this._logoutItem.visible ||
|
||||
this._suspendItem.visible ||
|
||||
this._restartItem.visible ||
|
||||
this._powerOffItem.visible;
|
||||
_sync() {
|
||||
this.visible = this._items.some(i => i.visible);
|
||||
}
|
||||
|
||||
_createSubMenu() {
|
||||
let bindFlags = GObject.BindingFlags.DEFAULT | GObject.BindingFlags.SYNC_CREATE;
|
||||
let item;
|
||||
|
||||
let app = this._settingsApp = Shell.AppSystem.get_default().lookup_app(
|
||||
'org.gnome.Settings.desktop');
|
||||
if (app) {
|
||||
const [icon] = app.app_info.get_icon().names;
|
||||
const name = app.app_info.get_name();
|
||||
item = new PopupMenu.PopupImageMenuItem(name, icon);
|
||||
item.connect('activate', () => {
|
||||
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE);
|
||||
Main.overview.hide();
|
||||
this._settingsApp.activate();
|
||||
});
|
||||
this.menu.addMenuItem(item);
|
||||
this._settingsItem = item;
|
||||
} else {
|
||||
log('Missing required core component Settings, expect trouble…');
|
||||
this._settingsItem = new St.Widget();
|
||||
}
|
||||
|
||||
item = new PopupMenu.PopupImageMenuItem(_('Lock'), 'changes-prevent-symbolic');
|
||||
item.connect('activate', () => {
|
||||
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE);
|
||||
this._systemActions.activateLockScreen();
|
||||
const LockItem = GObject.registerClass(
|
||||
class LockItem extends QuickSettingsItem {
|
||||
_init() {
|
||||
this._systemActions = new SystemActions.getDefault();
|
||||
|
||||
super._init({
|
||||
style_class: 'icon-button',
|
||||
can_focus: true,
|
||||
child: new St.Icon({
|
||||
icon_name: 'system-lock-screen-symbolic',
|
||||
}),
|
||||
accessible_name: _('Lock Screen'),
|
||||
});
|
||||
this.menu.addMenuItem(item);
|
||||
this._lockScreenItem = item;
|
||||
|
||||
this._systemActions.bind_property('can-lock-screen',
|
||||
this._lockScreenItem, 'visible',
|
||||
bindFlags);
|
||||
this, 'visible',
|
||||
GObject.BindingFlags.DEFAULT |
|
||||
GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
this._sessionSubMenu = new PopupMenu.PopupSubMenuMenuItem(
|
||||
_('Power Off / Log Out'), true);
|
||||
this._sessionSubMenu.icon.icon_name = 'system-shutdown-symbolic';
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_('Suspend'));
|
||||
item.connect('activate', () => {
|
||||
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE);
|
||||
this._systemActions.activateSuspend();
|
||||
});
|
||||
this._sessionSubMenu.menu.addMenuItem(item);
|
||||
this._suspendItem = item;
|
||||
this._systemActions.bind_property('can-suspend',
|
||||
this._suspendItem, 'visible',
|
||||
bindFlags);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_('Restart…'));
|
||||
item.connect('activate', () => {
|
||||
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE);
|
||||
this._systemActions.activateRestart();
|
||||
});
|
||||
this._sessionSubMenu.menu.addMenuItem(item);
|
||||
this._restartItem = item;
|
||||
this._systemActions.bind_property('can-restart',
|
||||
this._restartItem, 'visible',
|
||||
bindFlags);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_('Power Off…'));
|
||||
item.connect('activate', () => {
|
||||
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE);
|
||||
this._systemActions.activatePowerOff();
|
||||
});
|
||||
this._sessionSubMenu.menu.addMenuItem(item);
|
||||
this._powerOffItem = item;
|
||||
this._systemActions.bind_property('can-power-off',
|
||||
this._powerOffItem, 'visible',
|
||||
bindFlags);
|
||||
|
||||
this._sessionSubMenu.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_('Log Out'));
|
||||
item.connect('activate', () => {
|
||||
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE);
|
||||
this._systemActions.activateLogout();
|
||||
});
|
||||
this._sessionSubMenu.menu.addMenuItem(item);
|
||||
this._logoutItem = item;
|
||||
this._systemActions.bind_property('can-logout',
|
||||
this._logoutItem, 'visible',
|
||||
bindFlags);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_('Switch User…'));
|
||||
item.connect('activate', () => {
|
||||
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE);
|
||||
this._systemActions.activateSwitchUser();
|
||||
});
|
||||
this._sessionSubMenu.menu.addMenuItem(item);
|
||||
this._loginScreenItem = item;
|
||||
this._systemActions.bind_property('can-switch-user',
|
||||
this._loginScreenItem, 'visible',
|
||||
bindFlags);
|
||||
|
||||
this.menu.addMenuItem(this._sessionSubMenu);
|
||||
this.connect('clicked',
|
||||
() => this._systemActions.activateLockScreen());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const SystemItem = GObject.registerClass(
|
||||
class SystemItem extends QuickSettingsItem {
|
||||
_init() {
|
||||
super._init({
|
||||
style_class: 'quick-settings-system-item',
|
||||
reactive: false,
|
||||
});
|
||||
|
||||
this.child = new St.BoxLayout();
|
||||
|
||||
// spacer
|
||||
this.child.add_child(new Clutter.Actor({x_expand: true}));
|
||||
|
||||
const settingsItem = new SettingsItem();
|
||||
this.child.add_child(settingsItem);
|
||||
|
||||
const lockItem = new LockItem();
|
||||
this.child.add_child(lockItem);
|
||||
|
||||
const shutdownItem = new ShutdownItem();
|
||||
this.child.add_child(shutdownItem);
|
||||
|
||||
this.menu = shutdownItem.menu;
|
||||
}
|
||||
});
|
||||
|
||||
var Indicator = GObject.registerClass(
|
||||
class Indicator extends SystemIndicator {
|
||||
_init() {
|
||||
super._init();
|
||||
|
||||
const item = new SystemItem();
|
||||
|
||||
this.quickSettingsItems.push(item);
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user