Oreon-Lime-R2/dash-to-panel/dash-to-panel-44/panel.js

1512 lines
59 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* This file is part of the Dash-To-Panel extension for Gnome 3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Credits:
* This file is based on code from the Dash to Dock extension by micheleg
* and code from the Taskbar extension by Zorin OS
*
* Code to re-anchor the panel was taken from Thoma5 BottomPanel:
* https://github.com/Thoma5/gnome-shell-extension-bottompanel
*
* Pattern for moving clock based on Frippery Move Clock by R M Yorston
* http://frippery.org/extensions/
*
* Some code was also adapted from the upstream Gnome Shell source code.
*/
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Clutter = imports.gi.Clutter;
const Config = imports.misc.config;
const Gtk = imports.gi.Gtk;
const Gi = imports._gi;
const AppIcons = Me.imports.appIcons;
const Utils = Me.imports.utils;
const Taskbar = Me.imports.taskbar;
const Pos = Me.imports.panelPositions;
const PanelSettings = Me.imports.panelSettings;
const PanelStyle = Me.imports.panelStyle;
const Lang = imports.lang;
const Main = imports.ui.main;
const Mainloop = imports.mainloop;
const Dash = imports.ui.dash;
const CtrlAltTab = imports.ui.ctrlAltTab;
const Panel = imports.ui.panel;
const PanelMenu = imports.ui.panelMenu;
const St = imports.gi.St;
const GLib = imports.gi.GLib;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const DND = imports.ui.dnd;
const Shell = imports.gi.Shell;
const PopupMenu = imports.ui.popupMenu;
const IconGrid = imports.ui.iconGrid;
const DateMenu = imports.ui.dateMenu;
const Volume = imports.ui.status.volume;
const Progress = Me.imports.progress;
const Intellihide = Me.imports.intellihide;
const Transparency = Me.imports.transparency;
const _ = imports.gettext.domain(Me.imports.utils.TRANSLATION_DOMAIN).gettext;
let tracker = Shell.WindowTracker.get_default();
var panelBoxes = ['_leftBox', '_centerBox', '_rightBox'];
//timeout names
const T1 = 'startDynamicTransparencyTimeout';
const T2 = 'startIntellihideTimeout';
const T3 = 'allocationThrottleTimeout';
const T4 = 'showDesktopTimeout';
const T5 = 'trackerFocusAppTimeout';
const T6 = 'scrollPanelDelayTimeout';
const T7 = 'waitPanelBoxAllocation';
var dtpPanel = Utils.defineClass({
Name: 'DashToPanel-Panel',
Extends: St.Widget,
_init: function(panelManager, monitor, panelBox, isStandalone) {
this.callParent('_init', { layout_manager: new Clutter.BinLayout() });
this._timeoutsHandler = new Utils.TimeoutsHandler();
this._signalsHandler = new Utils.GlobalSignalsHandler();
this.panelManager = panelManager;
this.panelStyle = new PanelStyle.dtpPanelStyle();
this.monitor = monitor;
this.panelBox = panelBox;
// when the original gnome-shell top panel is kept, all panels are "standalone",
// so in this case use isPrimary to get the panel on the primary dtp monitor, which
// might be different from the system's primary monitor.
this.isStandalone = isStandalone;
this.isPrimary = !isStandalone || (Me.settings.get_boolean('stockgs-keep-top-panel') &&
monitor == panelManager.dtpPrimaryMonitor);
this._sessionStyle = null;
this._unmappedButtons = [];
this._elementGroups = [];
this.cornerSize = 0;
let position = this.getPosition();
if (isStandalone) {
this.panel = new dtpSecondaryPanel({ name: 'panel', reactive: true });
this.statusArea = this.panel.statusArea = {};
Utils.wrapActor(this.panel);
//next 3 functions are needed by other extensions to add elements to the secondary panel
this.panel.addToStatusArea = function(role, indicator, position, box) {
return Main.panel.addToStatusArea.call(this, role, indicator, position, box);
};
this.panel._addToPanelBox = function(role, indicator, position, box) {
Main.panel._addToPanelBox.call(this, role, indicator, position, box);
};
this.panel._onMenuSet = function(indicator) {
Main.panel._onMenuSet.call(this, indicator);
};
this._leftBox = this.panel._leftBox = new St.BoxLayout({ name: 'panelLeft' });
this._centerBox = this.panel._centerBox = new St.BoxLayout({ name: 'panelCenter' });
this._rightBox = this.panel._rightBox = new St.BoxLayout({ name: 'panelRight' });
this.menuManager = this.panel.menuManager = new PopupMenu.PopupMenuManager(this.panel);
this._setPanelMenu('aggregateMenu', dtpSecondaryAggregateMenu, this.panel.actor);
this._setPanelMenu('dateMenu', DateMenu.DateMenuButton, this.panel.actor);
this._setPanelMenu('activities', Panel.ActivitiesButton, this.panel.actor);
this.panel.add_child(this._leftBox);
this.panel.add_child(this._centerBox);
this.panel.add_child(this._rightBox);
} else {
this.panel = Main.panel;
this.statusArea = Main.panel.statusArea;
this.menuManager = Main.panel.menuManager;
panelBoxes.forEach(p => this[p] = Main.panel[p]);
['activities', 'aggregateMenu', 'dateMenu'].forEach(b => {
let container = this.statusArea[b].container;
let parent = container.get_parent();
container._dtpOriginalParent = parent;
parent ? parent.remove_child(container) : null;
this.panel.actor.add_child(container);
});
}
// Create a wrapper around the real showAppsIcon in order to add a popupMenu. Most of
// its behavior is handled by the taskbar, but its positioning is done at the panel level
this.showAppsIconWrapper = new AppIcons.ShowAppsIconWrapper(this);
this.panel.actor.add_child(this.showAppsIconWrapper.realShowAppsIcon);
this.panel.actor._delegate = this;
Utils.wrapActor(this.statusArea.activities);
this.add_child(this.panel.actor);
if (Main.panel._onButtonPress || Main.panel._tryDragWindow) {
this._signalsHandler.add([
this.panel.actor,
[
'button-press-event',
'touch-event'
],
this._onButtonPress.bind(this)
]);
}
if (Main.panel._onKeyPress) {
this._signalsHandler.add([this.panel.actor, 'key-press-event', Main.panel._onKeyPress.bind(this)]);
}
Main.ctrlAltTabManager.addGroup(this, _("Top Bar")+" "+ monitor.index, 'focus-top-bar-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.TOP });
},
enable : function() {
let position = this.getPosition();
if (this.statusArea.aggregateMenu) {
Utils.getIndicators(this.statusArea.aggregateMenu._volume)._dtpIgnoreScroll = 1;
}
this.geom = this.getGeometry();
// The overview uses the panel height as a margin by way of a "ghost" transparent Clone
// This pushes everything down, which isn't desired when the panel is moved to the bottom
// I'm adding a 2nd ghost panel and will resize the top or bottom ghost depending on the panel position
this._myPanelGhost = new Clutter.Actor({
x: this.geom.x,
y: this.geom.y ,
reactive: false,
opacity: 0
});
let isTop = this.geom.position == St.Side.TOP;
if (isTop) {
this.panel._leftCorner = this.panel._leftCorner || new Panel.PanelCorner(St.Side.LEFT);
this.panel._rightCorner = this.panel._rightCorner || new Panel.PanelCorner(St.Side.RIGHT);
Main.overview._overview.insert_child_at_index(this._myPanelGhost, 0);
} else {
let overviewControls = Main.overview._overview._controls || Main.overview._controls;
Main.overview._overview.add_actor(this._myPanelGhost);
}
if (this.panel._leftCorner) {
Utils.wrapActor(this.panel._leftCorner);
Utils.wrapActor(this.panel._rightCorner);
if (isTop) {
if (this.isStandalone) {
this.panel.actor.add_child(this.panel._leftCorner.actor);
this.panel.actor.add_child(this.panel._rightCorner.actor);
}
} else if (Config.PACKAGE_VERSION >= '3.32') {
this.panel.actor.remove_child(this.panel._leftCorner.actor);
this.panel.actor.remove_child(this.panel._rightCorner.actor);
}
}
this._setPanelPosition();
if (!this.isStandalone) {
if (this.panel.vfunc_allocate) {
this._panelConnectId = 0;
Utils.hookVfunc(this.panel.__proto__, 'allocate', (box, flags) => this._mainPanelAllocate(0, box, flags));
} else {
this._panelConnectId = this.panel.actor.connect('allocate', (actor, box, flags) => this._mainPanelAllocate(actor, box, flags));
}
// remove the extra space before the clock when the message-indicator is displayed
if (DateMenu.IndicatorPad) {
Utils.hookVfunc(DateMenu.IndicatorPad.prototype, 'get_preferred_width', () => [0,0]);
Utils.hookVfunc(DateMenu.IndicatorPad.prototype, 'get_preferred_height', () => [0,0]);
}
}
if (!DateMenu.IndicatorPad && this.statusArea.dateMenu) {
//3.36 switched to a size constraint applied on an anonymous child
let indicatorPad = this.statusArea.dateMenu.get_first_child().get_first_child();
this._dateMenuIndicatorPadContraints = indicatorPad.get_constraints();
indicatorPad.clear_constraints();
}
// The main panel's connection to the "allocate" signal is competing with this extension
// trying to move the centerBox over to the right, creating a never-ending cycle.
// Since we don't have the ID to disconnect that handler, wrap the allocate() function
// it calls instead. If the call didn't originate from this file, ignore it.
panelBoxes.forEach(b => {
this[b].allocate = (box, flags, isFromDashToPanel) => {
if (isFromDashToPanel) {
Utils.allocate(this[b], box, flags, true);
}
}
});
this.menuManager._oldChangeMenu = this.menuManager._changeMenu;
this.menuManager._changeMenu = (menu) => {
if (!Me.settings.get_boolean('stockgs-panelbtn-click-only')) {
this.menuManager._oldChangeMenu(menu);
}
};
this.dynamicTransparency = new Transparency.DynamicTransparency(this);
this.taskbar = new Taskbar.taskbar(this);
this.panel.actor.add_child(this.taskbar.actor);
this._setAppmenuVisible(Me.settings.get_boolean('show-appmenu'));
this._setShowDesktopButton(true);
this._setAllocationMap();
this.panel.actor.add_style_class_name('dashtopanelMainPanel ' + this.getOrientation());
this._setPanelGhostSize();
this._timeoutsHandler.add([T2, Me.settings.get_int('intellihide-enable-start-delay'), () => this.intellihide = new Intellihide.Intellihide(this)]);
this._signalsHandler.add(
// this is to catch changes to the theme or window scale factor
[
Utils.getStageTheme(),
'changed',
() => (this._resetGeometry(), this._setShowDesktopButtonStyle()),
],
[
// sync hover after a popupmenu is closed
this.taskbar,
'menu-closed',
Lang.bind(this, function(){this.panel.actor.sync_hover();})
],
[
Main.overview,
[
'showing',
'hiding'
],
() => this._adjustForOverview()
],
[
Main.overview,
'hidden',
() => {
if (this.isPrimary) {
//reset the primary monitor when exiting the overview
this.panelManager.setFocusedMonitor(this.monitor, true);
}
}
],
[
this.statusArea.activities.actor,
'captured-event',
(actor, e) => {
// todo this is not being called right now, so the overview is not shown on the correct monitor
if (e.type() == Clutter.EventType.BUTTON_PRESS || e.type() == Clutter.EventType.TOUCH_BEGIN) {
//temporarily use as primary the monitor on which the activities btn was clicked
this.panelManager.setFocusedMonitor(this.monitor, true);
}
}
],
[
this._centerBox,
'actor-added',
() => this._onBoxActorAdded(this._centerBox)
],
[
this._rightBox,
'actor-added',
() => this._onBoxActorAdded(this._rightBox)
],
[
this.panel.actor,
'scroll-event',
this._onPanelMouseScroll.bind(this)
],
[
Main.layoutManager,
'startup-complete',
() => this._resetGeometry()
]
);
this._bindSettingsChanges();
this.panelStyle.enable(this);
if (this.checkIfVertical()) {
this._signalsHandler.add([
this.panelBox,
'notify::visible',
() => {
if (this.panelBox.visible) {
this._refreshVerticalAlloc();
}
}
]);
this._setSearchEntryOffset(this.geom.w);
if (this.statusArea.dateMenu) {
this._formatVerticalClock();
this._signalsHandler.add([
this.statusArea.dateMenu._clock,
'notify::clock',
() => this._formatVerticalClock()
]);
}
}
// Since we are usually visible but not usually changing, make sure
// most repaint requests don't actually require us to repaint anything.
// This saves significant CPU when repainting the screen.
this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._initProgressManager();
},
disable: function () {
this.panelStyle.disable();
this._timeoutsHandler.destroy();
this._signalsHandler.destroy();
this._disablePanelCornerSignals();
this.panel.actor.remove_child(this.taskbar.actor);
this._setAppmenuVisible(false);
if (this.intellihide) {
this.intellihide.destroy();
}
this.dynamicTransparency.destroy();
this.progressManager.destroy();
this.taskbar.destroy();
this.showAppsIconWrapper.destroy();
this.menuManager._changeMenu = this.menuManager._oldChangeMenu;
this._myPanelGhost.get_parent().remove_actor(this._myPanelGhost);
this._setSearchEntryOffset(0);
panelBoxes.forEach(b => delete this[b].allocate);
this._unmappedButtons.forEach(a => this._disconnectVisibleId(a));
if (this._dateMenuIndicatorPadContraints && this.statusArea.dateMenu) {
let indicatorPad = this.statusArea.dateMenu.get_first_child().get_first_child();
this._dateMenuIndicatorPadContraints.forEach(c => indicatorPad.add_constraint(c));
}
this._setVertical(this.panel.actor, false);
if (!this.isStandalone) {
this.statusArea.dateMenu._clockDisplay.text = this.statusArea.dateMenu._clock.clock;
['vertical', 'horizontal', 'dashtopanelMainPanel'].forEach(c => this.panel.actor.remove_style_class_name(c));
if (!Main.sessionMode.isLocked) {
[['activities', 0], ['aggregateMenu', -1], ['dateMenu', 0]].forEach(b => {
let container = this.statusArea[b[0]].container;
let originalParent = container._dtpOriginalParent;
this.panel.actor.remove_child(container);
originalParent ? originalParent.insert_child_at_index(container, b[1]) : null;
delete container._dtpOriginalParent;
});
}
if (!this.panel._leftCorner.actor.mapped) {
this.panel.actor.add_child(this.panel._leftCorner.actor);
this.panel.actor.add_child(this.panel._rightCorner.actor);
}
this._setShowDesktopButton(false);
delete Utils.getIndicators(this.statusArea.aggregateMenu._volume)._dtpIgnoreScroll;
if (DateMenu.IndicatorPad) {
Utils.hookVfunc(DateMenu.IndicatorPad.prototype, 'get_preferred_width', DateMenu.IndicatorPad.prototype.vfunc_get_preferred_width);
Utils.hookVfunc(DateMenu.IndicatorPad.prototype, 'get_preferred_height', DateMenu.IndicatorPad.prototype.vfunc_get_preferred_height);
}
if (this._panelConnectId) {
this.panel.actor.disconnect(this._panelConnectId);
} else {
Utils.hookVfunc(this.panel.__proto__, 'allocate', this.panel.__proto__.vfunc_allocate);
}
this.panel.actor._delegate = this.panel;
} else {
this._removePanelMenu('dateMenu');
this._removePanelMenu('aggregateMenu');
this._removePanelMenu('activities');
}
Main.ctrlAltTabManager.removeGroup(this);
},
handleDragOver: function(source, actor, x, y, time) {
if (source == Main.xdndHandler) {
// open overview so they can choose a window for focusing
// and ultimately dropping dragged item onto
if(Main.overview.shouldToggleByCornerOrButton())
Main.overview.show();
}
return DND.DragMotionResult.CONTINUE;
},
getPosition: function() {
let position = PanelSettings.getPanelPosition(Me.settings, this.monitor.index);
if (position == Pos.TOP) {
return St.Side.TOP;
} else if (position == Pos.RIGHT) {
return St.Side.RIGHT;
} else if (position == Pos.BOTTOM) {
return St.Side.BOTTOM;
}
return St.Side.LEFT;
},
checkIfVertical: function() {
let position = this.getPosition();
return (position == St.Side.LEFT || position == St.Side.RIGHT);
},
getOrientation: function() {
return (this.checkIfVertical() ? 'vertical' : 'horizontal');
},
updateElementPositions: function() {
let panelPositions = this.panelManager.panelsElementPositions[this.monitor.index] || Pos.defaults;
this._updateGroupedElements(panelPositions);
this._disablePanelCornerSignals();
if (this.getPosition() == St.Side.TOP) {
let visibleElements = panelPositions.filter(pp => pp.visible);
let connectCorner = (corner, button) => {
corner._button = button;
corner._buttonStyleChangedSignalId = button.connect('style-changed', () => {
corner.set_style_pseudo_class(button.get_style_pseudo_class());
});
}
if (visibleElements[0].element == Pos.ACTIVITIES_BTN) {
connectCorner(this.panel._leftCorner, this.statusArea.activities);
}
if (visibleElements[visibleElements.length - 1].element == Pos.SYSTEM_MENU) {
connectCorner(this.panel._rightCorner, this.statusArea.aggregateMenu);
}
}
this.panel.actor.hide();
this.panel.actor.show();
},
_updateGroupedElements: function(panelPositions) {
let previousPosition = 0;
let previousCenteredPosition = 0;
let currentGroup = -1;
this._elementGroups = [];
panelPositions.forEach(pos => {
let allocationMap = this.allocationMap[pos.element];
if (allocationMap.actor) {
allocationMap.actor.visible = pos.visible;
if (!pos.visible) {
return;
}
let currentPosition = pos.position;
let isCentered = Pos.checkIfCentered(currentPosition);
if (currentPosition == Pos.STACKED_TL && previousPosition == Pos.STACKED_BR) {
currentPosition = Pos.STACKED_BR;
}
if (!previousPosition ||
(previousPosition == Pos.STACKED_TL && currentPosition != Pos.STACKED_TL) ||
(previousPosition != Pos.STACKED_BR && currentPosition == Pos.STACKED_BR) ||
(isCentered && previousPosition != currentPosition && previousPosition != Pos.STACKED_BR)) {
this._elementGroups[++currentGroup] = { elements: [], index: this._elementGroups.length, expandableIndex: -1 };
previousCenteredPosition = 0;
}
if (pos.element == Pos.TASKBAR) {
this._elementGroups[currentGroup].expandableIndex = this._elementGroups[currentGroup].elements.length;
}
if (isCentered && !this._elementGroups[currentGroup].isCentered) {
this._elementGroups[currentGroup].isCentered = 1;
previousCenteredPosition = currentPosition;
}
this._elementGroups[currentGroup].position = previousCenteredPosition || currentPosition;
this._elementGroups[currentGroup].elements.push(allocationMap);
allocationMap.position = currentPosition;
previousPosition = currentPosition;
}
});
},
_disablePanelCornerSignals: function() {
if (this.panel._rightCorner && this.panel._rightCorner._buttonStyleChangedSignalId) {
this.panel._rightCorner._button.disconnect(this.panel._rightCorner._buttonStyleChangedSignalId);
delete this.panel._rightCorner._buttonStyleChangedSignalId;
}
if (this.panel._leftCorner && this.panel._leftCorner._buttonStyleChangedSignalId) {
this.panel._leftCorner._button.disconnect(this.panel._leftCorner._buttonStyleChangedSignalId);
delete this.panel._leftCorner._buttonStyleChangedSignalId;
}
},
_bindSettingsChanges: function() {
let isVertical = this.checkIfVertical();
this._signalsHandler.add(
[
Me.settings,
[
'changed::panel-sizes',
'changed::group-apps'
],
() => this._resetGeometry()
],
[
Me.settings,
[
'changed::appicon-margin',
'changed::appicon-padding'
],
() => this.taskbar.resetAppIcons()
],
[
Me.settings,
'changed::show-appmenu',
() => this._setAppmenuVisible(Me.settings.get_boolean('show-appmenu'))
],
[
Me.settings,
[
'changed::showdesktop-button-width',
'changed::trans-use-custom-bg',
'changed::desktop-line-use-custom-color',
'changed::desktop-line-custom-color',
'changed::trans-bg-color'
],
() => this._setShowDesktopButtonStyle()
],
[
Me.desktopSettings,
'changed::clock-format',
() => {
this._clockFormat = null;
if (isVertical) {
this._formatVerticalClock();
}
}
],
[
Me.settings,
'changed::progress-show-bar',
() => this._initProgressManager()
],
[
Me.settings,
'changed::progress-show-count',
() => this._initProgressManager()
]
);
if (isVertical) {
this._signalsHandler.add([Me.settings, 'changed::group-apps-label-max-width', () => this._resetGeometry()]);
}
},
_setPanelMenu: function(propName, constr, container) {
if (!this.statusArea[propName]) {
this.statusArea[propName] = this._getPanelMenu(propName, constr);
this.menuManager.addMenu(this.statusArea[propName].menu);
container.insert_child_at_index(this.statusArea[propName].container, 0);
}
},
_removePanelMenu: function(propName) {
if (this.statusArea[propName]) {
let parent = this.statusArea[propName].container.get_parent();
if (parent) {
parent.remove_actor(this.statusArea[propName].container);
}
//calling this.statusArea[propName].destroy(); is buggy for now, gnome-shell never
//destroys those panel menus...
//since we can't destroy the menu (hence properly disconnect its signals), let's
//store it so the next time a panel needs one of its kind, we can reuse it instead
//of creating a new one
let panelMenu = this.statusArea[propName];
this.menuManager.removeMenu(panelMenu.menu);
Me.persistentStorage[propName].push(panelMenu);
this.statusArea[propName] = null;
}
},
_getPanelMenu: function(propName, constr) {
Me.persistentStorage[propName] = Me.persistentStorage[propName] || [];
if (!Me.persistentStorage[propName].length) {
Me.persistentStorage[propName].push(new constr());
}
return Me.persistentStorage[propName].pop();
},
_setPanelGhostSize: function() {
this._myPanelGhost.set_size(this.width, this.checkIfVertical() ? 1 : this.height);
},
_setSearchEntryOffset: function(offset) {
if (this.isPrimary) {
//In the overview, when the panel is vertical the search-entry is the only element
//that doesn't natively take into account the size of a side dock, as it is always
//centered relatively to the monitor. This looks misaligned, adjust it here so it
//is centered like the rest of the overview elements.
let paddingSide = this.getPosition() == St.Side.LEFT ? 'left' : 'right';
let scaleFactor = Utils.getScaleFactor();
let style = offset ? 'padding-' + paddingSide + ':' + (offset / scaleFactor) + 'px;' : null;
let searchEntry = Main.overview._overview._controls._searchEntry;
searchEntry.get_parent().set_style(style);
}
},
_adjustForOverview: function() {
let isFocusedMonitor = this.panelManager.checkIfFocusedMonitor(this.monitor);
let isOverview = !!Main.overview.visibleTarget;
let isOverviewFocusedMonitor = isOverview && isFocusedMonitor;
let isShown = !isOverview || isOverviewFocusedMonitor;
this.panelBox[isShown ? 'show' : 'hide']();
if (isOverview) {
this._myPanelGhost[isOverviewFocusedMonitor ? 'show' : 'hide']();
if (isOverviewFocusedMonitor) {
Utils.getPanelGhost().set_size(1, this.geom.position == St.Side.TOP ? 0 : 32);
}
}
},
_resetGeometry: function() {
this.geom = this.getGeometry();
this._setPanelGhostSize();
this._setPanelPosition();
this.taskbar.resetAppIcons(true);
this.dynamicTransparency.updateExternalStyle();
if (this.intellihide && this.intellihide.enabled) {
this.intellihide.reset();
}
if (this.checkIfVertical()) {
this.showAppsIconWrapper.realShowAppsIcon.toggleButton.set_width(this.geom.w);
this._refreshVerticalAlloc();
this._setSearchEntryOffset(this.geom.w);
}
},
getGeometry: function() {
let scaleFactor = Utils.getScaleFactor();
let panelBoxTheme = this.panelBox.get_theme_node();
let lrPadding = panelBoxTheme.get_padding(St.Side.RIGHT) + panelBoxTheme.get_padding(St.Side.LEFT);
let topPadding = panelBoxTheme.get_padding(St.Side.TOP);
let tbPadding = topPadding + panelBoxTheme.get_padding(St.Side.BOTTOM);
let position = this.getPosition();
let length = PanelSettings.getPanelLength(Me.settings, this.monitor.index) / 100;
let anchor = PanelSettings.getPanelAnchor(Me.settings, this.monitor.index);
let anchorPlaceOnMonitor = 0;
let gsTopPanelOffset = 0;
let x = 0, y = 0;
let w = 0, h = 0;
const panelSize = PanelSettings.getPanelSize(Me.settings, this.monitor.index);
this.dtpSize = panelSize * scaleFactor;
if (Me.settings.get_boolean('stockgs-keep-top-panel') && Main.layoutManager.primaryMonitor == this.monitor) {
gsTopPanelOffset = Main.layoutManager.panelBox.height - topPadding;
}
if (this.checkIfVertical()) {
if (!Me.settings.get_boolean('group-apps')) {
// add window title width and side padding of _dtpIconContainer when vertical
this.dtpSize += Me.settings.get_int('group-apps-label-max-width') + AppIcons.DEFAULT_PADDING_SIZE * 2 / scaleFactor;
}
this.sizeFunc = 'get_preferred_height',
this.fixedCoord = { c1: 'x1', c2: 'x2' },
this.varCoord = { c1: 'y1', c2: 'y2' };
w = this.dtpSize;
h = this.monitor.height * length - tbPadding - gsTopPanelOffset;
} else {
this.sizeFunc = 'get_preferred_width';
this.fixedCoord = { c1: 'y1', c2: 'y2' };
this.varCoord = { c1: 'x1', c2: 'x2' };
w = this.monitor.width * length - lrPadding;
h = this.dtpSize;
}
if (position == St.Side.TOP || position == St.Side.LEFT) {
x = this.monitor.x;
y = this.monitor.y + gsTopPanelOffset;
} else if (position == St.Side.RIGHT) {
x = this.monitor.x + this.monitor.width - this.dtpSize - lrPadding;
y = this.monitor.y + gsTopPanelOffset;
} else { //BOTTOM
x = this.monitor.x;
y = this.monitor.y + this.monitor.height - this.dtpSize - tbPadding;
}
if (this.checkIfVertical()) {
let viewHeight = this.monitor.height - gsTopPanelOffset;
if (anchor === Pos.MIDDLE) {
anchorPlaceOnMonitor = (viewHeight - h) / 2;
} else if (anchor === Pos.END) {
anchorPlaceOnMonitor = viewHeight - h;
} else { // Pos.START
anchorPlaceOnMonitor = 0;
}
y = y + anchorPlaceOnMonitor;
} else {
if (anchor === Pos.MIDDLE) {
anchorPlaceOnMonitor = (this.monitor.width - w) / 2;
} else if (anchor === Pos.END) {
anchorPlaceOnMonitor = this.monitor.width - w;
} else { // Pos.START
anchorPlaceOnMonitor = 0;
}
x = x + anchorPlaceOnMonitor;
}
return {
x: x, y: y,
w: w, h: h,
lrPadding: lrPadding,
tbPadding: tbPadding,
position: position
};
},
_setAllocationMap: function() {
this.allocationMap = {};
let setMap = (name, actor, isBox) => this.allocationMap[name] = {
actor: actor,
isBox: isBox || 0,
box: new Clutter.ActorBox()
};
setMap(Pos.SHOW_APPS_BTN, this.showAppsIconWrapper.realShowAppsIcon);
setMap(Pos.ACTIVITIES_BTN, this.statusArea.activities ? this.statusArea.activities.container : 0);
setMap(Pos.LEFT_BOX, this._leftBox, 1);
setMap(Pos.TASKBAR, this.taskbar.actor);
setMap(Pos.CENTER_BOX, this._centerBox, 1);
setMap(Pos.DATE_MENU, this.statusArea.dateMenu.container);
setMap(Pos.SYSTEM_MENU, this.statusArea.aggregateMenu.container);
setMap(Pos.RIGHT_BOX, this._rightBox, 1);
setMap(Pos.DESKTOP_BTN, this._showDesktopButton);
},
_mainPanelAllocate: function(actor, box, flags) {
Utils.setAllocation(this.panel.actor, box, flags);
},
vfunc_allocate: function(box, flags) {
Utils.setAllocation(this, box, flags);
let fixed = 0;
let centeredMonitorGroup;
let panelAlloc = new Clutter.ActorBox({ x1: 0, y1: 0, x2: this.geom.w, y2: this.geom.h });
let assignGroupSize = (group, update) => {
group.size = 0;
group.tlOffset = 0;
group.brOffset = 0;
group.elements.forEach(element => {
if (!update) {
element.box[this.fixedCoord.c1] = panelAlloc[this.fixedCoord.c1];
element.box[this.fixedCoord.c2] = panelAlloc[this.fixedCoord.c2];
element.natSize = element.actor[this.sizeFunc](-1)[1];
}
if (!group.isCentered || Pos.checkIfCentered(element.position)) {
group.size += element.natSize;
} else if (element.position == Pos.STACKED_TL) { 
group.tlOffset += element.natSize;
} else { // Pos.STACKED_BR
group.brOffset += element.natSize;
}
});
if (group.isCentered) {
group.size += Math.max(group.tlOffset, group.brOffset) * 2;
group.tlOffset = Math.max(group.tlOffset - group.brOffset, 0);
}
};
let allocateGroup = (group, tlLimit, brLimit) => {
let startPosition = tlLimit;
let currentPosition = 0;
if (group.expandableIndex >= 0) {
let availableSize = brLimit - tlLimit;
let expandable = group.elements[group.expandableIndex];
let i = 0;
let l = this._elementGroups.length;
let tlSize = 0;
let brSize = 0;
if (centeredMonitorGroup && (centeredMonitorGroup != group || expandable.position != Pos.CENTERED_MONITOR)) {
if (centeredMonitorGroup.index < group.index || (centeredMonitorGroup == group && expandable.position == Pos.STACKED_TL)) {
i = centeredMonitorGroup.index;
} else {
l = centeredMonitorGroup.index;
}
}
for (; i < l; ++i) {
let refGroup = this._elementGroups[i];
if (i < group.index && (!refGroup.fixed || refGroup[this.varCoord.c2] > tlLimit)) {
tlSize += refGroup.size;
} else if (i > group.index && (!refGroup.fixed || refGroup[this.varCoord.c1] < brLimit)) {
brSize += refGroup.size;
}
}
if (group.isCentered) {
availableSize -= Math.max(tlSize, brSize) * 2;
} else {
availableSize -= tlSize + brSize;
}
if (availableSize < group.size) {
expandable.natSize -= (group.size - availableSize) * (group.isCentered && !Pos.checkIfCentered(expandable.position) ? .5 : 1);
assignGroupSize(group, true);
}
}
if (group.isCentered) {
startPosition = tlLimit + (brLimit - tlLimit - group.size) * .5;
} else if (group.position == Pos.STACKED_BR) {
startPosition = brLimit - group.size;
}
currentPosition = group.tlOffset + startPosition;
group.elements.forEach(element => {
element.box[this.varCoord.c1] = Math.round(currentPosition);
element.box[this.varCoord.c2] = Math.round((currentPosition += element.natSize));
if (element.isBox) {
return element.actor.allocate(element.box, flags, true);
}
Utils.allocate(element.actor, element.box, flags, false);
});
group[this.varCoord.c1] = startPosition;
group[this.varCoord.c2] = currentPosition;
group.fixed = 1;
++fixed;
};
Utils.allocate(this.panel.actor, panelAlloc, flags);
this._elementGroups.forEach(group => {
group.fixed = 0;
assignGroupSize(group);
if (group.position == Pos.CENTERED_MONITOR) {
centeredMonitorGroup = group;
}
});
if (centeredMonitorGroup) {
allocateGroup(centeredMonitorGroup, panelAlloc[this.varCoord.c1], panelAlloc[this.varCoord.c2]);
}
let iterations = 0; //failsafe
while (fixed < this._elementGroups.length && ++iterations < 10) {
for (let i = 0, l = this._elementGroups.length; i < l; ++i) {
let group = this._elementGroups[i];
if (group.fixed) {
continue;
}
let prevGroup = this._elementGroups[i - 1];
let nextGroup = this._elementGroups[i + 1];
let prevLimit = prevGroup && prevGroup.fixed ? prevGroup[this.varCoord.c2] :
centeredMonitorGroup && group.index > centeredMonitorGroup.index ? centeredMonitorGroup[this.varCoord.c2] : panelAlloc[this.varCoord.c1];
let nextLimit = nextGroup && nextGroup.fixed ? nextGroup[this.varCoord.c1] :
centeredMonitorGroup && group.index < centeredMonitorGroup.index ? centeredMonitorGroup[this.varCoord.c1] : panelAlloc[this.varCoord.c2];
if (group.position == Pos.STACKED_TL) {
allocateGroup(group, panelAlloc[this.varCoord.c1], nextLimit);
} else if (group.position == Pos.STACKED_BR) {
allocateGroup(group, prevLimit, panelAlloc[this.varCoord.c2]);
} else if ((!prevGroup || prevGroup.fixed) && (!nextGroup || nextGroup.fixed)) { // CENTERED
allocateGroup(group, prevLimit, nextLimit);
}
}
}
if (this.geom.position == St.Side.TOP) {
let childBoxLeftCorner = new Clutter.ActorBox();
let childBoxRightCorner = new Clutter.ActorBox();
let currentCornerSize = this.cornerSize;
let panelAllocFixedSize = box[this.fixedCoord.c2] - box[this.fixedCoord.c1];
[ , this.cornerSize] = this.panel._leftCorner.actor[this.sizeFunc](-1);
childBoxLeftCorner[this.varCoord.c1] = 0;
childBoxLeftCorner[this.varCoord.c2] = this.cornerSize;
childBoxLeftCorner[this.fixedCoord.c1] = panelAllocFixedSize;
childBoxLeftCorner[this.fixedCoord.c2] = panelAllocFixedSize + this.cornerSize;
childBoxRightCorner[this.varCoord.c1] = box[this.varCoord.c2] - this.cornerSize;
childBoxRightCorner[this.varCoord.c2] = box[this.varCoord.c2];
childBoxRightCorner[this.fixedCoord.c1] = panelAllocFixedSize;
childBoxRightCorner[this.fixedCoord.c2] = panelAllocFixedSize + this.cornerSize;
Utils.allocate(this.panel._leftCorner.actor, childBoxLeftCorner, flags);
Utils.allocate(this.panel._rightCorner.actor, childBoxRightCorner, flags);
if (this.cornerSize != currentCornerSize) {
this._setPanelClip();
}
}
},
_setPanelPosition: function() {
let clipContainer = this.panelBox.get_parent();
this.set_size(this.geom.w, this.geom.h);
clipContainer.set_position(this.geom.x, this.geom.y);
this._setVertical(this.panel.actor, this.checkIfVertical());
// styles for theming
Object.keys(St.Side).forEach(p => {
let cssName = 'dashtopanel' + p.charAt(0) + p.slice(1).toLowerCase();
this.panel.actor[(St.Side[p] == this.geom.position ? 'add' : 'remove') + '_style_class_name'](cssName);
});
this._setPanelClip(clipContainer);
Main.layoutManager._updateHotCorners();
Main.layoutManager._updatePanelBarrier(this);
},
_setPanelClip: function(clipContainer) {
clipContainer = clipContainer || this.panelBox.get_parent();
this._timeoutsHandler.add([T7, 0, () => Utils.setClip(clipContainer, clipContainer.x, clipContainer.y, this.panelBox.width, this.panelBox.height + this.cornerSize)]);
},
_onButtonPress: function(actor, event) {
let type = event.type();
let isPress = type == Clutter.EventType.BUTTON_PRESS;
let button = isPress ? event.get_button() : -1;
let [stageX, stageY] = event.get_coords();
if (button == 3 && global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, stageX, stageY) == this.panel.actor) {
//right click on an empty part of the panel, temporarily borrow and display the showapps context menu
Main.layoutManager.setDummyCursorGeometry(stageX, stageY, 0, 0);
this.showAppsIconWrapper.createMenu();
this.showAppsIconWrapper._menu.sourceActor = Main.layoutManager.dummyCursor;
this.showAppsIconWrapper.popupMenu();
return Clutter.EVENT_STOP;
} else if (Main.modalCount > 0 || event.get_source() != actor ||
(!isPress && type != Clutter.EventType.TOUCH_BEGIN) ||
(isPress && button != 1)) {
return Clutter.EVENT_PROPAGATE;
}
let params = this.checkIfVertical() ? [stageY, 'y', 'height'] : [stageX, 'x', 'width'];
let dragWindow = this._getDraggableWindowForPosition.apply(this, params.concat(['maximized_' + this.getOrientation() + 'ly']));
if (!dragWindow)
return Clutter.EVENT_PROPAGATE;
global.display.begin_grab_op(dragWindow,
Meta.GrabOp.MOVING,
false, /* pointer grab */
true, /* frame action */
button,
event.get_state(),
event.get_time(),
stageX, stageY);
return Clutter.EVENT_STOP;
},
_getDraggableWindowForPosition: function(stageCoord, coord, dimension, maximizedProp) {
let workspace = Utils.getCurrentWorkspace();
let allWindowsByStacking = global.display.sort_windows_by_stacking(
workspace.list_windows()
).reverse();
return Utils.find(allWindowsByStacking, metaWindow => {
let rect = metaWindow.get_frame_rect();
return metaWindow.get_monitor() == this.monitor.index &&
metaWindow.showing_on_its_workspace() &&
metaWindow.get_window_type() != Meta.WindowType.DESKTOP &&
metaWindow[maximizedProp] &&
stageCoord > rect[coord] && stageCoord < rect[coord] + rect[dimension];
});
},
_onBoxActorAdded: function(box) {
if (this.checkIfVertical()) {
this._setVertical(box, true);
}
},
_refreshVerticalAlloc: function() {
this._setVertical(this._centerBox, true);
this._setVertical(this._rightBox, true);
this._formatVerticalClock();
},
_setVertical: function(actor, isVertical) {
let _set = (actor, isVertical) => {
if (!actor || actor instanceof Dash.DashItemContainer || actor instanceof Taskbar.TaskbarItemContainer) {
return;
}
if (actor instanceof St.BoxLayout) {
actor.vertical = isVertical;
} else if ((actor._delegate || actor) instanceof PanelMenu.ButtonBox && actor != this.statusArea.appMenu) {
let child = actor.get_first_child();
if (isVertical && !actor.visible && !actor._dtpVisibleId) {
this._unmappedButtons.push(actor);
actor._dtpVisibleId = actor.connect('notify::visible', () => {
this._disconnectVisibleId(actor);
this._refreshVerticalAlloc();
});
actor._dtpDestroyId = actor.connect('destroy', () => this._disconnectVisibleId(actor));
}
if (child) {
let [, natWidth] = actor.get_preferred_width(-1);
child.x_align = Clutter.ActorAlign[isVertical ? 'CENTER' : 'START'];
actor.set_width(isVertical ? this.dtpSize : -1);
isVertical = isVertical && (natWidth > this.dtpSize);
actor[(isVertical ? 'add' : 'remove') + '_style_class_name']('vertical');
}
}
actor.get_children().forEach(c => _set(c, isVertical));
};
_set(actor, false);
_set(actor, isVertical);
},
_disconnectVisibleId: function(actor) {
actor.disconnect(actor._dtpVisibleId);
actor.disconnect(actor._dtpDestroyId);
delete actor._dtpVisibleId;
delete actor._dtpDestroyId;
this._unmappedButtons.splice(this._unmappedButtons.indexOf(actor), 1);
},
_setAppmenuVisible: function(isVisible) {
let parent;
let appMenu = this.statusArea.appMenu;
if(appMenu)
parent = appMenu.container.get_parent();
if (parent) {
parent.remove_child(appMenu.container);
}
if (isVisible && appMenu) {
this._leftBox.insert_child_above(appMenu.container, null);
}
},
_formatVerticalClock: function() {
// https://github.com/GNOME/gnome-desktop/blob/master/libgnome-desktop/gnome-wall-clock.c#L310
if (this.statusArea.dateMenu) {
let datetime = this.statusArea.dateMenu._clock.clock;
let datetimeParts = datetime.split('');
let time = datetimeParts[1];
let clockText = this.statusArea.dateMenu._clockDisplay.clutter_text;
let setClockText = text => {
let stacks = text instanceof Array;
let separator = '\n<span size="xx-small">‧‧</span>\n';
clockText.set_text((stacks ? text.join(separator) : text).trim());
clockText.set_use_markup(stacks);
clockText.get_allocation_box();
return !clockText.get_layout().is_ellipsized();
};
if (clockText.ellipsize == Pango.EllipsizeMode.NONE) {
//on gnome-shell 3.36.4, the clockdisplay isn't ellipsize anymore, so set it back
clockText.ellipsize = Pango.EllipsizeMode.END;
}
if (!time) {
datetimeParts = datetime.split(' ');
time = datetimeParts.pop();
datetimeParts = [datetimeParts.join(' '), time];
}
if (!setClockText(datetime) &&
!setClockText(datetimeParts) &&
!setClockText(time)) {
let timeParts = time.split('');
if (!this._clockFormat) {
this._clockFormat = Me.desktopSettings.get_string('clock-format');
}
if (this._clockFormat == '12h') {
timeParts.push.apply(timeParts, timeParts.pop().split(' '));
}
setClockText(timeParts);
}
}
},
_setShowDesktopButton: function (add) {
if (add) {
if(this._showDesktopButton)
return;
this._showDesktopButton = new St.Bin({ style_class: 'showdesktop-button',
reactive: true,
can_focus: true,
// x_fill: true,
// y_fill: true,
track_hover: true });
this._setShowDesktopButtonStyle();
this._showDesktopButton.connect('button-press-event', () => this._onShowDesktopButtonPress());
this._showDesktopButton.connect('enter-event', () => {
this._showDesktopButton.add_style_class_name(this._getBackgroundBrightness() ?
'showdesktop-button-light-hovered' : 'showdesktop-button-dark-hovered');
if (Me.settings.get_boolean('show-showdesktop-hover')) {
this._timeoutsHandler.add([T4, Me.settings.get_int('show-showdesktop-delay'), () => {
this._hiddenDesktopWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace();
this._toggleWorkspaceWindows(true, this._hiddenDesktopWorkspace);
}]);
}
});
this._showDesktopButton.connect('leave-event', () => {
this._showDesktopButton.remove_style_class_name(this._getBackgroundBrightness() ?
'showdesktop-button-light-hovered' : 'showdesktop-button-dark-hovered');
if (Me.settings.get_boolean('show-showdesktop-hover')) {
if (this._timeoutsHandler.getId(T4)) {
this._timeoutsHandler.remove(T4);
} else if (this._hiddenDesktopWorkspace) {
this._toggleWorkspaceWindows(false, this._hiddenDesktopWorkspace);
}
 }
});
this.panel.actor.add_child(this._showDesktopButton);
} else {
if(!this._showDesktopButton)
return;
this.panel.actor.remove_child(this._showDesktopButton);
this._showDesktopButton.destroy();
this._showDesktopButton = null;
}
},
_setShowDesktopButtonStyle: function() {
let rgb = this._getBackgroundBrightness() ? "rgba(55, 55, 55, .2)" : "rgba(200, 200, 200, .2)";
let isLineCustom = Me.settings.get_boolean('desktop-line-use-custom-color');
rgb = isLineCustom ? Me.settings.get_string('desktop-line-custom-color') : rgb;
if (this._showDesktopButton) {
let buttonSize = Me.settings.get_int('showdesktop-button-width') + 'px;';
let isVertical = this.checkIfVertical();
let sytle = "border: 0 solid " + rgb + ";";
sytle += isVertical ? 'border-top-width:1px;height:' + buttonSize : 'border-left-width:1px;width:' + buttonSize;
this._showDesktopButton.set_style(sytle);
this._showDesktopButton[(isVertical ? 'x' : 'y') + '_expand'] = true;
}
},
// _getBackgroundBrightness: return true if panel has a bright background color
_getBackgroundBrightness: function() {
return Utils.checkIfColorIsBright(this.dynamicTransparency.backgroundColorRgb);
},
_toggleWorkspaceWindows: function(hide, workspace) {
let time = Me.settings.get_int('show-showdesktop-time') * .001;
workspace.list_windows().forEach(w => {
if (!w.minimized) {
let tweenOpts = {
opacity: hide ? 0 : 255,
time: time,
transition: 'easeOutQuad'
};
Utils.animateWindowOpacity(w.get_compositor_private(), tweenOpts);
}
});
},
_onShowDesktopButtonPress: function() {
let label = 'trackerFocusApp';
this._signalsHandler.removeWithLabel(label);
this._timeoutsHandler.remove(T5);
if(this._restoreWindowList && this._restoreWindowList.length) {
this._timeoutsHandler.remove(T4);
let current_workspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace();
let windows = current_workspace.list_windows();
this._restoreWindowList.forEach(function(w) {
if(windows.indexOf(w) > -1)
Main.activateWindow(w);
});
this._restoreWindowList = null;
} else {
let current_workspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace();
let windows = current_workspace.list_windows().filter(function (w) {
return w.showing_on_its_workspace() && !w.skip_taskbar;
});
windows = global.display.sort_windows_by_stacking(windows);
windows.forEach(function(w) {
w.minimize();
});
this._restoreWindowList = windows;
this._timeoutsHandler.add([T5, 20, () => this._signalsHandler.addWithLabel(
label,
[
tracker,
'notify::focus-app',
() => this._restoreWindowList = null
]
)]);
}
Main.overview.hide();
},
_onPanelMouseScroll: function(actor, event) {
let scrollAction = Me.settings.get_string('scroll-panel-action');
let direction = Utils.getMouseScrollDirection(event);
if (!this._checkIfIgnoredScrollSource(event.get_source()) && !this._timeoutsHandler.getId(T6)) {
if (direction && scrollAction === 'SWITCH_WORKSPACE') {
let args = [global.display];
//adjust for horizontal workspaces
if (Utils.DisplayWrapper.getWorkspaceManager().layout_rows === 1) {
direction = direction == 'up' ? 'left' : 'right';
}
//gnome-shell < 3.30 needs an additional "screen" param
global.screen ? args.push(global.screen) : 0;
let showWsPopup = Me.settings.get_boolean('scroll-panel-show-ws-popup');
showWsPopup ? 0 : Main.wm._workspaceSwitcherPopup = { display: () => {} };
Main.wm._showWorkspaceSwitcher.apply(Main.wm, args.concat([0, { get_name: () => 'switch---' + direction }]));
showWsPopup ? 0 : Main.wm._workspaceSwitcherPopup = null;
} else if (direction && scrollAction === 'CYCLE_WINDOWS') {
let windows = this.taskbar.getAppInfos().reduce((ws, appInfo) => ws.concat(appInfo.windows), []);
Utils.activateSiblingWindow(windows, direction);
} else if (scrollAction === 'CHANGE_VOLUME' && !event.is_pointer_emulated()) {
var proto = Volume.Indicator.prototype;
var func = proto._handleScrollEvent || proto.vfunc_scroll_event || proto._onScrollEvent;
func.call(Main.panel.statusArea.aggregateMenu._volume, 0, event);
} else {
return;
}
var scrollDelay = Me.settings.get_int('scroll-panel-delay');
if (scrollDelay) {
this._timeoutsHandler.add([T6, scrollDelay, () => {}]);
}
}
},
_checkIfIgnoredScrollSource: function(source) {
let ignoredConstr = ['WorkspaceIndicator'];
return source.get_parent()._dtpIgnoreScroll || ignoredConstr.indexOf(source.constructor.name) >= 0;
},
_initProgressManager: function() {
if(!this.progressManager && (Me.settings.get_boolean('progress-show-bar') || Me.settings.get_boolean('progress-show-count')))
this.progressManager = new Progress.ProgressManager();
},
});
var dtpSecondaryPanel = Utils.defineClass({
Name: 'DashToPanel-SecondaryPanel',
Extends: St.Widget,
_init: function(params) {
this.callParent('_init', params);
},
vfunc_allocate: function(box, flags) {
Utils.setAllocation(this, box, flags);
}
});
var dtpSecondaryAggregateMenu = Utils.defineClass({
Name: 'DashToPanel-SecondaryAggregateMenu',
Extends: PanelMenu.Button,
_init: function() {
this.callParent('_init', 0.0, C_("System menu in the top bar", "System"), false);
Utils.wrapActor(this);
this.menu.actor.add_style_class_name('aggregate-menu');
let menuLayout = new Panel.AggregateLayout();
this.menu.box.set_layout_manager(menuLayout);
this._indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box' });
this.actor.add_child(this._indicators);
this._power = new imports.ui.status.power.Indicator();
this._volume = new imports.ui.status.volume.Indicator();
this._brightness = new imports.ui.status.brightness.Indicator();
this._system = new imports.ui.status.system.Indicator();
if (Config.PACKAGE_VERSION >= '3.28') {
this._thunderbolt = new imports.ui.status.thunderbolt.Indicator();
this._indicators.add_child(Utils.getIndicators(this._thunderbolt));
}
if (Config.PACKAGE_VERSION < '3.37') {
this._screencast = new imports.ui.status.screencast.Indicator();
this._indicators.add_child(Utils.getIndicators(this._screencast));
}
if (Config.PACKAGE_VERSION >= '3.24') {
this._nightLight = new imports.ui.status.nightLight.Indicator();
this._indicators.add_child(Utils.getIndicators(this._nightLight));
}
if (Config.HAVE_NETWORKMANAGER && Config.PACKAGE_VERSION >= '3.24') {
this._network = new imports.ui.status.network.NMApplet();
this._indicators.add_child(Utils.getIndicators(this._network));
}
if (Config.HAVE_BLUETOOTH) {
this._bluetooth = new imports.ui.status.bluetooth.Indicator();
this._indicators.add_child(Utils.getIndicators(this._bluetooth));
}
this._indicators.add_child(Utils.getIndicators(this._volume));
this._indicators.add_child(Utils.getIndicators(this._power));
this.menu.addMenuItem(this._volume.menu);
this._volume._volumeMenu._readOutput();
this._volume._volumeMenu._readInput();
this.menu.addMenuItem(this._brightness.menu);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
if (this._network) {
this.menu.addMenuItem(this._network.menu);
}
if (this._bluetooth) {
this.menu.addMenuItem(this._bluetooth.menu);
}
this.menu.addMenuItem(this._power.menu);
this._power._sync();
if (this._nightLight) {
this.menu.addMenuItem(this._nightLight.menu);
}
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addMenuItem(this._system.menu);
menuLayout.addSizeChild(this._power.menu.actor);
menuLayout.addSizeChild(this._system.menu.actor);
},
});