status: Port to a new SystemIndicator framework
We can't silently replace the old behavior of separate status icons into a new system. Replace SystemStatusButton with a new SystemIndicator class which will allow for the flexibility we need. For now, make it a subclass of Button so that it mostly feels the same, but we'll soon be swapping it out with a dummy implementation that the aggregate menu will use. I think the code cleanup here is worth it. https://bugzilla.gnome.org/show_bug.cgi?id=705845
This commit is contained in:
parent
a347f02545
commit
5cca26a565
@ -614,7 +614,7 @@ StScrollBar StButton#vhandle:active {
|
|||||||
-boxpointer-gap: 4px;
|
-boxpointer-gap: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-status-button-box,
|
.panel-status-indicators-box,
|
||||||
.panel-status-menu-box {
|
.panel-status-menu-box {
|
||||||
spacing: 4px;
|
spacing: 4px;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ const PopupMenu = imports.ui.popupMenu;
|
|||||||
|
|
||||||
const PowerMenuButton = new Lang.Class({
|
const PowerMenuButton = new Lang.Class({
|
||||||
Name: 'PowerMenuButton',
|
Name: 'PowerMenuButton',
|
||||||
Extends: PanelMenu.SystemStatusButton,
|
Extends: PanelMenu.SystemIndicator,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
/* Translators: accessible name of the power menu in the login screen */
|
/* Translators: accessible name of the power menu in the login screen */
|
||||||
|
@ -233,51 +233,29 @@ const Button = new Lang.Class({
|
|||||||
});
|
});
|
||||||
Signals.addSignalMethods(Button.prototype);
|
Signals.addSignalMethods(Button.prototype);
|
||||||
|
|
||||||
/* SystemStatusButton:
|
/* SystemIndicator:
|
||||||
*
|
*
|
||||||
* This class manages one System Status indicator (network, keyboard,
|
* This class manages one system indicator, which are the icons
|
||||||
* volume, bluetooth...), which is just a PanelMenuButton with an
|
* that you see at the top right. A system indicator is composed
|
||||||
* icon.
|
* of an icon and a menu section, which will be composed into the
|
||||||
|
* aggregate menu.
|
||||||
*/
|
*/
|
||||||
const SystemStatusButton = new Lang.Class({
|
const SystemIndicator = new Lang.Class({
|
||||||
Name: 'SystemStatusButton',
|
Name: 'SystemIndicator',
|
||||||
Extends: Button,
|
Extends: Button,
|
||||||
|
|
||||||
_init: function(iconName, nameText) {
|
_init: function() {
|
||||||
this.parent(0.0, nameText);
|
this.parent(0.0);
|
||||||
this.actor.add_style_class_name('panel-status-button');
|
this.actor.add_style_class_name('panel-status-button');
|
||||||
|
|
||||||
this._box = new St.BoxLayout({ style_class: 'panel-status-button-box' });
|
this.indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box' });
|
||||||
this.actor.add_actor(this._box);
|
this.actor.add_actor(this.indicators);
|
||||||
|
|
||||||
if (iconName)
|
|
||||||
this.setIcon(iconName);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
get icons() {
|
addIndicator: function(gicon) {
|
||||||
return this._box.get_children();
|
|
||||||
},
|
|
||||||
|
|
||||||
addIcon: function(gicon) {
|
|
||||||
let icon = new St.Icon({ gicon: gicon,
|
let icon = new St.Icon({ gicon: gicon,
|
||||||
style_class: 'system-status-icon' });
|
style_class: 'system-status-icon' });
|
||||||
this._box.add_actor(icon);
|
this.indicators.add_actor(icon);
|
||||||
|
|
||||||
this.emit('icons-changed');
|
|
||||||
|
|
||||||
return icon;
|
return icon;
|
||||||
},
|
|
||||||
|
|
||||||
setIcon: function(iconName) {
|
|
||||||
if (!this.mainIcon)
|
|
||||||
this.mainIcon = this.addIcon(null);
|
|
||||||
this.mainIcon.icon_name = iconName;
|
|
||||||
},
|
|
||||||
|
|
||||||
setGIcon: function(gicon) {
|
|
||||||
if (this.mainIcon)
|
|
||||||
this.mainIcon.gicon = gicon;
|
|
||||||
else
|
|
||||||
this.mainIcon = this.addIcon(gicon);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -15,10 +15,12 @@ const PopupMenu = imports.ui.popupMenu;
|
|||||||
|
|
||||||
const Indicator = new Lang.Class({
|
const Indicator = new Lang.Class({
|
||||||
Name: 'BTIndicator',
|
Name: 'BTIndicator',
|
||||||
Extends: PanelMenu.SystemStatusButton,
|
Extends: PanelMenu.SystemIndicator,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent('bluetooth-disabled-symbolic', _("Bluetooth"));
|
this.parent();
|
||||||
|
|
||||||
|
this._indicator = this.addIndicator(new Gio.ThemedIcon({ name: 'bluetooth-active-symbolic' }));
|
||||||
|
|
||||||
// The Bluetooth menu only appears when Bluetooth is in use,
|
// The Bluetooth menu only appears when Bluetooth is in use,
|
||||||
// so just statically build it with a "Turn Off" menu item.
|
// so just statically build it with a "Turn Off" menu item.
|
||||||
@ -47,8 +49,8 @@ const Indicator = new Lang.Class({
|
|||||||
let nDevices = connectedDevices.length;
|
let nDevices = connectedDevices.length;
|
||||||
|
|
||||||
let on = nDevices > 0;
|
let on = nDevices > 0;
|
||||||
this.mainIcon.visible = on;
|
this._indicator.visible = on;
|
||||||
this.actor.visible = on;
|
this._item.actor.visible = on;
|
||||||
|
|
||||||
if (on)
|
if (on)
|
||||||
this._item.status.text = ngettext("%d Connected Device", "%d Connected Devices").format(nDevices);
|
this._item.status.text = ngettext("%d Connected Device", "%d Connected Devices").format(nDevices);
|
||||||
|
@ -37,26 +37,26 @@ const FakeStatusIcon = new Lang.Class({
|
|||||||
|
|
||||||
const Indicator = new Lang.Class({
|
const Indicator = new Lang.Class({
|
||||||
Name: 'LockScreenMenuIndicator',
|
Name: 'LockScreenMenuIndicator',
|
||||||
Extends: PanelMenu.SystemStatusButton,
|
Extends: PanelMenu.SystemIndicator,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent(null, _("Volume, network, battery"));
|
this.parent(null, _("Volume, network, battery"));
|
||||||
this._box.style_class = 'lock-screen-status-button-box';
|
this.indicators.style_class = 'lock-screen-status-button-box';
|
||||||
|
|
||||||
this._volumeControl = VolumeMenu.getMixerControl();
|
this._volumeControl = VolumeMenu.getMixerControl();
|
||||||
this._volumeMenu = new VolumeMenu.VolumeMenu(this._volumeControl);
|
this._volumeMenu = new VolumeMenu.VolumeMenu(this._volumeControl);
|
||||||
this.menu.addMenuItem(this._volumeMenu);
|
this.menu.addMenuItem(this._volumeMenu);
|
||||||
|
|
||||||
this._volume = new FakeStatusIcon(Main.panel.statusArea.volume);
|
this._volume = new FakeStatusIcon(Main.panel.statusArea.volume);
|
||||||
this._box.add_child(this._volume.actor);
|
this.indicators.add_child(this._volume.actor);
|
||||||
|
|
||||||
// Network may not exist if the user doesn't have NetworkManager
|
// Network may not exist if the user doesn't have NetworkManager
|
||||||
if (Main.panel.statusArea.network) {
|
if (Main.panel.statusArea.network) {
|
||||||
this._network = new FakeStatusIcon(Main.panel.statusArea.network);
|
this._network = new FakeStatusIcon(Main.panel.statusArea.network);
|
||||||
this._box.add_child(this._network.actor);
|
this.indicators.add_child(this._network.actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._battery = new FakeStatusIcon(Main.panel.statusArea.battery);
|
this._battery = new FakeStatusIcon(Main.panel.statusArea.battery);
|
||||||
this._box.add_child(this._battery.actor);
|
this.indicators.add_child(this._battery.actor);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1152,12 +1152,13 @@ Signals.addSignalMethods(NMVPNSection.prototype);
|
|||||||
|
|
||||||
const NMApplet = new Lang.Class({
|
const NMApplet = new Lang.Class({
|
||||||
Name: 'NMApplet',
|
Name: 'NMApplet',
|
||||||
Extends: PanelMenu.SystemStatusButton,
|
Extends: PanelMenu.SystemIndicator,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent('network-offline-symbolic', _('Network'));
|
this.parent();
|
||||||
|
|
||||||
this._vpnIcon = this.addIcon(null);
|
this._primaryIndicator = this.addIndicator(null);
|
||||||
|
this._vpnIndicator = this.addIndicator(null);
|
||||||
|
|
||||||
// Device types
|
// Device types
|
||||||
this._dtypes = { };
|
this._dtypes = { };
|
||||||
@ -1579,29 +1580,27 @@ const NMApplet = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_syncNMState: function() {
|
_syncNMState: function() {
|
||||||
this.mainIcon.visible = this._client.manager_running;
|
|
||||||
this.actor.visible = this.mainIcon.visible;
|
|
||||||
|
|
||||||
this._syncActiveConnections();
|
this._syncActiveConnections();
|
||||||
|
|
||||||
|
this.indicators.visible = this._client.manager_running;
|
||||||
this._section.actor.visible = this._client.networking_enabled;
|
this._section.actor.visible = this._client.networking_enabled;
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateIcon: function() {
|
_updateIcon: function() {
|
||||||
let hasApIcon = false;
|
let mc = this._mainConnection;
|
||||||
let hasMobileIcon = false;
|
|
||||||
|
|
||||||
if (!this._client.networking_enabled || !this._mainConnection) {
|
if (!this._client.networking_enabled || !mc) {
|
||||||
this.setIcon('network-offline-symbolic');
|
this._primaryIndicator.icon_name = 'network-offline-symbolic';
|
||||||
} else {
|
} else {
|
||||||
let dev = this._mainConnection._primaryDevice;
|
let dev = this._mainConnection._primaryDevice;
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
log('Active connection with no primary device?');
|
log('Active connection with no primary device?');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setIcon(dev.getIndicatorIcon());
|
this._primaryIndicator.icon_name = dev.getIndicatorIcon(mc);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._vpnIcon.icon_name = this._vpnSection.getIndicatorIcon();
|
this._vpnIndicator.icon_name = this._vpnSection.getIndicatorIcon();
|
||||||
this._vpnIcon.visible = (this._vpnIcon.icon_name != '');
|
this._vpnIndicator.visible = (this._vpnIndicator.icon_name != '');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -25,10 +25,12 @@ const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface);
|
|||||||
|
|
||||||
const Indicator = new Lang.Class({
|
const Indicator = new Lang.Class({
|
||||||
Name: 'PowerIndicator',
|
Name: 'PowerIndicator',
|
||||||
Extends: PanelMenu.SystemStatusButton,
|
Extends: PanelMenu.SystemIndicator,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent('battery-missing-symbolic', _("Battery"));
|
this.parent();
|
||||||
|
|
||||||
|
this._indicator = this.addIndicator(null);
|
||||||
|
|
||||||
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
|
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
|
||||||
Lang.bind(this, function(proxy, error) {
|
Lang.bind(this, function(proxy, error) {
|
||||||
@ -104,16 +106,14 @@ const Indicator = new Lang.Class({
|
|||||||
|
|
||||||
_syncIcon: function() {
|
_syncIcon: function() {
|
||||||
let icon = this._proxy.Icon;
|
let icon = this._proxy.Icon;
|
||||||
let hasIcon = false;
|
|
||||||
|
|
||||||
if (icon) {
|
if (icon) {
|
||||||
let gicon = Gio.icon_new_for_string(icon);
|
let gicon = Gio.icon_new_for_string(icon);
|
||||||
this.setGIcon(gicon);
|
this._indicator.gicon = gicon;
|
||||||
|
this._indicator.show();
|
||||||
this._item.icon.gicon = gicon;
|
this._item.icon.gicon = gicon;
|
||||||
hasIcon = true;
|
} else {
|
||||||
|
this._indicator.hide();
|
||||||
}
|
}
|
||||||
this.mainIcon.visible = hasIcon;
|
|
||||||
this.actor.visible = hasIcon;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_sync: function() {
|
_sync: function() {
|
||||||
|
@ -42,10 +42,12 @@ const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIf
|
|||||||
|
|
||||||
const Indicator = new Lang.Class({
|
const Indicator = new Lang.Class({
|
||||||
Name: 'SystemIndicator',
|
Name: 'SystemIndicator',
|
||||||
Extends: PanelMenu.SystemStatusButton,
|
Extends: PanelMenu.SystemIndicator,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent('system-shutdown-symbolic', _("System"));
|
this.parent();
|
||||||
|
|
||||||
|
this._indicator = this.addIndicator(new Gio.ThemedIcon({ name: 'system-shutdown-symbolic' }));
|
||||||
|
|
||||||
this._screenSaverSettings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
|
this._screenSaverSettings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
|
||||||
this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
|
this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
|
||||||
|
@ -296,22 +296,29 @@ const VolumeMenu = new Lang.Class({
|
|||||||
|
|
||||||
const Indicator = new Lang.Class({
|
const Indicator = new Lang.Class({
|
||||||
Name: 'VolumeIndicator',
|
Name: 'VolumeIndicator',
|
||||||
Extends: PanelMenu.SystemStatusButton,
|
Extends: PanelMenu.SystemIndicator,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent('audio-volume-muted-symbolic', _("Volume"));
|
this.parent();
|
||||||
|
|
||||||
|
this._primaryIndicator = this.addIndicator(null);
|
||||||
|
|
||||||
this._control = getMixerControl();
|
this._control = getMixerControl();
|
||||||
this._volumeMenu = new VolumeMenu(this._control);
|
this._volumeMenu = new VolumeMenu(this._control);
|
||||||
this._volumeMenu.connect('icon-changed', Lang.bind(this, function(menu) {
|
this._volumeMenu.connect('icon-changed', Lang.bind(this, function(menu) {
|
||||||
let icon = this._volumeMenu.getIcon();
|
let icon = this._volumeMenu.getIcon();
|
||||||
this.actor.visible = (icon != null);
|
|
||||||
this.setIcon(icon);
|
if (icon != null) {
|
||||||
|
this.indicators.show();
|
||||||
|
this._primaryIndicator.icon_name = icon;
|
||||||
|
} else {
|
||||||
|
this.indicators.hide();
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.menu.addMenuItem(this._volumeMenu);
|
this.menu.addMenuItem(this._volumeMenu);
|
||||||
|
|
||||||
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
this.indicators.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
||||||
},
|
},
|
||||||
|
|
||||||
_onScrollEvent: function(actor, event) {
|
_onScrollEvent: function(actor, event) {
|
||||||
|
Loading…
Reference in New Issue
Block a user