Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • manjaro-arm/applications/arm-profiles
  • luka177/arm-profiles
  • boredland/arm-profiles
3 results
Show changes
Showing
with 0 additions and 1993 deletions
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 56">
<g fill="#000000">
<rect y="45" width="1" height="1" opacity="0.5"/>
<rect y="46" width="1" height="2" opacity="0.2"/>
</g>
</svg>
/*
* 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/>.
*/
const Lang = imports.lang;
const Clutter = imports.gi.Clutter;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const GrabHelper = imports.ui.grabHelper;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const OverviewControls = imports.ui.overviewControls;
const PointerWatcher = imports.ui.pointerWatcher;
const Tweener = imports.ui.tweener;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Panel = Me.imports.panel;
const Proximity = Me.imports.proximity;
const Utils = Me.imports.utils;
//timeout intervals
const CHECK_POINTER_MS = 200;
const CHECK_GRAB_MS = 400;
const POST_ANIMATE_MS = 50;
const MIN_UPDATE_MS = 250;
//timeout names
const T1 = 'checkGrabTimeout';
const T2 = 'limitUpdateTimeout';
const T3 = 'postAnimateTimeout';
const T4 = 'panelBoxClipTimeout';
var SIDE_CONTROLS_ANIMATION_TIME = OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / (OverviewControls.SIDE_CONTROLS_ANIMATION_TIME > 1 ? 1000 : 1);
var Hold = {
NONE: 0,
TEMPORARY: 1,
PERMANENT: 2
};
var Intellihide = Utils.defineClass({
Name: 'DashToPanel.Intellihide',
_init: function(dtpPanel) {
this._dtpPanel = dtpPanel;
this._panelBox = dtpPanel.panelBox;
this._panelManager = dtpPanel.panelManager;
this._proximityManager = this._panelManager.proximityManager;
this._holdStatus = Hold.NONE;
this._signalsHandler = new Utils.GlobalSignalsHandler();
this._timeoutsHandler = new Utils.TimeoutsHandler();
this._intellihideChangedId = Me.settings.connect('changed::intellihide', () => this._changeEnabledStatus());
this._intellihideOnlySecondaryChangedId = Me.settings.connect('changed::intellihide-only-secondary', () => this._changeEnabledStatus());
this.enabled = false;
this._changeEnabledStatus();
},
enable: function(reset) {
this.enabled = true;
this._monitor = this._dtpPanel.monitor;
this._animationDestination = -1;
this._pendingUpdate = false;
this._hoveredOut = false;
this._windowOverlap = false;
this._translationProp = 'translation_' + (Panel.checkIfVertical() ? 'x' : 'y');
this._panelBox.translation_y = 0;
this._panelBox.translation_x = 0;
this._setTrackPanel(reset, true);
this._bindGeneralSignals();
if (Me.settings.get_boolean('intellihide-hide-from-windows')) {
this._proximityWatchId = this._proximityManager.createWatch(
this._clipContainer,
Proximity.Mode[Me.settings.get_string('intellihide-behaviour')],
0, 0,
overlap => {
this._windowOverlap = overlap;
this._queueUpdatePanelPosition();
}
);
}
this._setRevealMechanism();
this._queueUpdatePanelPosition();
},
disable: function(reset) {
if (this._proximityWatchId) {
this._proximityManager.removeWatch(this._proximityWatchId);
}
this._setTrackPanel(reset, false);
this._signalsHandler.destroy();
this._timeoutsHandler.destroy();
this._removeRevealMechanism();
this._revealPanel(!reset);
this.enabled = false;
},
destroy: function() {
Me.settings.disconnect(this._intellihideChangedId);
Me.settings.disconnect(this._intellihideOnlySecondaryChangedId);
if (this.enabled) {
this.disable();
}
},
toggle: function() {
this[this._holdStatus & Hold.PERMANENT ? 'release' : 'revealAndHold'](Hold.PERMANENT);
},
revealAndHold: function(holdStatus) {
if (this.enabled && !this._holdStatus) {
this._revealPanel();
}
this._holdStatus |= holdStatus;
},
release: function(holdStatus) {
this._holdStatus -= holdStatus;
if (this.enabled && !this._holdStatus) {
this._queueUpdatePanelPosition();
}
},
_reset: function() {
this.disable(true);
this.enable(true);
},
_changeEnabledStatus: function() {
let intellihide = Me.settings.get_boolean('intellihide');
let onlySecondary = Me.settings.get_boolean('intellihide-only-secondary');
let enabled = intellihide && (this._dtpPanel.isSecondary || !onlySecondary);
if (this.enabled !== enabled) {
this[enabled ? 'enable' : 'disable']();
}
},
_bindGeneralSignals: function() {
this._signalsHandler.add(
[
this._dtpPanel.taskbar,
'menu-closed',
() => this._panelBox.sync_hover()
],
[
Me.settings,
[
'changed::panel-position',
'changed::panel-size',
'changed::intellihide-use-pressure',
'changed::intellihide-hide-from-windows',
'changed::intellihide-behaviour'
],
() => this._reset()
],
[
Main.layoutManager,
'monitors-changed',
() => this._reset()
],
[
this._panelBox,
'notify::hover',
() => this._onHoverChanged()
],
[
this._dtpPanel.taskbar.previewMenu,
'open-state-changed',
() => this._queueUpdatePanelPosition()
],
[
Main.overview,
[
'showing',
'hiding'
],
() => this._queueUpdatePanelPosition()
]
);
},
_onHoverChanged: function() {
this._hoveredOut = !this._panelBox.hover;
this._queueUpdatePanelPosition();
},
_setTrackPanel: function(reset, enable) {
if (!reset) {
Main.layoutManager._untrackActor(this._panelBox);
if (enable) {
this._clipContainer = new Clutter.Actor();
Utils.setClip(this._clipContainer, this._panelBox.x, this._panelBox.y, this._panelBox.width, this._panelBox.height);
Main.layoutManager.removeChrome(this._panelBox);
Main.layoutManager.addChrome(this._clipContainer, { affectsInputRegion: false });
this._clipContainer.add_child(this._panelBox);
Main.layoutManager.trackChrome(this._panelBox, { affectsInputRegion: true });
this._timeoutsHandler.add([T4, 0, () => this._panelBox.set_position(0, 0)]);
} else {
this._panelBox.set_position(this._clipContainer.x, this._clipContainer.y);
Main.layoutManager.removeChrome(this._clipContainer);
this._clipContainer.remove_child(this._panelBox);
Main.layoutManager.addChrome(this._panelBox, { affectsStruts: true, trackFullscreen: true });
}
this._panelBox.track_hover = enable;
this._panelBox.reactive = enable;
this._panelBox.visible = enable ? enable : this._panelBox.visible;
}
},
_setRevealMechanism: function() {
if (global.display.supports_extended_barriers() && Me.settings.get_boolean('intellihide-use-pressure')) {
this._edgeBarrier = this._createBarrier();
this._pressureBarrier = new Layout.PressureBarrier(
Me.settings.get_int('intellihide-pressure-threshold'),
Me.settings.get_int('intellihide-pressure-time'),
Shell.ActionMode.NORMAL
);
this._pressureBarrier.addBarrier(this._edgeBarrier);
this._signalsHandler.add([this._pressureBarrier, 'trigger', () => this._queueUpdatePanelPosition(true)]);
} else {
this._pointerWatch = PointerWatcher.getPointerWatcher()
.addWatch(CHECK_POINTER_MS, (x, y) => this._checkMousePointer(x, y));
}
},
_removeRevealMechanism: function() {
if (this._pointerWatch) {
PointerWatcher.getPointerWatcher()._removeWatch(this._pointerWatch);
}
if (this._pressureBarrier) {
this._pressureBarrier.destroy();
this._edgeBarrier.destroy();
}
},
_createBarrier: function() {
let position = this._dtpPanel.geom.position;
let opts = { display: global.display };
if (Panel.checkIfVertical()) {
opts.y1 = this._monitor.y;
opts.y2 = this._monitor.y + this._monitor.height;
opts.x1 = opts.x2 = this._monitor.x;
} else {
opts.x1 = this._monitor.x;
opts.x2 = this._monitor.x + this._monitor.width;
opts.y1 = opts.y2 = this._monitor.y;
}
if (position == St.Side.TOP) {
opts.directions = Meta.BarrierDirection.POSITIVE_Y;
} else if (position == St.Side.BOTTOM) {
opts.y1 = opts.y2 = opts.y1 + this._monitor.height;
opts.directions = Meta.BarrierDirection.NEGATIVE_Y;
} else if (position == St.Side.LEFT) {
opts.directions = Meta.BarrierDirection.POSITIVE_X;
} else {
opts.x1 = opts.x2 = opts.x1 + this._monitor.width;
opts.directions = Meta.BarrierDirection.NEGATIVE_X;
}
return new Meta.Barrier(opts);
},
_checkMousePointer: function(x, y) {
let position = this._dtpPanel.geom.position;
if (!this._panelBox.hover && !Main.overview.visible &&
((position == St.Side.TOP && y <= this._monitor.y + 1) ||
(position == St.Side.BOTTOM && y >= this._monitor.y + this._monitor.height - 1) ||
(position == St.Side.LEFT && x <= this._monitor.x + 1) ||
(position == St.Side.RIGHT && x >= this._monitor.x + this._monitor.width - 1)) &&
((x >= this._monitor.x && x < this._monitor.x + this._monitor.width) &&
(y >= this._monitor.y && y < this._monitor.y + this._monitor.height))) {
this._queueUpdatePanelPosition(true);
}
},
_queueUpdatePanelPosition: function(fromRevealMechanism) {
if (!fromRevealMechanism && this._timeoutsHandler.getId(T2) && !Main.overview.visible) {
//unless this is a mouse interaction or entering/leaving the overview, limit the number
//of updates, but remember to update again when the limit timeout is reached
this._pendingUpdate = true;
} else if (!this._holdStatus) {
this._checkIfShouldBeVisible(fromRevealMechanism) ? this._revealPanel() : this._hidePanel();
this._timeoutsHandler.add([T2, MIN_UPDATE_MS, () => this._endLimitUpdate()]);
}
},
_endLimitUpdate: function() {
if (this._pendingUpdate) {
this._pendingUpdate = false;
this._queueUpdatePanelPosition();
}
},
_checkIfShouldBeVisible: function(fromRevealMechanism) {
if (Main.overview.visibleTarget || this._dtpPanel.taskbar.previewMenu.opened ||
this._panelBox.get_hover() || this._checkIfGrab()) {
return true;
}
if (fromRevealMechanism) {
let mouseBtnIsPressed = global.get_pointer()[2] & Clutter.ModifierType.BUTTON1_MASK;
//the user is trying to reveal the panel
if (this._monitor.inFullscreen && !mouseBtnIsPressed) {
return Me.settings.get_boolean('intellihide-show-in-fullscreen');
}
return !mouseBtnIsPressed;
}
if (!Me.settings.get_boolean('intellihide-hide-from-windows')) {
return this._panelBox.hover;
}
return !this._windowOverlap;
},
_checkIfGrab: function() {
if (GrabHelper._grabHelperStack.some(gh => gh._owner == this._dtpPanel.grabOwner)) {
//there currently is a grab on a child of the panel, check again soon to catch its release
this._timeoutsHandler.add([T1, CHECK_GRAB_MS, () => this._queueUpdatePanelPosition()]);
return true;
}
},
_revealPanel: function(immediate) {
this._animatePanel(0, immediate);
},
_hidePanel: function(immediate) {
let position = this._dtpPanel.geom.position;
let size = this._panelBox[position == St.Side.LEFT || position == St.Side.RIGHT ? 'width' : 'height'];
let coefficient = position == St.Side.TOP || position == St.Side.LEFT ? -1 : 1;
this._animatePanel(size * coefficient, immediate);
},
_animatePanel: function(destination, immediate, onComplete) {
let animating = Tweener.isTweening(this._panelBox);
if (!((animating && destination === this._animationDestination) ||
(!animating && destination === this._panelBox[this._translationProp]))) {
//the panel isn't already at, or animating to the asked destination
if (animating) {
Tweener.removeTweens(this._panelBox);
}
this._animationDestination = destination;
if (immediate) {
this._panelBox[this._translationProp] = destination;
this._invokeIfExists(onComplete);
} else {
let tweenOpts = {
//when entering/leaving the overview, use its animation time instead of the one from the settings
time: Main.overview.visible ?
SIDE_CONTROLS_ANIMATION_TIME :
Me.settings.get_int('intellihide-animation-time') * 0.001,
//only delay the animation when hiding the panel after the user hovered out
delay: destination != 0 && this._hoveredOut ? Me.settings.get_int('intellihide-close-delay') * 0.001 : 0,
transition: 'easeOutQuad',
onComplete: () => {
this._invokeIfExists(onComplete);
Main.layoutManager._queueUpdateRegions();
this._timeoutsHandler.add([T3, POST_ANIMATE_MS, () => this._queueUpdatePanelPosition()]);
}
};
tweenOpts[this._translationProp] = destination;
Tweener.addTween(this._panelBox, tweenOpts);
}
}
this._hoveredOut = false;
},
_invokeIfExists: function(func) {
func ? func.call(this) : null;
}
});
\ No newline at end of file
{
"_generated": "Generated by SweetTooth, do not edit",
"description": "An icon taskbar for the Gnome Shell. This extension moves the dash into the gnome main panel so that the application launchers and system tray are combined into a single panel, similar to that found in KDE Plasma and Windows 7+. A separate dock is no longer needed for easy access to running and favorited applications.\n\nFor a more traditional experience, you may also want to use Tweak Tool to enable Windows > Titlebar Buttons > Minimize & Maximize.\n\nFor the best support, please report any issues on Github. Dash-to-panel is developed and maintained by @jderose9 and @charlesg99.",
"extension-id": "dash-to-panel",
"gettext-domain": "dash-to-panel",
"name": "Dash to Panel",
"shell-version": [
"3.18",
"3.20",
"3.22",
"3.24",
"3.26",
"3.28",
"3.30",
"3.34",
"3.32"
],
"url": "https://github.com/jderose9/dash-to-panel",
"uuid": "dash-to-panel@jderose9.github.com",
"version": 26
}
\ No newline at end of file
/*
* 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
*
* Some code was also adapted from the upstream Gnome Shell source code.
*/
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Intellihide = Me.imports.intellihide;
const Utils = Me.imports.utils;
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Main = imports.ui.main;
const Shell = imports.gi.Shell;
const Gtk = imports.gi.Gtk;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const GS_HOTKEYS_KEY = 'switch-to-application-';
var dtpOverview = Utils.defineClass({
Name: 'DashToPanel.Overview',
_init: function() {
this._numHotkeys = 10;
this._currentHotkeyFocusIndex = -1;
},
enable : function(panel) {
this._panel = panel;
this.taskbar = panel.taskbar;
this._injectionsHandler = new Utils.InjectionsHandler();
this._signalsHandler = new Utils.GlobalSignalsHandler();
this._optionalWorkspaceIsolation();
this._optionalHotKeys();
this._optionalNumberOverlay();
this._toggleDash();
this._signalsHandler.add([
Me.settings,
'changed::stockgs-keep-dash',
() => this._toggleDash()
]);
},
disable: function () {
this._signalsHandler.destroy();
this._injectionsHandler.destroy();
this._toggleDash(true);
// reset stored icon size to the default dash
Main.overview.dashIconSize = Main.overview._controls.dash.iconSize;
// Remove key bindings
this._disableHotKeys();
this._disableExtraShortcut();
},
_toggleDash: function(visible) {
// To hide the dash, set its width to 1, so it's almost not taken into account by code
// calculaing the reserved space in the overview. The reason to keep it at 1 is
// to allow its visibility change to trigger an allocaion of the appGrid which
// in turn is triggergin the appsIcon spring animation, required when no other
// actors has this effect, i.e in horizontal mode and without the workspaceThumnails
// 1 static workspace only)
if (visible === undefined) {
visible = Me.settings.get_boolean('stockgs-keep-dash');
}
let visibilityFunc = visible ? 'show' : 'hide';
let width = visible ? -1 : 1;
Main.overview._controls.dash.actor[visibilityFunc]();
Main.overview._controls.dash.actor.set_width(width);
// This force the recalculation of the icon size
Main.overview._controls.dash._maxHeight = -1;
},
/**
* Isolate overview to open new windows for inactive apps
*/
_optionalWorkspaceIsolation: function() {
let label = 'optionalWorkspaceIsolation';
this._signalsHandler.add([
Me.settings,
'changed::isolate-workspaces',
Lang.bind(this, function() {
this._panel.panelManager.allPanels.forEach(p => p.taskbar.resetAppIcons());
if (Me.settings.get_boolean('isolate-workspaces'))
Lang.bind(this, enable)();
else
Lang.bind(this, disable)();
})
]);
if (Me.settings.get_boolean('isolate-workspaces'))
Lang.bind(this, enable)();
function enable() {
this._injectionsHandler.removeWithLabel(label);
this._injectionsHandler.addWithLabel(label, [
Shell.App.prototype,
'activate',
IsolatedOverview
]);
this._signalsHandler.removeWithLabel(label);
this._signalsHandler.addWithLabel(label, [
global.window_manager,
'switch-workspace',
() => this._panel.panelManager.allPanels.forEach(p => p.taskbar.handleIsolatedWorkspaceSwitch())
]);
}
function disable() {
this._signalsHandler.removeWithLabel(label);
this._injectionsHandler.removeWithLabel(label);
}
function IsolatedOverview() {
// These lines take care of Nautilus for icons on Desktop
let activeWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace();
let windows = this.get_windows().filter(w => w.get_workspace().index() == activeWorkspace.index());
if (windows.length > 0 &&
(!(windows.length == 1 && windows[0].skip_taskbar) ||
this.is_on_workspace(activeWorkspace)))
return Main.activateWindow(windows[0]);
return this.open_new_window(-1);
}
},
// Hotkeys
_activateApp: function(appIndex) {
let seenApps = {};
let apps = [];
this.taskbar._getAppIcons().forEach(function(appIcon) {
if (!seenApps[appIcon.app]) {
apps.push(appIcon);
}
seenApps[appIcon.app] = (seenApps[appIcon.app] || 0) + 1;
});
this._showOverlay();
if (appIndex < apps.length) {
let appIcon = apps[appIndex];
let seenAppCount = seenApps[appIcon.app];
let windowCount = appIcon.window || appIcon._hotkeysCycle ? seenAppCount : appIcon._nWindows;
if (Me.settings.get_boolean('shortcut-previews') && windowCount > 1) {
if (this._currentHotkeyFocusIndex < 0) {
let currentWindow = appIcon.window;
let keyFocusOutId = appIcon.actor.connect('key-focus-out', () => appIcon.actor.grab_key_focus());
let capturedEventId = global.stage.connect('captured-event', (actor, e) => {
if (e.type() == Clutter.EventType.KEY_RELEASE && e.get_key_symbol() == Clutter.Super_L) {
global.stage.disconnect(capturedEventId);
appIcon.actor.disconnect(keyFocusOutId);
appIcon._previewMenu.activateFocused();
appIcon.window = currentWindow;
delete appIcon._hotkeysCycle;
this._currentHotkeyFocusIndex = -1;
}
return Clutter.EVENT_PROPAGATE;
});
appIcon._hotkeysCycle = appIcon.window;
appIcon.window = null;
appIcon._previewMenu.open(appIcon);
appIcon.actor.grab_key_focus();
}
this._currentHotkeyFocusIndex = appIcon._previewMenu.focusNext();
} else {
// Activate with button = 1, i.e. same as left click
let button = 1;
appIcon.activate(button, true);
}
}
},
_optionalHotKeys: function() {
this._hotKeysEnabled = false;
if (Me.settings.get_boolean('hot-keys'))
this._enableHotKeys();
this._signalsHandler.add([
Me.settings,
'changed::hot-keys',
Lang.bind(this, function() {
if (Me.settings.get_boolean('hot-keys'))
Lang.bind(this, this._enableHotKeys)();
else
Lang.bind(this, this._disableHotKeys)();
})
]);
},
_resetHotkeys: function() {
this._disableHotKeys();
this._enableHotKeys();
},
_enableHotKeys: function() {
if (this._hotKeysEnabled)
return;
//3.32 introduced app hotkeys, disable them to prevent conflicts
if (Main.wm._switchToApplication) {
for (let i = 1; i < 10; ++i) {
Utils.removeKeybinding(GS_HOTKEYS_KEY + i);
}
}
// Setup keyboard bindings for taskbar elements
let shortcutNumKeys = Me.settings.get_string('shortcut-num-keys');
let bothNumKeys = shortcutNumKeys == 'BOTH';
let keys = [];
if (bothNumKeys || shortcutNumKeys == 'NUM_ROW') {
keys.push('app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-'); // Regular numbers
}
if (bothNumKeys || shortcutNumKeys == 'NUM_KEYPAD') {
keys.push('app-hotkey-kp-', 'app-shift-hotkey-kp-', 'app-ctrl-hotkey-kp-'); // Key-pad numbers
}
keys.forEach( function(key) {
for (let i = 0; i < this._numHotkeys; i++) {
let appNum = i;
Utils.addKeybinding(key + (i + 1), Me.settings, () => this._activateApp(appNum));
}
}, this);
this._hotKeysEnabled = true;
if (Me.settings.get_string('hotkeys-overlay-combo') === 'ALWAYS')
this.taskbar.toggleNumberOverlay(true);
},
_disableHotKeys: function() {
if (!this._hotKeysEnabled)
return;
let keys = ['app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-', // Regular numbers
'app-hotkey-kp-', 'app-shift-hotkey-kp-', 'app-ctrl-hotkey-kp-']; // Key-pad numbers
keys.forEach( function(key) {
for (let i = 0; i < this._numHotkeys; i++) {
Utils.removeKeybinding(key + (i + 1));
}
}, this);
if (Main.wm._switchToApplication) {
let gsSettings = new Gio.Settings({ schema_id: imports.ui.windowManager.SHELL_KEYBINDINGS_SCHEMA });
for (let i = 1; i < 10; ++i) {
Utils.addKeybinding(GS_HOTKEYS_KEY + i, gsSettings, Main.wm._switchToApplication.bind(Main.wm));
}
}
this._hotKeysEnabled = false;
this.taskbar.toggleNumberOverlay(false);
},
_optionalNumberOverlay: function() {
// Enable extra shortcut
if (Me.settings.get_boolean('hot-keys'))
this._enableExtraShortcut();
this._signalsHandler.add([
Me.settings,
'changed::hot-keys',
Lang.bind(this, this._checkHotkeysOptions)
], [
Me.settings,
'changed::hotkeys-overlay-combo',
Lang.bind(this, function() {
if (Me.settings.get_boolean('hot-keys') && Me.settings.get_string('hotkeys-overlay-combo') === 'ALWAYS')
this.taskbar.toggleNumberOverlay(true);
else
this.taskbar.toggleNumberOverlay(false);
})
], [
Me.settings,
'changed::shortcut-num-keys',
() => this._resetHotkeys()
]);
},
_checkHotkeysOptions: function() {
if (Me.settings.get_boolean('hot-keys'))
this._enableExtraShortcut();
else
this._disableExtraShortcut();
},
_enableExtraShortcut: function() {
Utils.addKeybinding('shortcut', Me.settings, () => this._showOverlay(true));
},
_disableExtraShortcut: function() {
Utils.removeKeybinding('shortcut');
},
_showOverlay: function(overlayFromShortcut) {
//wait for intellihide timeout initialization
if (!this._panel.intellihide) {
return;
}
// Restart the counting if the shortcut is pressed again
if (this._numberOverlayTimeoutId) {
Mainloop.source_remove(this._numberOverlayTimeoutId);
this._numberOverlayTimeoutId = 0;
}
let hotkey_option = Me.settings.get_string('hotkeys-overlay-combo');
if (hotkey_option === 'NEVER')
return;
if (hotkey_option === 'TEMPORARILY' || overlayFromShortcut)
this.taskbar.toggleNumberOverlay(true);
this._panel.intellihide.revealAndHold(Intellihide.Hold.TEMPORARY);
let timeout = Me.settings.get_int('overlay-timeout');
if (overlayFromShortcut) {
timeout = Me.settings.get_int('shortcut-timeout');
}
// Hide the overlay/dock after the timeout
this._numberOverlayTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, function() {
this._numberOverlayTimeoutId = 0;
if (hotkey_option != 'ALWAYS') {
this.taskbar.toggleNumberOverlay(false);
}
this._panel.intellihide.release(Intellihide.Hold.TEMPORARY);
}));
}
});
/*
* 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 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 DND = imports.ui.dnd;
const Shell = imports.gi.Shell;
const PopupMenu = imports.ui.popupMenu;
const IconGrid = imports.ui.iconGrid;
const ViewSelector = imports.ui.viewSelector;
const DateMenu = imports.ui.dateMenu;
const Tweener = imports.ui.tweener;
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 sizeFunc;
var fixedCoord;
var varCoord;
var size;
//timeout names
const T1 = 'startDynamicTransparencyTimeout';
const T2 = 'startIntellihideTimeout';
const T3 = 'allocationThrottleTimeout';
const T4 = 'showDesktopTimeout';
const T5 = 'trackerFocusAppTimeout';
const T6 = 'scrollPanelDelayTimeout';
function getPosition() {
let position = Me.settings.get_string('panel-position');
if (position == 'TOP') {
return St.Side.TOP;
} else if (position == 'RIGHT') {
return St.Side.RIGHT;
} else if (position == 'BOTTOM') {
return St.Side.BOTTOM;
}
return St.Side.LEFT;
}
function checkIfVertical() {
let position = getPosition();
return (position == St.Side.LEFT || position == St.Side.RIGHT);
}
function getOrientation() {
return (checkIfVertical() ? 'vertical' : 'horizontal');
}
function setMenuArrow(arrowIcon, side) {
let parent = arrowIcon.get_parent();
let iconNames = {
'0': 'pan-down-symbolic', //TOP
'1': 'pan-start-symbolic', //RIGHT
'2': 'pan-up-symbolic', //BOTTOM
'3': 'pan-end-symbolic' //LEFT
};
parent.remove_child(arrowIcon);
arrowIcon.set_icon_name(iconNames[side]);
parent.add_child(arrowIcon);
}
var dtpPanel = Utils.defineClass({
Name: 'DashToPanel-Panel',
Extends: St.Widget,
_init: function(panelManager, monitor, panelBox, isSecondary) {
let position = getPosition();
this.callParent('_init', { name: 'panel', reactive: true });
this.bg = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this.bg.add_child(this);
Utils.wrapActor(this);
this._delegate = this;
this._timeoutsHandler = new Utils.TimeoutsHandler();
this._signalsHandler = new Utils.GlobalSignalsHandler();
this.panelManager = panelManager;
this.panelStyle = new PanelStyle.dtpPanelStyle();
this.monitor = monitor;
this.panelBox = panelBox;
this.isSecondary = isSecondary;
this._sessionStyle = null;
if (position == St.Side.TOP) {
this._leftCorner = new Panel.PanelCorner(St.Side.LEFT);
this.add_actor(this._leftCorner.actor);
this._rightCorner = new Panel.PanelCorner(St.Side.RIGHT);
this.add_actor(this._rightCorner.actor);
}
if (isSecondary) {
this.statusArea = {};
this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
this._centerBox = new St.BoxLayout({ name: 'panelCenter' });
this._rightBox = new St.BoxLayout({ name: 'panelRight' });
this.menuManager = new PopupMenu.PopupMenuManager(this);
this.grabOwner = this;
//adding the clock to the centerbox will correctly position it according to dtp settings (event actor-added)
this._setPanelMenu('show-status-menu-all-monitors', 'aggregateMenu', dtpSecondaryAggregateMenu, this._rightBox, true);
this._setPanelMenu('show-clock-all-monitors', 'dateMenu', DateMenu.DateMenuButton, this._centerBox, true);
} else {
this.statusArea = Main.panel.statusArea;
this.menuManager = Main.panel.menuManager;
this.grabOwner = Main.panel.actor;
setMenuArrow(this.statusArea.aggregateMenu._indicators.get_last_child(), position);
['_leftBox', '_centerBox', '_rightBox'].forEach(p => {
Main.panel.actor.remove_child(Main.panel[p]);
this[p] = Main.panel[p];
});
}
this.add_child(this._leftBox);
this.add_child(this._centerBox);
this.add_child(this._rightBox);
Utils.wrapActor(this.statusArea.activities || 0);
if (Main.panel._onButtonPress) {
this._signalsHandler.add([
this,
[
'button-press-event',
'touch-event'
],
this._onButtonPress.bind(this)
]);
}
if (Main.panel._onKeyPress) {
this._signalsHandler.add([this, '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 taskbarPosition = Me.settings.get_string('taskbar-position');
let isVertical = checkIfVertical();
if (taskbarPosition == 'CENTEREDCONTENT' || taskbarPosition == 'CENTEREDMONITOR') {
this.container = this._centerBox;
} else {
this.container = this._leftBox;
}
if (this.statusArea.aggregateMenu) {
this.statusArea.aggregateMenu._volume.indicators._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
});
if (this.geom.position == St.Side.TOP) {
Main.overview._overview.insert_child_at_index(this._myPanelGhost, 0);
} else {
if (this.geom.position == St.Side.BOTTOM) {
Main.overview._overview.add_actor(this._myPanelGhost);
} else if (this.geom.position == St.Side.LEFT) {
Main.overview._controls._group.insert_child_at_index(this._myPanelGhost, 0);
} else {
Main.overview._controls._group.add_actor(this._myPanelGhost);
}
}
this._adjustForOverview();
this._setPanelGhostSize();
this._setPanelPosition();
if (!this.isSecondary && this.statusArea.dateMenu) {
// remove the extra space before the clock when the message-indicator is displayed
Utils.hookVfunc(DateMenu.IndicatorPad.prototype, 'get_preferred_width', () => [0,0]);
Utils.hookVfunc(DateMenu.IndicatorPad.prototype, 'get_preferred_height', () => [0,0]);
}
this.menuManager._oldChangeMenu = this.menuManager._changeMenu;
this.menuManager._changeMenu = (menu) => {
if (!Me.settings.get_boolean('stockgs-panelbtn-click-only')) {
this.menuManager._oldChangeMenu(menu);
}
};
if (this.statusArea.appMenu) {
setMenuArrow(this.statusArea.appMenu._arrow, getPosition());
this._leftBox.remove_child(this.statusArea.appMenu.container);
}
//the timeout makes sure the theme's styles are computed before initially applying the transparency
this._timeoutsHandler.add([T1, 0, () => this.dynamicTransparency = new Transparency.DynamicTransparency(this)]);
this.taskbar = new Taskbar.taskbar(this);
Main.overview.dashIconSize = this.taskbar.iconSize;
this.container.insert_child_above(this.taskbar.actor, null);
this._setActivitiesButtonVisible(Me.settings.get_boolean('show-activities-button'));
this._setAppmenuVisible(Me.settings.get_boolean('show-appmenu'));
this._setClockLocation(Me.settings.get_string('location-clock'));
this._displayShowDesktopButton(Me.settings.get_boolean('show-showdesktop-button'));
this.add_style_class_name('dashtopanelMainPanel ' + getOrientation());
// Since Gnome 3.8 dragging an app without having opened the overview before cause the attemp to
//animate a null target since some variables are not initialized when the viewSelector is created
if(Main.overview.viewSelector._activePage == null)
Main.overview.viewSelector._activePage = Main.overview.viewSelector._workspacesPage;
if(this.taskbar._showAppsIconWrapper)
this.taskbar._showAppsIconWrapper._dtpPanel = this;
this._timeoutsHandler.add([T2, Me.settings.get_int('intellihide-enable-start-delay'), () => this.intellihide = new Intellihide.Intellihide(this)]);
this._signalsHandler.add(
[
this.panelBox,
'notify::height',
() => this._setPanelPosition()
],
// this is to catch changes to the window scale factor
[
St.ThemeContext.get_for_stage(global.stage),
'changed',
() => this._setPanelPosition()
],
// Keep dragged icon consistent in size with this dash
[
this.taskbar,
'icon-size-changed',
Lang.bind(this, function() {
Main.overview.dashIconSize = this.taskbar.iconSize;
})
],
[
// sync hover after a popupmenu is closed
this.taskbar,
'menu-closed',
Lang.bind(this, function(){this.container.sync_hover();})
],
// This duplicate the similar signal which is in overview.js.
// Being connected and thus executed later this effectively
// overwrite any attempt to use the size of the default dash
// which given the customization is usually much smaller.
// I can't easily disconnect the original signal
[
Main.overview._controls.dash,
'icon-size-changed',
Lang.bind(this, function() {
Main.overview.dashIconSize = this.taskbar.iconSize;
})
],
[
Main.overview,
[
'showing',
'hiding'
],
() => this._adjustForOverview()
],
[
this._centerBox,
'actor-added',
() => this._onBoxActorAdded(this._centerBox)
],
[
this._rightBox,
'actor-added',
() => this._onBoxActorAdded(this._rightBox)
],
[
this,
'scroll-event',
this._onPanelMouseScroll.bind(this)
],
[
Main.layoutManager,
'startup-complete',
() => this._resetGeometry(true)
]
);
if (isVertical) {
this._signalsHandler.add(
[
this._centerBox,
'notify::allocation',
() => this._refreshVerticalAlloc()
],
[
this._rightBox,
'notify::allocation',
() => this._refreshVerticalAlloc()
]
);
}
this._bindSettingsChanges();
this.panelStyle.enable(this);
if (this.statusArea.dateMenu && isVertical) {
this.statusArea.dateMenu._clock.time_only = true;
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);
},
disable: function () {
this.panelStyle.disable();
this._timeoutsHandler.destroy();
this._signalsHandler.destroy();
this.container.remove_child(this.taskbar.actor);
this._setAppmenuVisible(false);
if (this.statusArea.appMenu) {
setMenuArrow(this.statusArea.appMenu._arrow, St.Side.TOP);
this._leftBox.add_child(this.statusArea.appMenu.container);
}
if (this.intellihide) {
this.intellihide.destroy();
}
if (this.dynamicTransparency) {
this.dynamicTransparency.destroy();
}
this.taskbar.destroy();
// reset stored icon size to the default dash
Main.overview.dashIconSize = Main.overview._controls.dash.iconSize;
this.menuManager._changeMenu = this.menuManager._oldChangeMenu;
this._myPanelGhost.get_parent().remove_actor(this._myPanelGhost);
if (!this.isSecondary) {
this._setVertical(this, false);
this.remove_style_class_name('dashtopanelPanel vertical horizontal');
['_leftBox', '_centerBox', '_rightBox'].forEach(p => {
this.remove_child(Main.panel[p]);
Main.panel.actor.add_child(Main.panel[p]);
});
this._setActivitiesButtonVisible(true);
this._setClockLocation("BUTTONSLEFT");
this._displayShowDesktopButton(false);
if (this.statusArea.aggregateMenu) {
delete this.statusArea.aggregateMenu._volume.indicators._dtpIgnoreScroll;
setMenuArrow(this.statusArea.aggregateMenu._indicators.get_last_child(), St.Side.TOP);
}
if (this.statusArea.dateMenu) {
this.statusArea.dateMenu._clock.time_only = false;
this.statusArea.dateMenu._clockDisplay.text = this.statusArea.dateMenu._clock.clock;
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);
}
} else {
this._removePanelMenu('dateMenu');
this._removePanelMenu('aggregateMenu');
}
Main.ctrlAltTabManager.removeGroup(this);
},
//next 3 functions are needed by other extensions to add elements to the secondary panel
addToStatusArea: function(role, indicator, position, box) {
return Main.panel.addToStatusArea.call(this, role, indicator, position, box);
},
_addToPanelBox: function(role, indicator, position, box) {
Main.panel._addToPanelBox.call(this, role, indicator, position, box);
},
_onMenuSet: function(indicator) {
Main.panel._onMenuSet.call(this, indicator);
},
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;
},
_bindSettingsChanges: function() {
let isVertical = checkIfVertical();
this._signalsHandler.add(
[
Me.settings,
[
'changed::panel-size',
'changed::group-apps'
],
() => this._resetGeometry()
],
[
Me.settings,
[
'changed::appicon-margin',
'changed::appicon-padding'
],
() => this.taskbar.resetAppIcons()
],
[
Me.settings,
'changed::show-activities-button',
() => this._setActivitiesButtonVisible(Me.settings.get_boolean('show-activities-button'))
],
[
Me.settings,
'changed::show-appmenu',
() => this._setAppmenuVisible(Me.settings.get_boolean('show-appmenu'))
],
[
Me.settings,
'changed::location-clock',
() => this._setClockLocation(Me.settings.get_string('location-clock'))
],
[
Me.settings,
'changed::show-showdesktop-button',
() => this._displayShowDesktopButton(Me.settings.get_boolean('show-showdesktop-button'))
],
[
Me.settings,
'changed::showdesktop-button-width',
() => this._setShowDesktopButtonSize()
],
[
Me.desktopSettings,
'changed::clock-format',
() => {
this._clockFormat = null;
if (isVertical) {
this._formatVerticalClock();
}
}
]
);
if (isVertical) {
this._signalsHandler.add([Me.settings, 'changed::group-apps-label-max-width', () => this._resetGeometry()]);
}
},
_setPanelMenu: function(settingName, propName, constr, container, isInit) {
if (isInit) {
this._signalsHandler.add([Me.settings, 'changed::' + settingName, () => this._setPanelMenu(settingName, propName, constr, container)]);
}
if (!Me.settings.get_boolean(settingName)) {
this._removePanelMenu(propName);
} else if (!this.statusArea[propName]) {
this.statusArea[propName] = new 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);
}
//this.statusArea[propName].destroy(); //buggy for now, gnome-shell never destroys those menus
this.menuManager.removeMenu(this.statusArea[propName].menu);
this.statusArea[propName] = null;
}
},
_setPanelGhostSize: function() {
this._myPanelGhost.set_size(this.geom.w, checkIfVertical() ? 1 : this.geom.h);
},
_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) {
Main.overview._panelGhost.set_height(this.geom.position == St.Side.TOP ? 0 : Main.panel.height);
}
}
},
_resetGeometry: function(clockOnly) {
if (!clockOnly) {
this.geom = this.getGeometry();
this._setPanelGhostSize();
this._setPanelPosition();
this.taskbar.resetAppIcons();
}
if (checkIfVertical()) {
this._formatVerticalClock();
}
},
getGeometry: function() {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor || 1;
let position = getPosition();
let x = 0, y = 0;
let w = 0, h = 0;
size = Me.settings.get_int('panel-size') * scaleFactor;
if (checkIfVertical()) {
if (!Me.settings.get_boolean('group-apps')) {
// add window title width and side padding of _dtpIconContainer when vertical
size += Me.settings.get_int('group-apps-label-max-width') + AppIcons.DEFAULT_PADDING_SIZE * 2 / scaleFactor;
}
sizeFunc = 'get_preferred_height',
fixedCoord = { c1: 'x1', c2: 'x2' },
varCoord = { c1: 'y1', c2: 'y2' };
w = size;
h = this.monitor.height;
} else {
sizeFunc = 'get_preferred_width';
fixedCoord = { c1: 'y1', c2: 'y2' };
varCoord = { c1: 'x1', c2: 'x2' };
w = this.monitor.width;
h = size;
}
if (position == St.Side.TOP || position == St.Side.LEFT) {
x = this.monitor.x;
y = this.monitor.y;
} else if (position == St.Side.RIGHT) {
x = this.monitor.x + this.monitor.width - size;
y = this.monitor.y;
} else { //BOTTOM
x = this.monitor.x;
y = this.monitor.y + this.monitor.height - size;
}
return {
x: x, y: y,
w: w, h: h,
position: position
};
},
vfunc_allocate: function(box, flags) {
this.set_allocation(box, flags);
let panelAllocVarSize = box[varCoord.c2] - box[varCoord.c1];
let panelAllocFixedSize = box[fixedCoord.c2] - box[fixedCoord.c1];
let [, leftNaturalSize] = this._leftBox[sizeFunc](-1);
let [, centerNaturalSize] = this._centerBox[sizeFunc](-1);
let [, rightNaturalSize] = this._rightBox[sizeFunc](-1);
let taskbarPosition = Me.settings.get_string('taskbar-position');
// The _rightBox is always allocated the same, regardless of taskbar position setting
let rightAllocSize = rightNaturalSize;
// Now figure out how large the _leftBox and _centerBox should be.
// The box with the taskbar is always the one that is forced to be smaller as the other boxes grow
let leftAllocSize, centerStartPosition, centerEndPosition;
let childBoxLeft = new Clutter.ActorBox();
let childBoxCenter = new Clutter.ActorBox();
let childBoxRight = new Clutter.ActorBox();
if (taskbarPosition == 'CENTEREDMONITOR') {
leftAllocSize = leftNaturalSize;
centerStartPosition = Math.max(leftNaturalSize, Math.floor((panelAllocVarSize - centerNaturalSize)/2));
centerEndPosition = Math.min(panelAllocVarSize-rightNaturalSize, Math.ceil((panelAllocVarSize+centerNaturalSize))/2);
} else if (taskbarPosition == 'CENTEREDCONTENT') {
leftAllocSize = leftNaturalSize;
centerStartPosition = Math.max(leftNaturalSize, Math.floor((panelAllocVarSize - centerNaturalSize + leftNaturalSize - rightNaturalSize) / 2));
centerEndPosition = Math.min(panelAllocVarSize-rightNaturalSize, Math.ceil((panelAllocVarSize + centerNaturalSize + leftNaturalSize - rightNaturalSize) / 2));
} else if (taskbarPosition == 'LEFTPANEL_FIXEDCENTER') {
leftAllocSize = Math.floor((panelAllocVarSize - centerNaturalSize) / 2);
centerStartPosition = leftAllocSize;
centerEndPosition = centerStartPosition + centerNaturalSize;
} else if (taskbarPosition == 'LEFTPANEL_FLOATCENTER') {
let leftAllocSizeMax = panelAllocVarSize - rightNaturalSize - centerNaturalSize;
leftAllocSize = Math.min(leftAllocSizeMax, leftNaturalSize);
let freeSpace = panelAllocVarSize - leftAllocSize - rightAllocSize - centerNaturalSize;
centerStartPosition = leftAllocSize + Math.floor(freeSpace / 2);
centerEndPosition = centerStartPosition + centerNaturalSize;
} else { // LEFTPANEL
leftAllocSize = panelAllocVarSize - rightNaturalSize - centerNaturalSize;
centerStartPosition = leftAllocSize;
centerEndPosition = centerStartPosition + centerNaturalSize;
}
childBoxLeft[fixedCoord.c1] = childBoxCenter[fixedCoord.c1] = childBoxRight[fixedCoord.c1] = 0;
childBoxLeft[fixedCoord.c2] = childBoxCenter[fixedCoord.c2] = childBoxRight[fixedCoord.c2] = panelAllocFixedSize;
// if it is a RTL language, the boxes are switched around, and we need to invert the coordinates
if (this.get_text_direction() == Clutter.TextDirection.RTL) {
childBoxLeft[varCoord.c1] = panelAllocVarSize - leftAllocSize;
childBoxLeft[varCoord.c2] = panelAllocVarSize;
childBoxCenter[varCoord.c1] = panelAllocVarSize - centerEndPosition;
childBoxCenter[varCoord.c2] = panelAllocVarSize - centerStartPosition;
childBoxRight[varCoord.c1] = 0;
childBoxRight[varCoord.c2] = rightAllocSize;
} else {
childBoxLeft[varCoord.c1] = 0;
childBoxLeft[varCoord.c2] = leftAllocSize;
childBoxCenter[varCoord.c1] = centerStartPosition;
childBoxCenter[varCoord.c2] = centerEndPosition;
childBoxRight[varCoord.c1] = panelAllocVarSize - rightAllocSize;
childBoxRight[varCoord.c2] = panelAllocVarSize;
}
if (this._leftCorner) {
let childBoxLeftCorner = new Clutter.ActorBox();
let [ , cornerSize] = this._leftCorner.actor[sizeFunc](-1);
childBoxLeftCorner[varCoord.c1] = 0;
childBoxLeftCorner[varCoord.c2] = cornerSize;
childBoxLeftCorner[fixedCoord.c1] = panelAllocFixedSize;
childBoxLeftCorner[fixedCoord.c2] = panelAllocFixedSize + cornerSize;
let childBoxRightCorner = new Clutter.ActorBox();
[ , cornerSize] = this._rightCorner.actor[sizeFunc](-1);
childBoxRightCorner[varCoord.c1] = panelAllocVarSize - cornerSize;
childBoxRightCorner[varCoord.c2] = panelAllocVarSize;
childBoxRightCorner[fixedCoord.c1] = panelAllocFixedSize;
childBoxRightCorner[fixedCoord.c2] = panelAllocFixedSize + cornerSize;
this._leftCorner.actor.allocate(childBoxLeftCorner, flags);
this._rightCorner.actor.allocate(childBoxRightCorner, flags);
}
this._leftBox.allocate(childBoxLeft, flags);
this._centerBox.allocate(childBoxCenter, flags);
this._rightBox.allocate(childBoxRight, flags);
},
_setPanelPosition: function() {
let container = this.intellihide && this.intellihide.enabled ? this.panelBox.get_parent() : this.panelBox;
this.set_size(this.geom.w, this.geom.h);
container.set_position(this.geom.x, this.geom.y)
this._setVertical(this, checkIfVertical());
// styles for theming
Object.keys(St.Side).forEach(p => {
let cssName = 'dashtopanel' + p.charAt(0) + p.slice(1).toLowerCase();
this[(St.Side[p] == this.geom.position ? 'add' : 'remove') + '_style_class_name'](cssName);
});
Main.layoutManager._updateHotCorners();
Main.layoutManager._updatePanelBarrier(this);
},
_onButtonPress: function(actor, event) {
let type = event.type();
let isPress = type == Clutter.EventType.BUTTON_PRESS;
let button = isPress ? event.get_button() : -1;
if (Main.modalCount > 0 || event.get_source() != actor ||
(!isPress && type != Clutter.EventType.TOUCH_BEGIN) ||
(isPress && button != 1)) {
return Clutter.EVENT_PROPAGATE;
}
let [stageX, stageY] = event.get_coords();
let params = checkIfVertical() ? [stageY, 'y', 'height'] : [stageX, 'x', 'width'];
let dragWindow = this._getDraggableWindowForPosition.apply(this, params.concat(['maximized_' + 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 allWindowsByStacking.find(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) {
this._setClockLocation(Me.settings.get_string('location-clock'));
},
_refreshVerticalAlloc: function() {
if (!this._timeoutsHandler.getId(T3)) {
this._timeoutsHandler.add([T3, 200, () => {
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) {
return;
}
if (actor instanceof St.BoxLayout) {
actor.vertical = isVertical;
} else if (actor instanceof PanelMenu.ButtonBox && actor != this.statusArea.appMenu) {
let child = actor.get_first_child();
if (child) {
let [, natWidth] = actor.get_preferred_width(-1);
child.x_align = Clutter.ActorAlign[isVertical ? 'CENTER' : 'START'];
actor.set_width(isVertical ? size : -1);
isVertical = isVertical && (natWidth > size);
actor[(isVertical ? 'add' : 'remove') + '_style_class_name']('vertical');
}
}
actor.get_children().forEach(c => _set(c, isVertical));
};
_set(actor, false);
_set(actor, isVertical);
},
_setActivitiesButtonVisible: function(isVisible) {
if(this.statusArea.activities)
isVisible ? this.statusArea.activities.actor.show() :
this.statusArea.activities.actor.hide();
},
_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) {
let taskbarPosition = Me.settings.get_string('taskbar-position');
if (taskbarPosition == 'CENTEREDCONTENT' || taskbarPosition == 'CENTEREDMONITOR') {
this._leftBox.insert_child_above(appMenu.container, null);
} else {
this._centerBox.insert_child_at_index(appMenu.container, 0);
}
}
},
_formatVerticalClock: function() {
let time = this.statusArea.dateMenu._clock.clock;
let clockText = this.statusArea.dateMenu._clockDisplay.clutter_text;
clockText.set_text(time);
clockText.get_allocation_box();
if (clockText.get_layout().is_ellipsized()) {
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(' '));
}
clockText.set_text(timeParts.join('\n<span size="xx-small">‧‧</span>\n').trim());
clockText.set_use_markup(true);
}
},
_setClockLocation: function(loc) {
if(!this.statusArea.dateMenu)
return;
let dateMenuContainer = this.statusArea.dateMenu.container;
let parent = dateMenuContainer.get_parent();
let destination;
let refSibling = null;
if (!parent) {
return;
}
if (loc.indexOf('BUTTONS') == 0) {
destination = this._centerBox;
} else if (loc.indexOf('STATUS') == 0) {
refSibling = this.statusArea.aggregateMenu ? this.statusArea.aggregateMenu.container : null;
destination = this._rightBox;
} else { //TASKBAR
refSibling = this.taskbar.actor;
destination = refSibling.get_parent();
}
if (parent != destination) {
parent.remove_actor(dateMenuContainer);
destination.add_actor(dateMenuContainer);
}
destination['set_child_' + (loc.indexOf('RIGHT') > 0 ? 'above' : 'below') + '_sibling'](dateMenuContainer, refSibling);
destination.queue_relayout();
},
_displayShowDesktopButton: function (isVisible) {
if(isVisible) {
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._setShowDesktopButtonSize();
this._showDesktopButton.connect('button-press-event', () => this._onShowDesktopButtonPress());
this._showDesktopButton.connect('enter-event', () => {
this._showDesktopButton.add_style_class_name('showdesktop-button-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('showdesktop-button-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._rightBox.insert_child_at_index(this._showDesktopButton, this._rightBox.get_children().length);
} else {
if(!this._showDesktopButton)
return;
this._rightBox.remove_child(this._showDesktopButton);
this._showDesktopButton.destroy();
this._showDesktopButton = null;
}
},
_setShowDesktopButtonSize: function() {
if (this._showDesktopButton) {
let buttonSize = Me.settings.get_int('showdesktop-button-width') + 'px;';
let isVertical = checkIfVertical();
let 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;
}
},
_toggleWorkspaceWindows: function(hide, workspace) {
let toggleFunc = w => {
Tweener.addTween(w.get_compositor_private(), {
opacity: hide ? 0 : 255,
time: Me.settings.get_int('show-showdesktop-time') * .001,
transition: 'easeOutQuad'
});
};
//there currently is a mutter bug with the windows opacity on 3.34, so
//until it is fixed, immediately hide the windows instead of fading them
//https://gitlab.gnome.org/GNOME/mutter/issues/836
if (Config.PACKAGE_VERSION > '3.33') {
toggleFunc = w => w.get_compositor_private().visible = !hide;
}
workspace.list_windows().forEach(toggleFunc);
},
_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._checkIfIgnoredSrollSource(event.get_source()) && direction && !this._timeoutsHandler.getId(T6)) {
this._timeoutsHandler.add([T6, Me.settings.get_int('scroll-panel-delay'), () => {}]);
if (scrollAction === 'SWITCH_WORKSPACE') {
let args = [global.display];
//gnome-shell < 3.30 needs an additional "screen" param
global.screen ? args.push(global.screen) : 0;
Main.wm._showWorkspaceSwitcher.apply(Main.wm, args.concat([0, { get_name: () => 'switch---' + direction }]));
} else if (scrollAction === 'CYCLE_WINDOWS') {
let windows = this.taskbar.getAppInfos().reduce((ws, appInfo) => ws.concat(appInfo.windows), []);
Utils.activateSiblingWindow(windows, direction);
}
}
},
_checkIfIgnoredSrollSource: function(source) {
let ignoredConstr = ['WorkspaceIndicator'];
return source._dtpIgnoreScroll || ignoredConstr.indexOf(source.constructor.name) >= 0;
}
});
var dtpSecondaryAggregateMenu = Utils.defineClass({
Name: 'dtpSecondaryAggregateMenu',
Extends: PanelMenu.Button,
_init: function() {
this.callParent('_init', 0.0, C_("System menu in the top bar", "System"), false);
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);
if (Config.HAVE_NETWORKMANAGER && Config.PACKAGE_VERSION >= '3.24') {
this._network = new imports.ui.status.network.NMApplet();
} else {
this._network = null;
}
if (Config.HAVE_BLUETOOTH) {
this._bluetooth = new imports.ui.status.bluetooth.Indicator();
} else {
this._bluetooth = null;
}
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();
this._screencast = new imports.ui.status.screencast.Indicator();
if (Config.PACKAGE_VERSION >= '3.24') {
this._nightLight = new imports.ui.status.nightLight.Indicator();
}
if (Config.PACKAGE_VERSION >= '3.28') {
this._thunderbolt = new imports.ui.status.thunderbolt.Indicator();
}
if (this._thunderbolt) {
this._indicators.add_child(this._thunderbolt.indicators);
}
this._indicators.add_child(this._screencast.indicators);
if (this._nightLight) {
this._indicators.add_child(this._nightLight.indicators);
}
if (this._network) {
this._indicators.add_child(this._network.indicators);
}
if (this._bluetooth) {
this._indicators.add_child(this._bluetooth.indicators);
}
this._indicators.add_child(this._volume.indicators);
this._indicators.add_child(this._power.indicators);
this._indicators.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
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(this._system.menu);
menuLayout.addSizeChild(this._power.menu.actor);
menuLayout.addSizeChild(this._system.menu.actor);
setMenuArrow(this._indicators.get_last_child(), getPosition());
},
});