/* * 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. */ import * as Overview from './overview.js'; import * as Panel from './panel.js'; import * as PanelSettings from './panelSettings.js'; import * as Proximity from './proximity.js'; import * as Utils from './utils.js'; import * as DesktopIconsIntegration from './desktopIconsIntegration.js'; import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; import Clutter from 'gi://Clutter'; import Meta from 'gi://Meta'; import Shell from 'gi://Shell'; import St from 'gi://St'; import * as BoxPointer from 'resource:///org/gnome/shell/ui/boxpointer.js'; import * as LookingGlass from 'resource:///org/gnome/shell/ui/lookingGlass.js'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; import * as Layout from 'resource:///org/gnome/shell/ui/layout.js'; import {InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; import {SETTINGS} from './extension.js'; import {SecondaryMonitorDisplay, WorkspacesView} from 'resource:///org/gnome/shell/ui/workspacesView.js'; export const PanelManager = class { constructor() { this.overview = new Overview.Overview(); this.panelsElementPositions = {}; this._injectionManager = new InjectionManager(); this._saveMonitors(); } enable(reset) { let dtpPrimaryIndex = SETTINGS.get_int('primary-monitor'); this.allPanels = []; this.dtpPrimaryMonitor = Main.layoutManager.monitors[dtpPrimaryIndex] || Main.layoutManager.primaryMonitor; this.proximityManager = new Proximity.ProximityManager(); if (this.dtpPrimaryMonitor) { this.primaryPanel = this._createPanel(this.dtpPrimaryMonitor, SETTINGS.get_boolean('stockgs-keep-top-panel')); this.allPanels.push(this.primaryPanel); this.overview.enable(this.primaryPanel); this.setFocusedMonitor(this.dtpPrimaryMonitor); } if (SETTINGS.get_boolean('multi-monitors')) { Main.layoutManager.monitors.filter(m => m != this.dtpPrimaryMonitor).forEach(m => { this.allPanels.push(this._createPanel(m, true)); }); } global.dashToPanel.panels = this.allPanels; global.dashToPanel.emit('panels-created'); this.allPanels.forEach(p => { let panelPosition = p.getPosition(); let leftOrRight = (panelPosition == St.Side.LEFT || panelPosition == St.Side.RIGHT); p.panelBox.set_size( leftOrRight ? -1 : p.geom.w + p.geom.lrPadding, leftOrRight ? p.geom.h + p.geom.tbPadding : -1 ); this._findPanelMenuButtons(p.panelBox).forEach(pmb => this._adjustPanelMenuButton(pmb, p.monitor, panelPosition)); p.taskbar.iconAnimator.start(); }); this._setDesktopIconsMargins(); //in 3.32, BoxPointer now inherits St.Widget if (BoxPointer.BoxPointer.prototype.vfunc_get_preferred_height) { let panelManager = this; this._injectionManager.overrideMethod(BoxPointer.BoxPointer.prototype, 'vfunc_get_preferred_height', () => function(forWidth) { let alloc = { min_size: 0, natural_size: 0 }; [alloc.min_size, alloc.natural_size] = this.vfunc_get_preferred_height(forWidth); return panelManager._getBoxPointerPreferredHeight(this, alloc); }); } this._updatePanelElementPositions(); if (reset) return; this._desktopIconsUsableArea = new DesktopIconsIntegration.DesktopIconsUsableAreaClass(); this._oldUpdatePanelBarrier = Main.layoutManager._updatePanelBarrier; Main.layoutManager._updatePanelBarrier = (panel) => { let panelUpdates = panel ? [panel] : this.allPanels; panelUpdates.forEach(p => newUpdatePanelBarrier.call(Main.layoutManager, p)); }; Main.layoutManager._updatePanelBarrier(); this._oldUpdateHotCorners = Main.layoutManager._updateHotCorners; Main.layoutManager._updateHotCorners = newUpdateHotCorners.bind(Main.layoutManager); Main.layoutManager._updateHotCorners(); this._forceHotCornerId = SETTINGS.connect('changed::stockgs-force-hotcorner', () => Main.layoutManager._updateHotCorners()); if (Main.layoutManager._interfaceSettings) { this._enableHotCornersId = Main.layoutManager._interfaceSettings.connect('changed::enable-hot-corners', () => Main.layoutManager._updateHotCorners()); } this._oldUpdateWorkspacesViews = Main.overview._overview._controls._workspacesDisplay._updateWorkspacesViews; Main.overview._overview._controls._workspacesDisplay._updateWorkspacesViews = this._newUpdateWorkspacesViews.bind(Main.overview._overview._controls._workspacesDisplay); this._oldSetPrimaryWorkspaceVisible = Main.overview._overview._controls._workspacesDisplay.setPrimaryWorkspaceVisible Main.overview._overview._controls._workspacesDisplay.setPrimaryWorkspaceVisible = this._newSetPrimaryWorkspaceVisible.bind(Main.overview._overview._controls._workspacesDisplay); LookingGlass.LookingGlass.prototype._oldResize = LookingGlass.LookingGlass.prototype._resize; LookingGlass.LookingGlass.prototype._resize = _newLookingGlassResize; LookingGlass.LookingGlass.prototype._oldOpen = LookingGlass.LookingGlass.prototype.open; LookingGlass.LookingGlass.prototype.open = _newLookingGlassOpen; this._signalsHandler = new Utils.GlobalSignalsHandler(); //listen settings this._signalsHandler.add( [ SETTINGS, [ 'changed::primary-monitor', 'changed::multi-monitors', 'changed::isolate-monitors', 'changed::panel-positions', 'changed::panel-lengths', 'changed::panel-anchors', 'changed::stockgs-keep-top-panel' ], () => this._reset() ], [ SETTINGS, 'changed::panel-element-positions', () => this._updatePanelElementPositions() ], [ SETTINGS, 'changed::intellihide-key-toggle-text', () => this._setKeyBindings(true) ], [ SETTINGS, 'changed::panel-sizes', () => { GLib.idle_add(GLib.PRIORITY_LOW, () => { this._setDesktopIconsMargins(); return GLib.SOURCE_REMOVE; }); } ], [ Utils.DisplayWrapper.getMonitorManager(), 'monitors-changed', () => { if (Main.layoutManager.primaryMonitor) { this._saveMonitors(); this._reset(); } } ] ); Panel.panelBoxes.forEach(c => this._signalsHandler.add( [ Main.panel[c], 'actor-added', (parent, child) => this.primaryPanel && this._adjustPanelMenuButton(this._getPanelMenuButton(child), this.primaryPanel.monitor, this.primaryPanel.getPosition()) ] )); this._setKeyBindings(true); // keep GS overview.js from blowing away custom panel styles if(!SETTINGS.get_boolean('stockgs-keep-top-panel')) Object.defineProperty(Main.panel, "style", {configurable: true, set(v) {}}); } disable(reset) { this.primaryPanel && this.overview.disable(); this.proximityManager.destroy(); this.allPanels.forEach(p => { p.taskbar.iconAnimator.pause(); this._findPanelMenuButtons(p.panelBox).forEach(pmb => { if (pmb.menu._boxPointer._dtpGetPreferredHeightId) { pmb.menu._boxPointer._container.disconnect(pmb.menu._boxPointer._dtpGetPreferredHeightId); } pmb.menu._boxPointer.sourceActor = pmb.menu._boxPointer._dtpSourceActor; delete pmb.menu._boxPointer._dtpSourceActor; pmb.menu._boxPointer._userArrowSide = St.Side.TOP; }) this._removePanelBarriers(p); p.disable(); let clipContainer = p.panelBox.get_parent(); Main.layoutManager._untrackActor(p.panelBox); Main.layoutManager.removeChrome(clipContainer); if (p.isStandalone) { p.panelBox.destroy(); } else { p.panelBox.remove_child(p); p.remove_child(p.panel); p.panelBox.add(p.panel); p.panelBox.set_position(clipContainer.x, clipContainer.y); clipContainer.remove_child(p.panelBox); Main.layoutManager.addChrome(p.panelBox, { affectsStruts: true, trackFullscreen: true }); } }); this._injectionManager.clear(); if (Main.layoutManager.primaryMonitor) { Main.layoutManager.panelBox.set_position(Main.layoutManager.primaryMonitor.x, Main.layoutManager.primaryMonitor.y); Main.layoutManager.panelBox.set_size(Main.layoutManager.primaryMonitor.width, -1); } if (reset) return; this._setKeyBindings(false); this._signalsHandler.destroy(); Main.layoutManager._updateHotCorners = this._oldUpdateHotCorners; Main.layoutManager._updateHotCorners(); SETTINGS.disconnect(this._forceHotCornerId); if (this._enableHotCornersId) { Main.layoutManager._interfaceSettings.disconnect(this._enableHotCornersId); } Main.layoutManager._updatePanelBarrier = this._oldUpdatePanelBarrier; Main.layoutManager._updatePanelBarrier(); Main.overview._overview._controls._workspacesDisplay._updateWorkspacesViews = this._oldUpdateWorkspacesViews; Main.overview._overview._controls._workspacesDisplay.setPrimaryWorkspaceVisible = this._oldSetPrimaryWorkspaceVisible; LookingGlass.LookingGlass.prototype._resize = LookingGlass.LookingGlass.prototype._oldResize; delete LookingGlass.LookingGlass.prototype._oldResize; LookingGlass.LookingGlass.prototype.open = LookingGlass.LookingGlass.prototype._oldOpen; delete LookingGlass.LookingGlass.prototype._oldOpen delete Main.panel.style; this._desktopIconsUsableArea.destroy(); this._desktopIconsUsableArea = null; } _setDesktopIconsMargins() { this._desktopIconsUsableArea?.resetMargins(); this.allPanels.forEach(p => { switch(p.geom.position) { case St.Side.TOP: this._desktopIconsUsableArea?.setMargins(p.monitor.index, p.geom.h, 0, 0, 0); break; case St.Side.BOTTOM: this._desktopIconsUsableArea?.setMargins(p.monitor.index, 0, p.geom.h, 0, 0); break; case St.Side.LEFT: this._desktopIconsUsableArea?.setMargins(p.monitor.index, 0, 0, p.geom.w, 0); break; case St.Side.RIGHT: this._desktopIconsUsableArea?.setMargins(p.monitor.index, 0, 0, 0, p.geom.w); break; } }); } setFocusedMonitor(monitor) { this.focusedMonitorPanel = this.allPanels.find(p => p.monitor == monitor) if (!this.checkIfFocusedMonitor(monitor)) { Main.overview._overview.clear_constraints(); Main.overview._overview.add_constraint(new Layout.MonitorConstraint({ index: monitor.index })); Main.overview._overview._controls._workspacesDisplay._primaryIndex = monitor.index; } } _newSetPrimaryWorkspaceVisible(visible) { if (this._primaryVisible === visible) return; this._primaryVisible = visible; const primaryIndex = Main.overview._overview._controls._workspacesDisplay._primaryIndex; const primaryWorkspace = this._workspacesViews[primaryIndex]; if (primaryWorkspace) primaryWorkspace.visible = visible; } _newUpdateWorkspacesViews() { for (let i = 0; i < this._workspacesViews.length; i++) this._workspacesViews[i].destroy(); this._workspacesViews = []; let monitors = Main.layoutManager.monitors; for (let i = 0; i < monitors.length; i++) { let view; if (i === this._primaryIndex) { view = new WorkspacesView(i, this._controls, this._scrollAdjustment, this._fitModeAdjustment, this._overviewAdjustment); view.visible = this._primaryVisible; this.bind_property('opacity', view, 'opacity', GObject.BindingFlags.SYNC_CREATE); this.add_child(view); } else { // No idea why atm, but we need the import at the top of this file and to use the // full imports ns here, otherwise SecondaryMonitorDisplay can't be used ¯\_(ツ)_/¯ view = new SecondaryMonitorDisplay(i, this._controls, this._scrollAdjustment, this._fitModeAdjustment, this._overviewAdjustment); Main.layoutManager.overviewGroup.add_actor(view); } this._workspacesViews.push(view); } } _saveMonitors() { //Mutter meta_monitor_manager_get_primary_monitor (global.display.get_primary_monitor()) doesn't return the same //monitor as GDK gdk_screen_get_primary_monitor (imports.gi.Gdk.Screen.get_default().get_primary_monitor()). //Since the Mutter function is what's used in gnome-shell and we can't access it from the settings dialog, store //the monitors information in a setting so we can use the same monitor indexes as the ones in gnome-shell let keyMonitors = 'available-monitors'; let keyPrimary = 'primary-monitor'; let primaryIndex = Main.layoutManager.primaryIndex; let newMonitors = [primaryIndex]; let savedMonitors = SETTINGS.get_value(keyMonitors).deep_unpack(); let dtpPrimaryIndex = SETTINGS.get_int(keyPrimary); let newDtpPrimaryIndex = primaryIndex; Main.layoutManager.monitors.filter(m => m.index != primaryIndex).forEach(m => newMonitors.push(m.index)); if (savedMonitors[0] != dtpPrimaryIndex) { // dash to panel primary wasn't the gnome-shell primary (first index of available-monitors) let savedIndex = savedMonitors.indexOf(dtpPrimaryIndex) // default to primary if it was set to a monitor that is no longer available newDtpPrimaryIndex = newMonitors[savedIndex]; newDtpPrimaryIndex = newDtpPrimaryIndex == null ? primaryIndex : newDtpPrimaryIndex; } SETTINGS.set_int(keyPrimary, newDtpPrimaryIndex); SETTINGS.set_value(keyMonitors, new GLib.Variant('ai', newMonitors)); } checkIfFocusedMonitor(monitor) { return Main.overview._overview._controls._workspacesDisplay._primaryIndex == monitor.index; } _createPanel(monitor, isStandalone) { let panelBox; let panel; let clipContainer = new Clutter.Actor(); if (isStandalone) { panelBox = new St.BoxLayout({ name: 'panelBox' }); } else { panelBox = Main.layoutManager.panelBox; Main.layoutManager._untrackActor(panelBox); panelBox.remove_child(Main.panel); Main.layoutManager.removeChrome(panelBox); } Main.layoutManager.addChrome(clipContainer, { affectsInputRegion: false }); clipContainer.add_child(panelBox); Main.layoutManager.trackChrome(panelBox, { trackFullscreen: true, affectsStruts: true, affectsInputRegion: true }); panel = new Panel.Panel(this, monitor, panelBox, isStandalone); panelBox.add(panel); panel.enable(); panelBox.visible = true; if (monitor.inFullscreen) { panelBox.hide(); } panelBox.set_position(0, 0); return panel; } _reset() { this.disable(true); this.allPanels = []; this.enable(true); } _updatePanelElementPositions() { this.panelsElementPositions = PanelSettings.getSettingsJson(SETTINGS, 'panel-element-positions'); this.allPanels.forEach(p => p.updateElementPositions()); } _adjustPanelMenuButton(button, monitor, arrowSide) { if (button) { button.menu._boxPointer._dtpSourceActor = button.menu._boxPointer.sourceActor; button.menu._boxPointer.sourceActor = button; button.menu._boxPointer._userArrowSide = arrowSide; button.menu._boxPointer._dtpInPanel = 1; if (!button.menu._boxPointer.vfunc_get_preferred_height) { button.menu._boxPointer._dtpGetPreferredHeightId = button.menu._boxPointer._container.connect('get-preferred-height', (actor, forWidth, alloc) => { this._getBoxPointerPreferredHeight(button.menu._boxPointer, alloc, monitor); }); } } } _getBoxPointerPreferredHeight(boxPointer, alloc, monitor) { if (boxPointer._dtpInPanel && boxPointer.sourceActor && SETTINGS.get_boolean('intellihide')) { monitor = monitor || Main.layoutManager.findMonitorForActor(boxPointer.sourceActor); let panel = Utils.find(global.dashToPanel.panels, p => p.monitor == monitor); let excess = alloc.natural_size + panel.dtpSize + 10 - monitor.height; // 10 is arbitrary if (excess > 0) { alloc.natural_size -= excess; } } return [alloc.min_size, alloc.natural_size]; } _findPanelMenuButtons(container) { let panelMenuButtons = []; let panelMenuButton; let find = parent => parent.get_children().forEach(c => { if ((panelMenuButton = this._getPanelMenuButton(c))) { panelMenuButtons.push(panelMenuButton); } find(c); }); find(container); return panelMenuButtons; } _removePanelBarriers(panel) { if (panel.isStandalone && panel._rightPanelBarrier) { panel._rightPanelBarrier.destroy(); } if (panel._leftPanelBarrier) { panel._leftPanelBarrier.destroy(); delete panel._leftPanelBarrier; } } _getPanelMenuButton(obj) { return obj instanceof PanelMenu.Button && obj.menu?._boxPointer ? obj : 0; } _setKeyBindings(enable) { let keys = { 'intellihide-key-toggle': () => this.allPanels.forEach(p => p.intellihide.toggle()) }; Object.keys(keys).forEach(k => { Utils.removeKeybinding(k); if (enable) { Utils.addKeybinding(k, SETTINGS, keys[k], Shell.ActionMode.NORMAL); } }); } }; // This class drives long-running icon animations, to keep them running in sync // with each other. export const IconAnimator = class { constructor(actor) { this._count = 0; this._started = false; this._animations = { dance: [], }; this._timeline = new Clutter.Timeline({ duration: 3000, repeat_count: -1, }); /* Just use the construction property when no need to support 3.36 */ if (this._timeline.set_actor) this._timeline.set_actor(actor); this._timeline.connect('new-frame', () => { const progress = this._timeline.get_progress(); const danceRotation = progress < 1/6 ? 15*Math.sin(progress*24*Math.PI) : 0; const dancers = this._animations.dance; for (let i = 0, iMax = dancers.length; i < iMax; i++) { dancers[i].target.rotation_angle_z = danceRotation; } }); } destroy() { this._timeline.stop(); this._timeline = null; for (let name in this._animations) { const pairs = this._animations[name]; for (let i = 0, iMax = pairs.length; i < iMax; i++) { const pair = pairs[i]; pair.target.disconnect(pair.targetDestroyId); } } this._animations = null; } pause() { if (this._started && this._count > 0) { this._timeline.stop(); } this._started = false; } start() { if (!this._started && this._count > 0) { this._timeline.start(); } this._started = true; } addAnimation(target, name) { const targetDestroyId = target.connect('destroy', () => this.removeAnimation(target, name)); this._animations[name].push({ target: target, targetDestroyId: targetDestroyId }); if (this._started && this._count === 0) { this._timeline.start(); } this._count++; } removeAnimation(target, name) { const pairs = this._animations[name]; for (let i = 0, iMax = pairs.length; i < iMax; i++) { const pair = pairs[i]; if (pair.target === target) { target.disconnect(pair.targetDestroyId); pairs.splice(i, 1); this._count--; if (this._started && this._count === 0) { this._timeline.stop(); } return; } } } }; function newUpdateHotCorners() { // destroy old hot corners this.hotCorners.forEach(function(corner) { if (corner) corner.destroy(); }); this.hotCorners = []; //global.settings is ubuntu specific setting to disable the hot corner (Tweak tool > Top Bar > Activities Overview Hot Corner) //this._interfaceSettings is for the setting to disable the hot corner introduced in gnome-shell 3.34 if ((global.settings.list_keys().indexOf('enable-hot-corners') >= 0 && !global.settings.get_boolean('enable-hot-corners')) || (this._interfaceSettings && !this._interfaceSettings.get_boolean('enable-hot-corners'))) { this.emit('hot-corners-changed'); return; } // build new hot corners for (let i = 0; i < this.monitors.length; i++) { let panel = Utils.find(global.dashToPanel.panels, p => p.monitor.index == i); let panelPosition = panel ? panel.getPosition() : St.Side.BOTTOM; let panelTopLeft = panelPosition == St.Side.TOP || panelPosition == St.Side.LEFT; let monitor = this.monitors[i]; let cornerX = this._rtl ? monitor.x + monitor.width : monitor.x; let cornerY = monitor.y; let haveTopLeftCorner = true; // If the panel is on the bottom, unless this is explicitly forced, don't add a topleft // hot corner unless it is actually a top left panel. Otherwise, it stops the mouse // as you are dragging across. In the future, maybe we will automatically move the // hotcorner to the bottom when the panel is positioned at the bottom if (i != this.primaryIndex || (!panelTopLeft && !SETTINGS.get_boolean('stockgs-force-hotcorner'))) { // Check if we have a top left (right for RTL) corner. // I.e. if there is no monitor directly above or to the left(right) let besideX = this._rtl ? monitor.x + 1 : cornerX - 1; let besideY = cornerY; let aboveX = cornerX; let aboveY = cornerY - 1; for (let j = 0; j < this.monitors.length; j++) { if (i == j) continue; let otherMonitor = this.monitors[j]; if (besideX >= otherMonitor.x && besideX < otherMonitor.x + otherMonitor.width && besideY >= otherMonitor.y && besideY < otherMonitor.y + otherMonitor.height) { haveTopLeftCorner = false; break; } if (aboveX >= otherMonitor.x && aboveX < otherMonitor.x + otherMonitor.width && aboveY >= otherMonitor.y && aboveY < otherMonitor.y + otherMonitor.height) { haveTopLeftCorner = false; break; } } } if (haveTopLeftCorner) { let corner = new Layout.HotCorner(this, monitor, cornerX, cornerY); corner.setBarrierSize = size => Object.getPrototypeOf(corner).setBarrierSize.call(corner, Math.min(size, 32)); corner.setBarrierSize(panel ? panel.dtpSize : 32); this.hotCorners.push(corner); } else { this.hotCorners.push(null); } } this.emit('hot-corners-changed'); } function newUpdatePanelBarrier(panel) { let barriers = { _rightPanelBarrier: [(panel.isStandalone ? panel : this)], _leftPanelBarrier: [panel] }; Object.keys(barriers).forEach(k => { let obj = barriers[k][0]; if (obj[k]) { obj[k].destroy(); obj[k] = null; } }); if (!this.primaryMonitor || !panel.panelBox.height) { return; } let barrierSize = Math.min(10, panel.panelBox.height); let fixed1 = panel.monitor.y; let fixed2 = panel.monitor.y + barrierSize; if (panel.checkIfVertical()) { barriers._rightPanelBarrier.push(panel.monitor.y + panel.monitor.height, Meta.BarrierDirection.NEGATIVE_Y); barriers._leftPanelBarrier.push(panel.monitor.y, Meta.BarrierDirection.POSITIVE_Y); } else { barriers._rightPanelBarrier.push(panel.monitor.x + panel.monitor.width, Meta.BarrierDirection.NEGATIVE_X); barriers._leftPanelBarrier.push(panel.monitor.x, Meta.BarrierDirection.POSITIVE_X); } switch (panel.getPosition()) { //values are initialized as St.Side.TOP case St.Side.BOTTOM: fixed1 = panel.monitor.y + panel.monitor.height - barrierSize; fixed2 = panel.monitor.y + panel.monitor.height; break; case St.Side.LEFT: fixed1 = panel.monitor.x + barrierSize; fixed2 = panel.monitor.x; break; case St.Side.RIGHT: fixed1 = panel.monitor.x + panel.monitor.width - barrierSize; fixed2 = panel.monitor.x + panel.monitor.width; break; } //remove left barrier if it overlaps one of the hotcorners for (let k in this.hotCorners) { let hc = this.hotCorners[k]; if (hc && hc._monitor == panel.monitor && ((fixed1 == hc._x || fixed2 == hc._x) || fixed1 == hc._y || fixed2 == hc._y)) { delete barriers._leftPanelBarrier; break; } } Object.keys(barriers).forEach(k => { let barrierOptions = { display: global.display, directions: barriers[k][2] }; barrierOptions[panel.varCoord.c1] = barrierOptions[panel.varCoord.c2] = barriers[k][1]; barrierOptions[panel.fixedCoord.c1] = fixed1; barrierOptions[panel.fixedCoord.c2] = fixed2; barriers[k][0][k] = new Meta.Barrier(barrierOptions); }); } function _newLookingGlassResize() { let primaryMonitorPanel = Utils.find(global.dashToPanel.panels, p => p.monitor == Main.layoutManager.primaryMonitor); let topOffset = primaryMonitorPanel.getPosition() == St.Side.TOP ? primaryMonitorPanel.dtpSize + 8 : 32; this._oldResize(); this._hiddenY = Main.layoutManager.primaryMonitor.y + topOffset - this.height; this._targetY = this._hiddenY + this.height; this.y = this._hiddenY; this._objInspector.set_position(this.x + Math.floor(this.width * 0.1), this._targetY + Math.floor(this.height * 0.1)); } function _newLookingGlassOpen() { if (this._open) return; this._resize(); this._oldOpen(); }