diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index f9b1ccec7..dac6f631c 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -339,7 +339,8 @@ StTooltip StLabel { } .panel-button { - padding: 0px 12px; + -natural-hpadding: 12px; + -minimum-hpadding: 6px; font-weight: bold; color: #ccc; transition-duration: 100; diff --git a/js/ui/dateMenu.js b/js/ui/dateMenu.js index 37ce87b6d..7196f0c8b 100644 --- a/js/ui/dateMenu.js +++ b/js/ui/dateMenu.js @@ -60,7 +60,7 @@ DateMenuButton.prototype = { PanelMenu.Button.prototype._init.call(this, menuAlignment); this._clock = new St.Label(); - this.actor.set_child(this._clock); + this.actor.add_actor(this._clock); hbox = new St.BoxLayout({name: 'calendarArea' }); this.menu.addActor(hbox); diff --git a/js/ui/panel.js b/js/ui/panel.js index b4f18efa5..2146874a6 100644 --- a/js/ui/panel.js +++ b/js/ui/panel.js @@ -249,7 +249,7 @@ AppMenuButton.prototype = { this._targetApp = null; let bin = new St.Bin({ name: 'appMenu' }); - this.actor.set_child(bin); + this.actor.add_actor(bin); this.actor.reactive = false; this._targetIsCurrent = false; @@ -564,10 +564,10 @@ ActivitiesButton.prototype = { PanelMenu.Button.prototype._init.call(this, 0.0); let container = new Shell.GenericContainer(); - container.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth)); - container.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight)); - container.connect('allocate', Lang.bind(this, this._allocate)); - this.actor.child = container; + container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth)); + container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight)); + container.connect('allocate', Lang.bind(this, this._containerAllocate)); + this.actor.add_actor(container); this.actor.name = 'panelActivities'; /* Translators: If there is no suitable word for "Activities" @@ -599,15 +599,15 @@ ActivitiesButton.prototype = { this._xdndTimeOut = 0; }, - _getPreferredWidth: function(actor, forHeight, alloc) { + _containerGetPreferredWidth: function(actor, forHeight, alloc) { [alloc.min_size, alloc.natural_size] = this._label.get_preferred_width(forHeight); }, - _getPreferredHeight: function(actor, forWidth, alloc) { + _containerGetPreferredHeight: function(actor, forWidth, alloc) { [alloc.min_size, alloc.natural_size] = this._label.get_preferred_height(forWidth); }, - _allocate: function(actor, box, flags) { + _containerAllocate: function(actor, box, flags) { this._label.allocate(box, flags); // The hot corner needs to be outside any padding/alignment @@ -1102,16 +1102,17 @@ Panel.prototype = { } icon.height = PANEL_ICON_SIZE; - let bin = new St.Bin({ style_class: 'panel-button' }); - bin.child = icon; + let buttonBox = new PanelMenu.ButtonBox(); + let box = buttonBox.actor; + box.add_actor(icon); - this._insertStatusItem(bin, this._status_area_order.indexOf(role)); + this._insertStatusItem(box, this._status_area_order.indexOf(role)); }, _onTrayIconRemoved: function(o, icon) { - let bin = icon.get_parent(); - if (bin && bin instanceof St.Bin) - bin.destroy(); + let box = icon.get_parent(); + if (box && box._delegate instanceof PanelMenu.ButtonBox) + box.destroy(); }, }; diff --git a/js/ui/panelMenu.js b/js/ui/panelMenu.js index 582ac2edd..9dbf594e5 100644 --- a/js/ui/panelMenu.js +++ b/js/ui/panelMenu.js @@ -2,26 +2,110 @@ const Clutter = imports.gi.Clutter; const Gtk = imports.gi.Gtk; +const Lang = imports.lang; +const Shell = imports.gi.Shell; const Signals = imports.signals; const St = imports.gi.St; -const Lang = imports.lang; -const PopupMenu = imports.ui.popupMenu; const Main = imports.ui.main; +const Params = imports.misc.params; +const PopupMenu = imports.ui.popupMenu; + +function ButtonBox(params) { + this._init.apply(this, arguments); +}; + +ButtonBox.prototype = { + _init: function(params) { + params = Params.parse(params, { style_class: 'panel-button' }, true); + this.actor = new Shell.GenericContainer(params); + this.actor._delegate = this; + + this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth)); + this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight)); + this.actor.connect('allocate', Lang.bind(this, this._allocate)); + + this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged)); + this._minHPadding = this._natHPadding = 0.0; + }, + + _onStyleChanged: function(actor) { + let themeNode = actor.get_theme_node(); + + this._minHPadding = themeNode.get_length('-minimum-hpadding'); + this._natHPadding = themeNode.get_length('-natural-hpadding'); + }, + + _getPreferredWidth: function(actor, forHeight, alloc) { + let children = actor.get_children(); + let child = children.length > 0 ? children[0] : null; + + if (child) { + [alloc.min_size, alloc.natural_size] = child.get_preferred_width(-1); + } else { + alloc.min_size = alloc.natural_size = 0; + } + + alloc.min_size += 2 * this._minHPadding; + alloc.natural_size += 2 * this._natHPadding; + }, + + _getPreferredHeight: function(actor, forWidth, alloc) { + let children = actor.get_children(); + let child = children.length > 0 ? children[0] : null; + + if (child) { + [alloc.min_size, alloc.natural_size] = child.get_preferred_height(-1); + } else { + alloc.min_size = alloc.natural_size = 0; + } + }, + + _allocate: function(actor, box, flags) { + let children = actor.get_children(); + if (children.length == 0) + return; + + let child = children[0]; + let [minWidth, natWidth] = child.get_preferred_width(-1); + let [minHeight, natHeight] = child.get_preferred_height(-1); + + let availWidth = box.x2 - box.x1; + let availHeight = box.y2 - box.y1; + + let childBox = new Clutter.ActorBox(); + if (natWidth + 2 * this._natHPadding <= availWidth) { + childBox.x1 = this._natHPadding; + childBox.x2 = availWidth - this._natHPadding; + } else { + childBox.x1 = this._minHPadding; + childBox.x2 = availWidth - this._minHPadding; + } + + if (natHeight <= availHeight) { + childBox.y1 = Math.floor((availHeight - natHeight) / 2); + childBox.y2 = childBox.y1 + natHeight; + } else { + childBox.y1 = 0; + childBox.y2 = availHeight; + } + + child.allocate(childBox, flags); + }, +} function Button(menuAlignment) { this._init(menuAlignment); } Button.prototype = { + __proto__: ButtonBox.prototype, + _init: function(menuAlignment) { - this.actor = new St.Bin({ style_class: 'panel-button', - reactive: true, - can_focus: true, - x_fill: true, - y_fill: false, - track_hover: true }); - this.actor._delegate = this; + ButtonBox.prototype._init.call(this, { reactive: true, + can_focus: true, + track_hover: true }); + this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress)); this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress)); this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP); @@ -112,7 +196,7 @@ SystemStatusButton.prototype = { this._iconActor = new St.Icon({ icon_name: iconName, icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' }); - this.actor.set_child(this._iconActor); + this.actor.add_actor(this._iconActor); this.actor.add_style_class_name('panel-status-button'); this.setTooltip(tooltipText); }, diff --git a/js/ui/status/keyboard.js b/js/ui/status/keyboard.js index baa6f8461..e344425a9 100644 --- a/js/ui/status/keyboard.js +++ b/js/ui/status/keyboard.js @@ -52,7 +52,7 @@ XKBIndicator.prototype = { this._container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth)); this._container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight)); this._container.connect('allocate', Lang.bind(this, this._containerAllocate)); - this.actor.set_child(this._container); + this.actor.add_actor(this._container); this.actor.add_style_class_name('panel-status-button'); this._iconActor = new St.Icon({ icon_name: 'keyboard', icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' }); diff --git a/js/ui/userMenu.js b/js/ui/userMenu.js index e81d49931..607d66c70 100644 --- a/js/ui/userMenu.js +++ b/js/ui/userMenu.js @@ -364,7 +364,7 @@ UserMenuButton.prototype = { _init: function() { PanelMenu.Button.prototype._init.call(this, 0.0); let box = new St.BoxLayout({ name: 'panelUserMenu' }); - this.actor.set_child(box); + this.actor.add_actor(box); this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });