diff --git a/Makefile b/Makefile index 2f075b3..13ca75e 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ UUID = dash-to-panel@jderose9.github.com BASE_MODULES = extension.js stylesheet.css metadata.json COPYING README.md -EXTRA_MODULES = appIcons.js convenience.js panel.js intellihide.js panelStyle.js overview.js taskbar.js windowPreview.js prefs.js utils.js Settings.ui +EXTRA_MODULES = appIcons.js convenience.js panel.js panelManager.js intellihide.js panelStyle.js overview.js taskbar.js windowPreview.js prefs.js utils.js Settings.ui EXTRA_IMAGES = highlight_stacked_bg.svg TOLOCALIZE = prefs.js appIcons.js MSGSRC = $(wildcard po/*.po) diff --git a/appIcons.js b/appIcons.js index 3ace9b5..782f8b6 100644 --- a/appIcons.js +++ b/appIcons.js @@ -96,10 +96,11 @@ var taskbarAppIcon = new Lang.Class({ Name: 'DashToPanel.TaskbarAppIcon', Extends: AppDisplay.AppIcon, - _init: function(settings, appInfo, iconParams, onActivateOverride) { + _init: function(settings, appInfo, panel, iconParams, onActivateOverride) { // a prefix is required to avoid conflicting with the parent class variable this._dtpSettings = settings; + this.panel = panel; this._nWindows = 0; this.window = appInfo.window; this.isLauncher = appInfo.isLauncher; @@ -514,7 +515,7 @@ var taskbarAppIcon = new Lang.Class({ _setAppIconPadding: function() { let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; - let availSize = Main.panel.actor.get_height() - this._dtpSettings.get_int('dot-size') * scaleFactor * 2; + let availSize = this.panel.actor.get_height() - this._dtpSettings.get_int('dot-size') * scaleFactor * 2; let padding = this._dtpSettings.get_int('appicon-padding'); let margin = this._dtpSettings.get_int('appicon-margin'); diff --git a/extension.js b/extension.js index 97a8dd4..20bed89 100644 --- a/extension.js +++ b/extension.js @@ -20,7 +20,7 @@ const Me = imports.misc.extensionUtils.getCurrentExtension(); const Convenience = Me.imports.convenience; -const Panel = Me.imports.panel; +const PanelManager = Me.imports.panelManager; const Overview = Me.imports.overview; const Main = imports.ui.main; @@ -37,7 +37,7 @@ const Mainloop = imports.mainloop; const UBUNTU_DOCK_UUID = 'ubuntu-dock@ubuntu.com'; -let panel; +let panelManager; let overview; let settings; let oldDash; @@ -64,7 +64,7 @@ function _enable() { ExtensionSystem.extensionOrder.splice(ExtensionSystem.extensionOrder.indexOf(UBUNTU_DOCK_UUID), 1); //reset to prevent conflicts with the ubuntu-dock - if (panel) { + if (panelManager) { disable(true); } @@ -74,13 +74,13 @@ function _enable() { } } - if (panel) return; //already initialized + if (panelManager) return; //already initialized settings = Convenience.getSettings('org.gnome.shell.extensions.dash-to-panel'); - panel = new Panel.dtpPanel(settings); - panel.enable(); + panelManager = new PanelManager.dtpPanelManager(settings); + panelManager.enable(); overview = new Overview.dtpOverview(settings); - overview.enable(panel); + overview.enable(panelManager.primaryPanel); Main.wm.removeKeybinding('open-application-menu'); Main.wm.addKeybinding('open-application-menu', @@ -92,26 +92,26 @@ function _enable() { if(settings.get_boolean('show-appmenu')) Main.wm._toggleAppMenu(); else - panel.taskbar.popupFocusedAppSecondaryMenu(); + panelManager.primaryPanel.taskbar.popupFocusedAppSecondaryMenu(); }) ); // Pretend I'm the dash: meant to make appgrd swarm animation come from the // right position of the appShowButton. oldDash = Main.overview._dash; - Main.overview._dash = panel.taskbar; + Main.overview._dash = panelManager.primaryPanel.taskbar; } function disable(reset) { overview.disable(); - panel.disable(); + panelManager.disable(); settings.run_dispose(); Main.overview._dash = oldDash; oldDash=null; settings = null; overview = null; - panel = null; + panelManager = null; Main.wm.removeKeybinding('open-application-menu'); Main.wm.addKeybinding('open-application-menu', diff --git a/panel.js b/panel.js index 0aeaead..e0bb53c 100644 --- a/panel.js +++ b/panel.js @@ -36,7 +36,9 @@ const PanelStyle = Me.imports.panelStyle; const Lang = imports.lang; const Main = imports.ui.main; const Mainloop = imports.mainloop; +const CtrlAltTab = imports.ui.ctrlAltTab; const Layout = imports.ui.layout; +const Panel = imports.ui.panel; const St = imports.gi.St; const GLib = imports.gi.GLib; const Meta = imports.gi.Meta; @@ -51,22 +53,23 @@ const Intellihide = Me.imports.intellihide; let tracker = Shell.WindowTracker.get_default(); -var dtpPanel = new Lang.Class({ - Name: 'DashToPanel.Panel', +var dtpPanelWrapper = new Lang.Class({ + Name: 'DashToPanel.PanelWrapper', - _init: function(settings) { + _init: function(settings, monitor, panel, panelBox) { this._dtpSettings = settings; this.panelStyle = new PanelStyle.dtpPanelStyle(settings); - //rebuild panel when taskar-position change + //rebuild panel when taskar-position change this._dtpSettings.connect('changed::taskbar-position', Lang.bind(this, function() { this.disable(); this.enable(); })); + this.monitor = monitor; + this.panel = panel; + this.panelBox = panelBox; }, enable : function() { - this.panel = Main.panel; - let taskbarPosition = this._dtpSettings.get_string('taskbar-position'); if (taskbarPosition == 'CENTEREDCONTENT' || taskbarPosition == 'CENTEREDMONITOR') { this.container = this.panel._centerBox; @@ -74,7 +77,6 @@ var dtpPanel = new Lang.Class({ this.container = this.panel._leftBox; } this.appMenu = this.panel.statusArea.appMenu; - this.panelBox = Main.layoutManager.panelBox; this._oldPopupOpen = PopupMenu.PopupMenu.prototype.open; PopupMenu.PopupMenu.prototype.open = newPopupOpen; @@ -144,8 +146,9 @@ var dtpPanel = new Lang.Class({ }); this._panelConnectId = this.panel.actor.connect('allocate', Lang.bind(this, function(actor,box,flags){this._allocate(actor,box,flags);})); - this.panel._leftBox.remove_child(this.appMenu.container); - this.taskbar = new Taskbar.taskbar(this._dtpSettings); + if(this.appMenu) + this.panel._leftBox.remove_child(this.appMenu.container); + this.taskbar = new Taskbar.taskbar(this._dtpSettings, this.panel); Main.overview.dashIconSize = this.taskbar.iconSize; this.container.insert_child_at_index( this.taskbar.actor, 2 ); @@ -254,7 +257,8 @@ var dtpPanel = new Lang.Class({ this._signalsHandler.destroy(); this.container.remove_child(this.taskbar.actor); this._setAppmenuVisible(false); - this.panel._leftBox.add_child(this.appMenu.container); + if(this.appMenu) + this.panel._leftBox.add_child(this.appMenu.container); this.taskbar.destroy(); this.panel.actor.disconnect(this._panelConnectId); @@ -490,17 +494,15 @@ var dtpPanel = new Lang.Class({ if(!this.panel.actor.has_style_class_name('dashtopanelTop')) this.panel.actor.add_style_class_name('dashtopanelTop'); } else { - let primaryMonitor = Main.layoutManager.primaryMonitor; - - this.panelBox.set_anchor_point(0,(-1)*(primaryMonitor.height-this.panelBox.height)); + this.panelBox.set_anchor_point(0,(-1)*(this.monitor.height-this.panelBox.height)); if (!this._topLimit) { this._topLimit = new St.BoxLayout({ name: 'topLimit', vertical: true }); Main.layoutManager.addChrome(this._topLimit, { affectsStruts: true, trackFullscreen: true }); } - this._topLimit.set_position(primaryMonitor.x, primaryMonitor.y); - this._topLimit.set_size(primaryMonitor.width, -1); + this._topLimit.set_position(this.monitor.x, this.monitor.y); + this._topLimit.set_size(this.monitor.width, -1); // styles for theming if(this.panel.actor.has_style_class_name('dashtopanelTop')) @@ -528,13 +530,15 @@ var dtpPanel = new Lang.Class({ }, _setAppmenuVisible: function(isVisible) { - let parent = this.appMenu.container.get_parent(); + let parent; + if(this.appMenu) + parent = this.appMenu.container.get_parent(); if (parent) { parent.remove_child(this.appMenu.container); } - if (isVisible) { + if (isVisible && this.appMenu) { let taskbarPosition = this._dtpSettings.get_string('taskbar-position'); if (taskbarPosition == 'CENTEREDCONTENT' || taskbarPosition == 'CENTEREDMONITOR') { this.panel._leftBox.insert_child_above(this.appMenu.container, null); @@ -545,6 +549,9 @@ var dtpPanel = new Lang.Class({ }, _setClockLocation: function(loc) { + if(!this.panel.statusArea.dateMenu) + return; + let dateMenuContainer = this.panel.statusArea.dateMenu.container; let parent = dateMenuContainer.get_parent(); let destination; @@ -937,3 +944,97 @@ function newUpdatePanelBarrier() { directions: Meta.BarrierDirection.NEGATIVE_X }); } } + +var dtpSecondaryPanelBoxWrapper = new Lang.Class({ + Name: 'DashToPanel.SecondaryPanelBox', + + _init: function (monitor) { + this._rightPanelBarrier = null; + + this.panelBox = new St.BoxLayout({ name: 'panelBox', vertical: true }); + + Main.layoutManager.addChrome(this.panelBox, { affectsStruts: true, trackFullscreen: true }); + this.panelBox.set_position(monitor.x, monitor.y); + this.panelBox.set_size(monitor.width, -1); + Main.uiGroup.set_child_below_sibling(this.panelBox, Main.layoutManager.panelBox); + + this._panelBoxChangedId = this.panelBox.connect('allocation-changed', Lang.bind(this, this._panelBoxChanged)); + + this.panel = new dtpSecondaryPanel(); + this.panelBox.add(this.panel.actor); + }, + + destroy: function () { + if (this._rightPanelBarrier) { + this._rightPanelBarrier.destroy(); + this._rightPanelBarrier = null; + } + + this.panelBox.disconnect(this._panelBoxChangedId); + this.panelBox.destroy(); + }, + + updatePanel: function(monitor) { + this.panelBox.set_position(monitor.x, monitor.y); + this.panelBox.set_size(monitor.width, -1); + }, + + _panelBoxChanged: function(self, box, flags) { + if (this._rightPanelBarrier) { + this._rightPanelBarrier.destroy(); + this._rightPanelBarrier = null; + } + + if (this.panelBox.height) { + this._rightPanelBarrier = new Meta.Barrier({ display: global.display, + x1: box.get_x() + box.get_width(), y1: box.get_y(), + x2: box.get_x() + box.get_width(), y2: box.get_y() + this.panelBox.height, + directions: Meta.BarrierDirection.NEGATIVE_X }); + } + }, +}); + +var dtpSecondaryPanel = new Lang.Class({ + Name: 'DashToPanel.SecondaryPanel', + Extends: Panel.Panel, + + _init : function(monitorIndex, panelBox) { + this.monitorIndex = monitorIndex; + this.panelBox = panelBox; + + this.actor = new Shell.GenericContainer({ name: 'panel', reactive: true }); + this.actor._delegate = this; + + this._sessionStyle = null; + + this.statusArea = {}; + + this.menuManager = new PopupMenu.PopupMenuManager(this); + + this._leftBox = new St.BoxLayout({ name: 'panelLeft' }); + this.actor.add_actor(this._leftBox); + this._centerBox = new St.BoxLayout({ name: 'panelCenter' }); + this.actor.add_actor(this._centerBox); + this._rightBox = new St.BoxLayout({ name: 'panelRight' }); + this.actor.add_actor(this._rightBox); + + this._leftCorner = new Panel.PanelCorner(St.Side.LEFT); + this.actor.add_actor(this._leftCorner.actor); + + this._rightCorner = new Panel.PanelCorner(St.Side.RIGHT); + this.actor.add_actor(this._rightCorner.actor); + + this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); + + Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar")+" "+this.monitorIndex, 'focus-top-bar-symbolic', + { sortGroup: CtrlAltTab.SortGroup.TOP }); + + }, + + _onDestroy: function(actor) { + Main.ctrlAltTabManager.removeGroup(this.actor); + + this.actor._delegate = null; + }, + +}); \ No newline at end of file diff --git a/panelManager.js b/panelManager.js new file mode 100644 index 0000000..f954a15 --- /dev/null +++ b/panelManager.js @@ -0,0 +1,75 @@ +/* + * 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 . + * + * 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 Panel = Me.imports.panel; +const Main = imports.ui.main; +const Lang = imports.lang; +const St = imports.gi.St; + +var dtpPanelManager = new Lang.Class({ + Name: 'DashToDock.DockManager', + + _init: function(settings) { + this._dtpSettings = settings; + }, + + enable: function() { + this.primaryPanel = new Panel.dtpPanelWrapper(this._dtpSettings, Main.layoutManager.primaryMonitor, Main.panel, Main.layoutManager.panelBox); + this.primaryPanel.enable(); + this.allPanels = [ this.primaryPanel ]; + + Main.layoutManager.monitors.forEach(monitor => { + if(monitor == Main.layoutManager.primaryMonitor) + return; + + let panelBox = new St.BoxLayout({ name: 'dashtopanelSecondaryPanelBox', vertical: true }); + Main.layoutManager.addChrome(panelBox, { affectsStruts: true, trackFullscreen: true }); + Main.uiGroup.set_child_below_sibling(panelBox, Main.layoutManager.panelBox); + + let panel = new Panel.dtpSecondaryPanel(); + panelBox.add(panel.actor); + + panelBox.set_position(monitor.x, monitor.y); + panelBox.set_size(monitor.width, -1); + + let panelWrapper = new Panel.dtpPanelWrapper(this._dtpSettings, monitor, panel, panelBox); + panelWrapper.enable(panelWrapper); + + this.allPanels.push(panelWrapper); + }) + }, + + disable: function() { + this.allPanels.forEach(p => { + p.disable(); + }) + } + +}); diff --git a/taskbar.js b/taskbar.js index 2b86273..97eef6d 100644 --- a/taskbar.js +++ b/taskbar.js @@ -175,8 +175,9 @@ var taskbarActor = new Lang.Class({ var taskbar = new Lang.Class({ Name: 'DashToPanel.Taskbar', - _init : function(settings) { + _init : function(settings, panel) { this._dtpSettings = settings; + this.panel = panel; // start at smallest size due to running indicator drawing area expanding but not shrinking this.iconSize = 16; @@ -250,12 +251,12 @@ var taskbar = new Lang.Class({ this._signalsHandler.add( [ - Main.panel.actor, + this.panel.actor, 'notify::height', () => this._queueRedisplay() ], [ - Main.panel.actor, + this.panel.actor, 'notify::width', () => this._queueRedisplay() ], @@ -497,6 +498,7 @@ var taskbar = new Lang.Class({ window: window, isLauncher: isLauncher }, + this.panel, { setSizeManually: true, showLabel: false @@ -689,7 +691,7 @@ var taskbar = new Lang.Class({ // Getting the panel height and making sure that the icon padding is at // least the size of the app running indicator on both the top and bottom. - let availSize = (Main.panel.actor.get_height() - + let availSize = (this.panel.actor.get_height() - (this._dtpSettings.get_int('dot-size') * scaleFactor * 2) - (this._dtpSettings.get_int('appicon-padding') * 2)) / scaleFactor;