diff --git a/.gitignore b/.gitignore
index e9fb3e4..23439fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ dash-to-panel@jderose9.github.com*.zip
*.mo
po/dash-to-panel.pot
ui/*.ui.h
+node_modules/
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..cab365e
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "semi": false,
+ "arrowParens": "always",
+ "singleQuote": true
+}
\ No newline at end of file
diff --git a/appIcons.js b/appIcons.js
index 3bfad20..f90bac1 100644
--- a/appIcons.js
+++ b/appIcons.js
@@ -21,78 +21,86 @@
* Some code was also adapted from the upstream Gnome Shell source code.
*/
+import Clutter from 'gi://Clutter'
+import GLib from 'gi://GLib'
+import Gio from 'gi://Gio'
+import Graphene from 'gi://Graphene'
+import GObject from 'gi://GObject'
+import Mtk from 'gi://Mtk'
+import Shell from 'gi://Shell'
+import St from 'gi://St'
-import Clutter from 'gi://Clutter';
-import GLib from 'gi://GLib';
-import Gio from 'gi://Gio';
-import Graphene from 'gi://Graphene';
-import GObject from 'gi://GObject';
-import Mtk from 'gi://Mtk';
-import Shell from 'gi://Shell';
-import St from 'gi://St';
+import * as AppDisplay from 'resource:///org/gnome/shell/ui/appDisplay.js'
+import * as AppMenu from 'resource:///org/gnome/shell/ui/appMenu.js'
+import * as Dash from 'resource:///org/gnome/shell/ui/dash.js'
+import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'
+import * as Main from 'resource:///org/gnome/shell/ui/main.js'
+import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'
+import * as Util from 'resource:///org/gnome/shell/misc/util.js'
+import * as BoxPointer from 'resource:///org/gnome/shell/ui/boxpointer.js'
+import { EventEmitter } from 'resource:///org/gnome/shell/misc/signals.js'
-import * as AppDisplay from 'resource:///org/gnome/shell/ui/appDisplay.js';
-import * as AppMenu from 'resource:///org/gnome/shell/ui/appMenu.js';
-import * as Dash from 'resource:///org/gnome/shell/ui/dash.js';
-import * as DND from 'resource:///org/gnome/shell/ui/dnd.js';
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
-import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
-import * as Util from 'resource:///org/gnome/shell/misc/util.js';
-import * as BoxPointer from 'resource:///org/gnome/shell/ui/boxpointer.js';
-import { EventEmitter } from 'resource:///org/gnome/shell/misc/signals.js';
-
-import * as Utils from './utils.js';
-import * as PanelSettings from './panelSettings.js';
-import * as Taskbar from './taskbar.js';
-import * as Progress from './progress.js';
-import { DTP_EXTENSION, SETTINGS, DESKTOPSETTINGS, TERMINALSETTINGS, EXTENSION_PATH } from './extension.js';
-import { gettext as _, ngettext } from 'resource:///org/gnome/shell/extensions/extension.js';
+import * as Utils from './utils.js'
+import * as PanelSettings from './panelSettings.js'
+import * as Taskbar from './taskbar.js'
+import * as Progress from './progress.js'
+import {
+ DTP_EXTENSION,
+ SETTINGS,
+ DESKTOPSETTINGS,
+ TERMINALSETTINGS,
+ EXTENSION_PATH,
+} from './extension.js'
+import {
+ gettext as _,
+ ngettext,
+} from 'resource:///org/gnome/shell/extensions/extension.js'
//timeout names
-const T2 = 'mouseScrollTimeout';
-const T3 = 'showDotsTimeout';
-const T4 = 'overviewWindowDragEndTimeout';
-const T5 = 'switchWorkspaceTimeout';
-const T6 = 'displayProperIndicatorTimeout';
+const T2 = 'mouseScrollTimeout'
+const T3 = 'showDotsTimeout'
+const T4 = 'overviewWindowDragEndTimeout'
+const T5 = 'switchWorkspaceTimeout'
+const T6 = 'displayProperIndicatorTimeout'
//right padding defined for .overview-label in stylesheet.css
-const TITLE_RIGHT_PADDING = 8;
-const DOUBLE_CLICK_DELAY_MS = 450;
+const TITLE_RIGHT_PADDING = 8
+const DOUBLE_CLICK_DELAY_MS = 450
-let LABEL_GAP = 5;
-let MAX_INDICATORS = 4;
-export const DEFAULT_PADDING_SIZE = 4;
+let LABEL_GAP = 5
+let MAX_INDICATORS = 4
+export const DEFAULT_PADDING_SIZE = 4
let APPICON_STYLE = {
- NORMAL: "NORMAL",
- SYMBOLIC: "SYMBOLIC",
- GRAYSCALE: "GRAYSCALE"
+ NORMAL: 'NORMAL',
+ SYMBOLIC: 'SYMBOLIC',
+ GRAYSCALE: 'GRAYSCALE',
}
let DOT_STYLE = {
- DOTS: "DOTS",
- SQUARES: "SQUARES",
- DASHES: "DASHES",
- SEGMENTED: "SEGMENTED",
- CILIORA: "CILIORA",
- METRO: "METRO",
- SOLID: "SOLID"
+ DOTS: 'DOTS',
+ SQUARES: 'SQUARES',
+ DASHES: 'DASHES',
+ SEGMENTED: 'SEGMENTED',
+ CILIORA: 'CILIORA',
+ METRO: 'METRO',
+ SOLID: 'SOLID',
}
let DOT_POSITION = {
- TOP: "TOP",
- BOTTOM: "BOTTOM",
- LEFT: 'LEFT',
- RIGHT: 'RIGHT'
+ TOP: 'TOP',
+ BOTTOM: 'BOTTOM',
+ LEFT: 'LEFT',
+ RIGHT: 'RIGHT',
}
-let recentlyClickedAppLoopId = 0;
-let recentlyClickedApp = null;
-let recentlyClickedAppWindows = null;
-let recentlyClickedAppIndex = 0;
-let recentlyClickedAppMonitorIndex;
+let recentlyClickedAppLoopId = 0
+let recentlyClickedApp = null
+let recentlyClickedAppWindows = null
+let recentlyClickedAppIndex = 0
+let recentlyClickedAppMonitorIndex
-let tracker = Shell.WindowTracker.get_default();
+let tracker = Shell.WindowTracker.get_default()
/**
* Extend AppIcon
@@ -107,1311 +115,1720 @@ let tracker = Shell.WindowTracker.get_default();
*
*/
-export const TaskbarAppIcon = GObject.registerClass({
-}, class TaskbarAppIcon extends AppDisplay.AppIcon {
-
+export const TaskbarAppIcon = GObject.registerClass(
+ {},
+ class TaskbarAppIcon extends AppDisplay.AppIcon {
_init(appInfo, panel, iconParams, previewMenu, iconAnimator) {
- this.dtpPanel = panel;
- this._nWindows = 0;
- this.window = appInfo.window;
- this.isLauncher = appInfo.isLauncher;
- this._previewMenu = previewMenu;
- this.iconAnimator = iconAnimator;
- this.lastClick = 0;
- this._appicon_normalstyle = '';
- this._appicon_hoverstyle = '';
- this._appicon_pressedstyle = '';
+ this.dtpPanel = panel
+ this._nWindows = 0
+ this.window = appInfo.window
+ this.isLauncher = appInfo.isLauncher
+ this._previewMenu = previewMenu
+ this.iconAnimator = iconAnimator
+ this.lastClick = 0
+ this._appicon_normalstyle = ''
+ this._appicon_hoverstyle = ''
+ this._appicon_pressedstyle = ''
- super._init(appInfo.app, iconParams);
+ super._init(appInfo.app, iconParams)
- this._timeoutsHandler = new Utils.TimeoutsHandler();
+ this._timeoutsHandler = new Utils.TimeoutsHandler()
- // Fix touchscreen issues before the listener is added by the parent constructor.
- this._onTouchEvent = function (actor, event) {
- if (event.type() == Clutter.EventType.TOUCH_BEGIN) {
- // Open the popup menu on long press.
- this._setPopupTimeout();
- } else if (this._menuTimeoutId != 0 && (event.type() == Clutter.EventType.TOUCH_END || event.type() == Clutter.EventType.TOUCH_CANCEL)) {
- // Activate/launch the application.
- this.activate(1);
- this._removeMenuTimeout();
+ // Fix touchscreen issues before the listener is added by the parent constructor.
+ this._onTouchEvent = function (actor, event) {
+ if (event.type() == Clutter.EventType.TOUCH_BEGIN) {
+ // Open the popup menu on long press.
+ this._setPopupTimeout()
+ } else if (
+ this._menuTimeoutId != 0 &&
+ (event.type() == Clutter.EventType.TOUCH_END ||
+ event.type() == Clutter.EventType.TOUCH_CANCEL)
+ ) {
+ // Activate/launch the application.
+ this.activate(1)
+ this._removeMenuTimeout()
+ }
+ // Disable dragging via touch screen as it's buggy as hell. Not perfect for tablet users, but the alternative is way worse.
+ // Also, EVENT_PROPAGATE launches applications twice with this solution, so this.activate(1) above must only be called if there's already a window.
+ return Clutter.EVENT_STOP
+ }
+ // Hack for missing TOUCH_END event.
+ this._onLeaveEvent = function (actor, event) {
+ this.fake_release()
+ if (this._menuTimeoutId != 0) this.activate(1) // Activate/launch the application if TOUCH_END didn't fire.
+ this._removeMenuTimeout()
+ }
+
+ this._dot.set_width(0)
+ this._isGroupApps = SETTINGS.get_boolean('group-apps')
+
+ this._container = new St.Widget({
+ style_class: 'dtp-container',
+ layout_manager: new Clutter.BinLayout(),
+ })
+ this._dotsContainer = new St.Widget({
+ style_class: 'dtp-dots-container',
+ layout_manager: new Clutter.BinLayout(),
+ })
+ this._dtpIconContainer = new St.Widget({
+ layout_manager: new Clutter.BinLayout(),
+ style: getIconContainerStyle(panel.checkIfVertical()),
+ })
+
+ this.remove_child(this._iconContainer)
+
+ this._dtpIconContainer.add_child(this._iconContainer)
+
+ if (appInfo.window) {
+ let box = new St.BoxLayout()
+
+ this._windowTitle = new St.Label({
+ y_align: Clutter.ActorAlign.CENTER,
+ x_align: Clutter.ActorAlign.START,
+ style_class: 'overview-label',
+ })
+
+ this._updateWindowTitle()
+ this._updateWindowTitleStyle()
+
+ this._scaleFactorChangedId = Utils.getStageTheme().connect(
+ 'changed',
+ () => this._updateWindowTitleStyle(),
+ )
+
+ box.add_child(this._dtpIconContainer)
+ box.add_child(this._windowTitle)
+
+ this._dotsContainer.add_child(box)
+ } else {
+ this._dotsContainer.add_child(this._dtpIconContainer)
+ }
+
+ this._container.add_child(this._dotsContainer)
+ this.set_child(this._container)
+
+ if (panel.checkIfVertical()) {
+ this.set_width(panel.geom.w)
+ }
+
+ // Monitor windows-changes instead of app state.
+ // Keep using the same Id and function callback (that is extended)
+ if (this._stateChangedId > 0) {
+ this.app.disconnect(this._stateChangedId)
+ this._stateChangedId = 0
+ }
+
+ this._onAnimateAppiconHoverChanged()
+ this._onAppIconHoverHighlightChanged()
+ this._setAppIconPadding()
+ this._setAppIconStyle()
+ this._showDots()
+
+ this._focusWindowChangedId = global.display.connect(
+ 'notify::focus-window',
+ this._onFocusAppChanged.bind(this),
+ )
+
+ this._windowEnteredMonitorId = this._windowLeftMonitorId = 0
+ this._stateChangedId = this.app.connect(
+ 'windows-changed',
+ this.onWindowsChanged.bind(this),
+ )
+
+ if (!this.window) {
+ if (SETTINGS.get_boolean('isolate-monitors')) {
+ this._windowEnteredMonitorId =
+ Utils.DisplayWrapper.getScreen().connect(
+ 'window-entered-monitor',
+ this.onWindowEnteredOrLeft.bind(this),
+ )
+ this._windowLeftMonitorId = Utils.DisplayWrapper.getScreen().connect(
+ 'window-left-monitor',
+ this.onWindowEnteredOrLeft.bind(this),
+ )
+ }
+
+ this._titleWindowChangeId = 0
+ this._minimizedWindowChangeId = 0
+
+ this._fullscreenId = Utils.DisplayWrapper.getScreen().connect(
+ 'in-fullscreen-changed',
+ () => {
+ if (
+ global.display.focus_window?.get_monitor() ==
+ this.dtpPanel.monitor.index &&
+ !this.dtpPanel.monitor.inFullscreen
+ ) {
+ this._resetDots(true)
+ this._displayProperIndicator()
}
- // Disable dragging via touch screen as it's buggy as hell. Not perfect for tablet users, but the alternative is way worse.
- // Also, EVENT_PROPAGATE launches applications twice with this solution, so this.activate(1) above must only be called if there's already a window.
- return Clutter.EVENT_STOP;
- };
- // Hack for missing TOUCH_END event.
- this._onLeaveEvent = function (actor, event) {
- this.fake_release();
- if (this._menuTimeoutId != 0) this.activate(1); // Activate/launch the application if TOUCH_END didn't fire.
- this._removeMenuTimeout();
- };
+ },
+ )
+ } else {
+ this._titleWindowChangeId = this.window.connect(
+ 'notify::title',
+ this._updateWindowTitle.bind(this),
+ )
+ this._minimizedWindowChangeId = this.window.connect(
+ 'notify::minimized',
+ this._updateWindowTitleStyle.bind(this),
+ )
+ }
- this._dot.set_width(0);
- this._isGroupApps = SETTINGS.get_boolean('group-apps');
+ this._scrollEventId = this.connect(
+ 'scroll-event',
+ this._onMouseScroll.bind(this),
+ )
- this._container = new St.Widget({ style_class: 'dtp-container', layout_manager: new Clutter.BinLayout() });
- this._dotsContainer = new St.Widget({ style_class: 'dtp-dots-container', layout_manager: new Clutter.BinLayout() });
- this._dtpIconContainer = new St.Widget({ layout_manager: new Clutter.BinLayout(), style: getIconContainerStyle(panel.checkIfVertical()) });
+ this._overviewWindowDragEndId = Main.overview.connect(
+ 'window-drag-end',
+ this._onOverviewWindowDragEnd.bind(this),
+ )
- this.remove_child(this._iconContainer);
+ this._switchWorkspaceId = global.window_manager.connect(
+ 'switch-workspace',
+ this._onSwitchWorkspace.bind(this),
+ )
- this._dtpIconContainer.add_child(this._iconContainer);
+ this._hoverChangeId = this.connect('notify::hover', () =>
+ this._onAppIconHoverChanged(),
+ )
- if (appInfo.window) {
- let box = new St.BoxLayout();
+ this._hoverChangeId2 = this.connect('notify::hover', () =>
+ this._onAppIconHoverChanged_GtkWorkaround(),
+ )
+ this._pressedChangedId = this.connect('notify::pressed', () =>
+ this._onAppIconPressedChanged_GtkWorkaround(),
+ )
- this._windowTitle = new St.Label({
- y_align: Clutter.ActorAlign.CENTER,
- x_align: Clutter.ActorAlign.START,
- style_class: 'overview-label'
- });
+ this._dtpSettingsSignalIds = [
+ SETTINGS.connect(
+ 'changed::animate-appicon-hover',
+ this._onAnimateAppiconHoverChanged.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::animate-appicon-hover',
+ this._onAppIconHoverHighlightChanged.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::highlight-appicon-hover',
+ this._onAppIconHoverHighlightChanged.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::highlight-appicon-hover-background-color',
+ this._onAppIconHoverHighlightChanged.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::highlight-appicon-pressed-background-color',
+ this._onAppIconHoverHighlightChanged.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::highlight-appicon-hover-border-radius',
+ this._onAppIconHoverHighlightChanged.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-position',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-size',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-style-focused',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-style-unfocused',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-color-dominant',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-color-override',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-color-1',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-color-2',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-color-3',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-color-4',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-color-unfocused-different',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-color-unfocused-1',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-color-unfocused-2',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-color-unfocused-3',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::dot-color-unfocused-4',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::focus-highlight',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::focus-highlight-dominant',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::focus-highlight-color',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::focus-highlight-opacity',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::group-apps-label-font-size',
+ this._updateWindowTitleStyle.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::group-apps-label-font-weight',
+ this._updateWindowTitleStyle.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::group-apps-label-font-color',
+ this._updateWindowTitleStyle.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::group-apps-label-font-color-minimized',
+ this._updateWindowTitleStyle.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::group-apps-label-max-width',
+ this._updateWindowTitleStyle.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::group-apps-use-fixed-width',
+ this._updateWindowTitleStyle.bind(this),
+ ),
+ SETTINGS.connect(
+ 'changed::group-apps-underline-unfocused',
+ this._settingsChangeRefresh.bind(this),
+ ),
+ ]
- this._updateWindowTitle();
- this._updateWindowTitleStyle();
+ this._dtpSettingsSignalIds = this._dtpSettingsSignalIds.concat([
+ SETTINGS.connect('changed::highlight-appicon-hover-border-radius', () =>
+ this._setIconStyle(this._isFocusedWindow()),
+ ),
+ ])
- this._scaleFactorChangedId = Utils.getStageTheme().connect('changed', () => this._updateWindowTitleStyle());
+ this._progressIndicator = new Progress.ProgressIndicator(
+ this,
+ panel.progressManager,
+ )
- box.add_child(this._dtpIconContainer);
- box.add_child(this._windowTitle);
-
- this._dotsContainer.add_child(box);
- } else {
- this._dotsContainer.add_child(this._dtpIconContainer);
- }
-
- this._container.add_child(this._dotsContainer);
- this.set_child(this._container);
-
- if (panel.checkIfVertical()) {
- this.set_width(panel.geom.w);
- }
-
- // Monitor windows-changes instead of app state.
- // Keep using the same Id and function callback (that is extended)
- if (this._stateChangedId > 0) {
- this.app.disconnect(this._stateChangedId);
- this._stateChangedId = 0;
- }
-
- this._onAnimateAppiconHoverChanged();
- this._onAppIconHoverHighlightChanged();
- this._setAppIconPadding();
- this._setAppIconStyle();
- this._showDots();
-
- this._focusWindowChangedId = global.display.connect('notify::focus-window',
- this._onFocusAppChanged.bind(this));
-
- this._windowEnteredMonitorId = this._windowLeftMonitorId = 0;
- this._stateChangedId = this.app.connect('windows-changed', this.onWindowsChanged.bind(this));
-
- if (!this.window) {
- if (SETTINGS.get_boolean('isolate-monitors')) {
- this._windowEnteredMonitorId = Utils.DisplayWrapper.getScreen().connect('window-entered-monitor', this.onWindowEnteredOrLeft.bind(this));
- this._windowLeftMonitorId = Utils.DisplayWrapper.getScreen().connect('window-left-monitor', this.onWindowEnteredOrLeft.bind(this));
- }
-
- this._titleWindowChangeId = 0;
- this._minimizedWindowChangeId = 0;
-
- this._fullscreenId = Utils.DisplayWrapper.getScreen().connect('in-fullscreen-changed', () => {
- if (
- global.display.focus_window?.get_monitor() == this.dtpPanel.monitor.index &&
- !this.dtpPanel.monitor.inFullscreen
- ) {
- this._resetDots(true);
- this._displayProperIndicator();
- }
- })
- } else {
- this._titleWindowChangeId = this.window.connect('notify::title',
- this._updateWindowTitle.bind(this));
-
- this._minimizedWindowChangeId = this.window.connect('notify::minimized',
- this._updateWindowTitleStyle.bind(this));
- }
-
- this._scrollEventId = this.connect('scroll-event', this._onMouseScroll.bind(this));
-
- this._overviewWindowDragEndId = Main.overview.connect('window-drag-end',
- this._onOverviewWindowDragEnd.bind(this));
-
- this._switchWorkspaceId = global.window_manager.connect('switch-workspace',
- this._onSwitchWorkspace.bind(this));
-
- this._hoverChangeId = this.connect('notify::hover', () => this._onAppIconHoverChanged());
-
- this._hoverChangeId2 = this.connect('notify::hover', () => this._onAppIconHoverChanged_GtkWorkaround());
- this._pressedChangedId = this.connect('notify::pressed', () => this._onAppIconPressedChanged_GtkWorkaround());
-
-
- this._dtpSettingsSignalIds = [
- SETTINGS.connect('changed::animate-appicon-hover', this._onAnimateAppiconHoverChanged.bind(this)),
- SETTINGS.connect('changed::animate-appicon-hover', this._onAppIconHoverHighlightChanged.bind(this)),
- SETTINGS.connect('changed::highlight-appicon-hover', this._onAppIconHoverHighlightChanged.bind(this)),
- SETTINGS.connect('changed::highlight-appicon-hover-background-color', this._onAppIconHoverHighlightChanged.bind(this)),
- SETTINGS.connect('changed::highlight-appicon-pressed-background-color', this._onAppIconHoverHighlightChanged.bind(this)),
- SETTINGS.connect('changed::highlight-appicon-hover-border-radius', this._onAppIconHoverHighlightChanged.bind(this)),
- SETTINGS.connect('changed::dot-position', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-size', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-style-focused', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-style-unfocused', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-color-dominant', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-color-override', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-color-1', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-color-2', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-color-3', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-color-4', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-color-unfocused-different', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-color-unfocused-1', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-color-unfocused-2', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-color-unfocused-3', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::dot-color-unfocused-4', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::focus-highlight', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::focus-highlight-dominant', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::focus-highlight-color', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::focus-highlight-opacity', this._settingsChangeRefresh.bind(this)),
- SETTINGS.connect('changed::group-apps-label-font-size', this._updateWindowTitleStyle.bind(this)),
- SETTINGS.connect('changed::group-apps-label-font-weight', this._updateWindowTitleStyle.bind(this)),
- SETTINGS.connect('changed::group-apps-label-font-color', this._updateWindowTitleStyle.bind(this)),
- SETTINGS.connect('changed::group-apps-label-font-color-minimized', this._updateWindowTitleStyle.bind(this)),
- SETTINGS.connect('changed::group-apps-label-max-width', this._updateWindowTitleStyle.bind(this)),
- SETTINGS.connect('changed::group-apps-use-fixed-width', this._updateWindowTitleStyle.bind(this)),
- SETTINGS.connect('changed::group-apps-underline-unfocused', this._settingsChangeRefresh.bind(this)),
- ];
-
- this._dtpSettingsSignalIds = this._dtpSettingsSignalIds.concat([
- SETTINGS.connect('changed::highlight-appicon-hover-border-radius', () => this._setIconStyle(this._isFocusedWindow())),
- ]);
-
-
- this._progressIndicator = new Progress.ProgressIndicator(this, panel.progressManager);
-
- this._numberOverlay();
+ this._numberOverlay()
}
getDragActor() {
- return this.app.create_icon_texture(this.dtpPanel.taskbar.iconSize);
+ return this.app.create_icon_texture(this.dtpPanel.taskbar.iconSize)
}
// Used by TaskbarItemContainer to animate appIcons on hover
getCloneButton() {
- // The source of the clone is this._dtpIconContainer,
- // which contains the icon but no highlighting elements
- // using this.actor directly would break DnD style.
- let cloneSource = this._dtpIconContainer;
- let clone = new Clutter.Clone({
- source: cloneSource,
- x: this.child.x, y: this.child.y,
- width: cloneSource.width, height: cloneSource.height,
- pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
- opacity: 255,
- reactive: false,
- x_align: Clutter.ActorAlign.CENTER, y_align: Clutter.ActorAlign.CENTER,
- });
+ // The source of the clone is this._dtpIconContainer,
+ // which contains the icon but no highlighting elements
+ // using this.actor directly would break DnD style.
+ let cloneSource = this._dtpIconContainer
+ let clone = new Clutter.Clone({
+ source: cloneSource,
+ x: this.child.x,
+ y: this.child.y,
+ width: cloneSource.width,
+ height: cloneSource.height,
+ pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
+ opacity: 255,
+ reactive: false,
+ x_align: Clutter.ActorAlign.CENTER,
+ y_align: Clutter.ActorAlign.CENTER,
+ })
- clone._delegate = this._delegate;
+ clone._delegate = this._delegate
- // "clone" of this.actor
- return new St.Button({
- child: clone,
- x: this.x, y: this.y,
- width: this.width, height: this.height,
- reactive: false,
- });
+ // "clone" of this.actor
+ return new St.Button({
+ child: clone,
+ x: this.x,
+ y: this.y,
+ width: this.width,
+ height: this.height,
+ reactive: false,
+ })
}
shouldShowTooltip() {
- if (!SETTINGS.get_boolean('show-tooltip') ||
- (!this.isLauncher && SETTINGS.get_boolean("show-window-previews") &&
- this.getAppIconInterestingWindows().length > 0)) {
- return false;
- } else {
- return this.hover && !this.window &&
- (!this._menu || !this._menu.isOpen) &&
- (this._previewMenu.getCurrentAppIcon() !== this);
- }
+ if (
+ !SETTINGS.get_boolean('show-tooltip') ||
+ (!this.isLauncher &&
+ SETTINGS.get_boolean('show-window-previews') &&
+ this.getAppIconInterestingWindows().length > 0)
+ ) {
+ return false
+ } else {
+ return (
+ this.hover &&
+ !this.window &&
+ (!this._menu || !this._menu.isOpen) &&
+ this._previewMenu.getCurrentAppIcon() !== this
+ )
+ }
}
_onAppIconHoverChanged() {
- if (!SETTINGS.get_boolean('show-window-previews') ||
- (!this.window && !this._nWindows)) {
- return;
- }
+ if (
+ !SETTINGS.get_boolean('show-window-previews') ||
+ (!this.window && !this._nWindows)
+ ) {
+ return
+ }
- if (this.hover) {
- this._previewMenu.requestOpen(this);
- } else {
- this._previewMenu.requestClose();
- }
+ if (this.hover) {
+ this._previewMenu.requestOpen(this)
+ } else {
+ this._previewMenu.requestClose()
+ }
}
_onDestroy() {
- super._onDestroy();
+ super._onDestroy()
- this._timeoutsHandler.destroy();
+ this._timeoutsHandler.destroy()
- this._previewMenu.close(true);
+ this._previewMenu.close(true)
- // Disconect global signals
- if (this._stateChangedId > 0) {
- this.app.disconnect(this._stateChangedId);
- this._stateChangedId = 0;
- }
+ // Disconect global signals
+ if (this._stateChangedId > 0) {
+ this.app.disconnect(this._stateChangedId)
+ this._stateChangedId = 0
+ }
- if (this._overviewWindowDragEndId)
- Main.overview.disconnect(this._overviewWindowDragEndId);
+ if (this._overviewWindowDragEndId)
+ Main.overview.disconnect(this._overviewWindowDragEndId)
- if (this._focusWindowChangedId)
- global.display.disconnect(this._focusWindowChangedId);
+ if (this._focusWindowChangedId)
+ global.display.disconnect(this._focusWindowChangedId)
- if (this._fullscreenId)
- Utils.DisplayWrapper.getScreen().disconnect(this._fullscreenId);
+ if (this._fullscreenId)
+ Utils.DisplayWrapper.getScreen().disconnect(this._fullscreenId)
- if (this._titleWindowChangeId)
- this.window.disconnect(this._titleWindowChangeId);
+ if (this._titleWindowChangeId)
+ this.window.disconnect(this._titleWindowChangeId)
- if (this._minimizedWindowChangeId)
- this.window.disconnect(this._minimizedWindowChangeId);
+ if (this._minimizedWindowChangeId)
+ this.window.disconnect(this._minimizedWindowChangeId)
- if (this._windowEnteredMonitorId) {
- Utils.DisplayWrapper.getScreen().disconnect(this._windowEnteredMonitorId);
- Utils.DisplayWrapper.getScreen().disconnect(this._windowLeftMonitorId);
- }
+ if (this._windowEnteredMonitorId) {
+ Utils.DisplayWrapper.getScreen().disconnect(
+ this._windowEnteredMonitorId,
+ )
+ Utils.DisplayWrapper.getScreen().disconnect(this._windowLeftMonitorId)
+ }
- if (this._switchWorkspaceId)
- global.window_manager.disconnect(this._switchWorkspaceId);
+ if (this._switchWorkspaceId)
+ global.window_manager.disconnect(this._switchWorkspaceId)
- if (this._scaleFactorChangedId)
- Utils.getStageTheme().disconnect(this._scaleFactorChangedId);
+ if (this._scaleFactorChangedId)
+ Utils.getStageTheme().disconnect(this._scaleFactorChangedId)
- if (this._hoverChangeId) {
- this.disconnect(this._hoverChangeId);
- }
- if (this._hoverChangeId2) {
- this.disconnect(this._hoverChangeId2);
- }
- if (this._pressedChangedId) {
- this.disconnect(this._pressedChangedId);
- }
+ if (this._hoverChangeId) {
+ this.disconnect(this._hoverChangeId)
+ }
+ if (this._hoverChangeId2) {
+ this.disconnect(this._hoverChangeId2)
+ }
+ if (this._pressedChangedId) {
+ this.disconnect(this._pressedChangedId)
+ }
- if (this._scrollEventId) {
- this.disconnect(this._scrollEventId);
- }
+ if (this._scrollEventId) {
+ this.disconnect(this._scrollEventId)
+ }
- for (let i = 0; i < this._dtpSettingsSignalIds.length; ++i) {
- SETTINGS.disconnect(this._dtpSettingsSignalIds[i]);
- }
+ for (let i = 0; i < this._dtpSettingsSignalIds.length; ++i) {
+ SETTINGS.disconnect(this._dtpSettingsSignalIds[i])
+ }
}
onWindowsChanged() {
- this._updateWindows();
- this.updateIcon();
+ this._updateWindows()
+ this.updateIcon()
- if (this._isGroupApps)
- this._setIconStyle();
+ if (this._isGroupApps) this._setIconStyle()
}
onWindowEnteredOrLeft(display, number, metaWindow) {
- if (number > 0 && tracker.get_window_app(metaWindow) == this.app) {
- this._updateWindows();
- this._displayProperIndicator();
- }
+ if (number > 0 && tracker.get_window_app(metaWindow) == this.app) {
+ this._updateWindows()
+ this._displayProperIndicator()
+ }
}
updateTitleStyle() {
- this._updateWindowTitleStyle();
+ this._updateWindowTitleStyle()
}
// Update indicator and target for minimization animation
updateIcon() {
+ // If (for unknown reason) the actor is not on the stage the reported size
+ // and position are random values, which might exceeds the integer range
+ // resulting in an error when assigned to the a rect. This is a more like
+ // a workaround to prevent flooding the system with errors.
+ if (this.get_stage() == null) return
- // If (for unknown reason) the actor is not on the stage the reported size
- // and position are random values, which might exceeds the integer range
- // resulting in an error when assigned to the a rect. This is a more like
- // a workaround to prevent flooding the system with errors.
- if (this.get_stage() == null)
- return;
+ let rect = new Mtk.Rectangle()
- let rect = new Mtk.Rectangle();
+ ;[rect.x, rect.y] = this.get_transformed_position()
+ ;[rect.width, rect.height] = this.get_transformed_size()
- [rect.x, rect.y] = this.get_transformed_position();
- [rect.width, rect.height] = this.get_transformed_size();
-
- let windows = this.window ? [this.window] : this.getAppIconInterestingWindows(true);
- windows.forEach(function (w) {
- w.set_icon_geometry(rect);
- });
+ let windows = this.window
+ ? [this.window]
+ : this.getAppIconInterestingWindows(true)
+ windows.forEach(function (w) {
+ w.set_icon_geometry(rect)
+ })
}
_onAnimateAppiconHoverChanged() {
- if (SETTINGS.get_boolean('animate-appicon-hover')) {
- this._container.add_style_class_name('animate-appicon-hover');
+ if (SETTINGS.get_boolean('animate-appicon-hover')) {
+ this._container.add_style_class_name('animate-appicon-hover')
- // Workaround to prevent scaled icon from being ugly when it is animated on hover.
- // It increases the "resolution" of the icon without changing the icon size.
- this.icon.createIcon = (iconSize) => this.app.create_icon_texture(2 * iconSize);
- this._iconIconBinActorAddedId = this.icon._iconBin.connect('child-added', () => {
- let size = this.icon.iconSize * Utils.getScaleFactor()
+ // Workaround to prevent scaled icon from being ugly when it is animated on hover.
+ // It increases the "resolution" of the icon without changing the icon size.
+ this.icon.createIcon = (iconSize) =>
+ this.app.create_icon_texture(2 * iconSize)
+ this._iconIconBinActorAddedId = this.icon._iconBin.connect(
+ 'child-added',
+ () => {
+ let size = this.icon.iconSize * Utils.getScaleFactor()
- if (this.icon._iconBin.child.mapped) {
- this.icon._iconBin.child.set_size(size, size);
- } else {
- let iconMappedId = this.icon._iconBin.child.connect('notify::mapped', () => {
- this.icon._iconBin.child.set_size(size, size);
- this.icon._iconBin.child.disconnect(iconMappedId);
- });
- }
- });
- if (this.icon._iconBin.child)
- this.icon._createIconTexture(this.icon.iconSize);
- } else {
- this._container.remove_style_class_name('animate-appicon-hover');
-
- if (this._iconIconBinActorAddedId) {
- this.icon._iconBin.disconnect(this._iconIconBinActorAddedId);
- this._iconIconBinActorAddedId = 0;
- this.icon.createIcon = this._createIcon.bind(this);
+ if (this.icon._iconBin.child.mapped) {
+ this.icon._iconBin.child.set_size(size, size)
+ } else {
+ let iconMappedId = this.icon._iconBin.child.connect(
+ 'notify::mapped',
+ () => {
+ this.icon._iconBin.child.set_size(size, size)
+ this.icon._iconBin.child.disconnect(iconMappedId)
+ },
+ )
}
+ },
+ )
+ if (this.icon._iconBin.child)
+ this.icon._createIconTexture(this.icon.iconSize)
+ } else {
+ this._container.remove_style_class_name('animate-appicon-hover')
+
+ if (this._iconIconBinActorAddedId) {
+ this.icon._iconBin.disconnect(this._iconIconBinActorAddedId)
+ this._iconIconBinActorAddedId = 0
+ this.icon.createIcon = this._createIcon.bind(this)
}
+ }
}
_onAppIconHoverHighlightChanged() {
- const background_color = SETTINGS.get_string('highlight-appicon-hover-background-color');
- const pressed_color = SETTINGS.get_string('highlight-appicon-pressed-background-color');
- const border_radius = SETTINGS.get_int('highlight-appicon-hover-border-radius');
+ const background_color = SETTINGS.get_string(
+ 'highlight-appicon-hover-background-color',
+ )
+ const pressed_color = SETTINGS.get_string(
+ 'highlight-appicon-pressed-background-color',
+ )
+ const border_radius = SETTINGS.get_int(
+ 'highlight-appicon-hover-border-radius',
+ )
- // Some trickery needed to get the effect
- const br = `border-radius: ${border_radius}px;`;
- this._appicon_normalstyle = br;
- this._container.set_style(this._appicon_normalstyle);
- this._appicon_hoverstyle = `background-color: ${background_color}; ${br}`;
- this._appicon_pressedstyle = `background-color: ${pressed_color}; ${br}`;
+ // Some trickery needed to get the effect
+ const br = `border-radius: ${border_radius}px;`
+ this._appicon_normalstyle = br
+ this._container.set_style(this._appicon_normalstyle)
+ this._appicon_hoverstyle = `background-color: ${background_color}; ${br}`
+ this._appicon_pressedstyle = `background-color: ${pressed_color}; ${br}`
- if (SETTINGS.get_boolean('highlight-appicon-hover')) {
- this._container.remove_style_class_name('no-highlight');
- } else {
- this._container.add_style_class_name('no-highlight');
- this._appicon_normalstyle = '';
- this._appicon_hoverstyle = '';
- this._appicon_pressedstyle = '';
- }
+ if (SETTINGS.get_boolean('highlight-appicon-hover')) {
+ this._container.remove_style_class_name('no-highlight')
+ } else {
+ this._container.add_style_class_name('no-highlight')
+ this._appicon_normalstyle = ''
+ this._appicon_hoverstyle = ''
+ this._appicon_pressedstyle = ''
+ }
}
_onAppIconHoverChanged_GtkWorkaround() {
- if (this.hover && this._appicon_hoverstyle) {
- this._container.set_style(this._appicon_hoverstyle);
- } else if (this._appicon_normalstyle) {
- this._container.set_style(this._appicon_normalstyle);
- } else {
- this._container.set_style('');
- }
+ if (this.hover && this._appicon_hoverstyle) {
+ this._container.set_style(this._appicon_hoverstyle)
+ } else if (this._appicon_normalstyle) {
+ this._container.set_style(this._appicon_normalstyle)
+ } else {
+ this._container.set_style('')
+ }
}
_onAppIconPressedChanged_GtkWorkaround() {
- if (this.pressed && this._appicon_pressedstyle) {
- this._container.set_style(this._appicon_pressedstyle);
- } else if (this.hover && this._appicon_hoverstyle) {
- this._container.set_style(this._appicon_hoverstyle);
- } else if (this._appicon_normalstyle) {
- this._container.set_style(this._appicon_normalstyle);
- } else {
- this._container.set_style('');
- }
+ if (this.pressed && this._appicon_pressedstyle) {
+ this._container.set_style(this._appicon_pressedstyle)
+ } else if (this.hover && this._appicon_hoverstyle) {
+ this._container.set_style(this._appicon_hoverstyle)
+ } else if (this._appicon_normalstyle) {
+ this._container.set_style(this._appicon_normalstyle)
+ } else {
+ this._container.set_style('')
+ }
}
_onMouseScroll(actor, event) {
- let scrollAction = SETTINGS.get_string('scroll-icon-action');
+ let scrollAction = SETTINGS.get_string('scroll-icon-action')
- if (scrollAction === 'PASS_THROUGH') {
- return this.dtpPanel._onPanelMouseScroll(actor, event);
- } else if (scrollAction === 'NOTHING' || (!this.window && !this._nWindows)) {
- return;
- }
+ if (scrollAction === 'PASS_THROUGH') {
+ return this.dtpPanel._onPanelMouseScroll(actor, event)
+ } else if (
+ scrollAction === 'NOTHING' ||
+ (!this.window && !this._nWindows)
+ ) {
+ return
+ }
- let direction = Utils.getMouseScrollDirection(event);
+ let direction = Utils.getMouseScrollDirection(event)
- if (direction && !this._timeoutsHandler.getId(T2)) {
- this._timeoutsHandler.add([T2, SETTINGS.get_int('scroll-icon-delay'), () => { }]);
+ if (direction && !this._timeoutsHandler.getId(T2)) {
+ this._timeoutsHandler.add([
+ T2,
+ SETTINGS.get_int('scroll-icon-delay'),
+ () => {},
+ ])
- let windows = this.getAppIconInterestingWindows();
+ let windows = this.getAppIconInterestingWindows()
- windows.sort(Taskbar.sortWindowsCompareFunction);
- Utils.activateSiblingWindow(windows, direction, this.window);
- }
+ windows.sort(Taskbar.sortWindowsCompareFunction)
+ Utils.activateSiblingWindow(windows, direction, this.window)
+ }
}
_showDots() {
- // Just update style if dots already exist
- if (this._focusedDots && this._unfocusedDots) {
- this._updateWindows();
- return;
- }
+ // Just update style if dots already exist
+ if (this._focusedDots && this._unfocusedDots) {
+ this._updateWindows()
+ return
+ }
- if (!this._isGroupApps) {
- this._focusedDots = new St.Widget({
- layout_manager: new Clutter.BinLayout(),
- x_expand: true, y_expand: true,
- visible: false
- });
+ if (!this._isGroupApps) {
+ this._focusedDots = new St.Widget({
+ layout_manager: new Clutter.BinLayout(),
+ x_expand: true,
+ y_expand: true,
+ visible: false,
+ })
- let mappedId = this.connect('notify::mapped', () => {
- this._displayProperIndicator();
- this.disconnect(mappedId);
- });
- } else {
- this._focusedDots = new St.DrawingArea(),
- this._unfocusedDots = new St.DrawingArea();
+ let mappedId = this.connect('notify::mapped', () => {
+ this._displayProperIndicator()
+ this.disconnect(mappedId)
+ })
+ } else {
+ ;(this._focusedDots = new St.DrawingArea()),
+ (this._unfocusedDots = new St.DrawingArea())
- this._focusedDots.connect('repaint', () => {
- if (!this._dashItemContainer.animatingOut)
- // don't draw and trigger more animations if the icon is in the middle of
- // being removed from the panel
- this._drawRunningIndicator(this._focusedDots, SETTINGS.get_string('dot-style-focused'), true);
- });
+ this._focusedDots.connect('repaint', () => {
+ if (!this._dashItemContainer.animatingOut)
+ // don't draw and trigger more animations if the icon is in the middle of
+ // being removed from the panel
+ this._drawRunningIndicator(
+ this._focusedDots,
+ SETTINGS.get_string('dot-style-focused'),
+ true,
+ )
+ })
- this._unfocusedDots.connect('repaint', () => {
- if (!this._dashItemContainer.animatingOut)
- this._drawRunningIndicator(this._unfocusedDots, SETTINGS.get_string('dot-style-unfocused'), false);
- });
+ this._unfocusedDots.connect('repaint', () => {
+ if (!this._dashItemContainer.animatingOut)
+ this._drawRunningIndicator(
+ this._unfocusedDots,
+ SETTINGS.get_string('dot-style-unfocused'),
+ false,
+ )
+ })
- this._dotsContainer.add_child(this._unfocusedDots);
+ this._dotsContainer.add_child(this._unfocusedDots)
- this._updateWindows();
+ this._updateWindows()
- this._timeoutsHandler.add([T3, 0, () => {
- this._resetDots();
- this._displayProperIndicator();
- }]);
- }
+ this._timeoutsHandler.add([
+ T3,
+ 0,
+ () => {
+ this._resetDots()
+ this._displayProperIndicator()
+ },
+ ])
+ }
- this._dotsContainer.add_child(this._focusedDots);
+ this._dotsContainer.add_child(this._focusedDots)
}
_resetDots(ignoreSizeReset) {
- let position = SETTINGS.get_string('dot-position');
- let isHorizontalDots = position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM;
- let sizeProp = isHorizontalDots ? 'width' : 'height';
- let focusedDotStyle = SETTINGS.get_string('dot-style-focused');
- let unfocusedDotStyle = SETTINGS.get_string('dot-style-unfocused');
+ let position = SETTINGS.get_string('dot-position')
+ let isHorizontalDots =
+ position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM
+ let sizeProp = isHorizontalDots ? 'width' : 'height'
+ let focusedDotStyle = SETTINGS.get_string('dot-style-focused')
+ let unfocusedDotStyle = SETTINGS.get_string('dot-style-unfocused')
- this._focusedIsWide = this._isWideDotStyle(focusedDotStyle);
- this._unfocusedIsWide = this._isWideDotStyle(unfocusedDotStyle);
+ this._focusedIsWide = this._isWideDotStyle(focusedDotStyle)
+ this._unfocusedIsWide = this._isWideDotStyle(unfocusedDotStyle)
+ ;[, this._containerSize] =
+ this._container[`get_preferred_${sizeProp}`](-1)
- [, this._containerSize] = this._container[`get_preferred_${sizeProp}`](-1);
+ if (!ignoreSizeReset) {
+ ;[this._focusedDots, this._unfocusedDots].forEach((d) => {
+ d.set_size(-1, -1)
+ d.x_expand = d.y_expand = false
- if (!ignoreSizeReset) {
- [this._focusedDots, this._unfocusedDots].forEach(d => {
- d.set_size(-1, -1);
- d.x_expand = d.y_expand = false;
-
- d[sizeProp] = 1;
- d[(isHorizontalDots ? 'y' : 'x') + '_expand'] = true;
- });
- }
+ d[sizeProp] = 1
+ d[(isHorizontalDots ? 'y' : 'x') + '_expand'] = true
+ })
+ }
}
_settingsChangeRefresh() {
- if (this._isGroupApps) {
- this._updateWindows();
- this._resetDots();
- this._focusedDots.queue_repaint();
- this._unfocusedDots.queue_repaint();
- }
+ if (this._isGroupApps) {
+ this._updateWindows()
+ this._resetDots()
+ this._focusedDots.queue_repaint()
+ this._unfocusedDots.queue_repaint()
+ }
- this._displayProperIndicator();
+ this._displayProperIndicator()
}
_updateWindowTitleStyle() {
- if (this._windowTitle) {
- let useFixedWidth = SETTINGS.get_boolean('group-apps-use-fixed-width');
- let fontWeight = SETTINGS.get_string('group-apps-label-font-weight');
- let fontScale = DESKTOPSETTINGS.get_double('text-scaling-factor');
- let fontColor = this.window.minimized ?
- SETTINGS.get_string('group-apps-label-font-color-minimized') :
- SETTINGS.get_string('group-apps-label-font-color');
- let scaleFactor = Utils.getScaleFactor();
- let maxLabelWidth = SETTINGS.get_int('group-apps-label-max-width') * scaleFactor;
- let variableWidth = !useFixedWidth || this.dtpPanel.checkIfVertical() || this.dtpPanel.taskbar.fullScrollView;
+ if (this._windowTitle) {
+ let useFixedWidth = SETTINGS.get_boolean('group-apps-use-fixed-width')
+ let fontWeight = SETTINGS.get_string('group-apps-label-font-weight')
+ let fontScale = DESKTOPSETTINGS.get_double('text-scaling-factor')
+ let fontColor = this.window.minimized
+ ? SETTINGS.get_string('group-apps-label-font-color-minimized')
+ : SETTINGS.get_string('group-apps-label-font-color')
+ let scaleFactor = Utils.getScaleFactor()
+ let maxLabelWidth =
+ SETTINGS.get_int('group-apps-label-max-width') * scaleFactor
+ let variableWidth =
+ !useFixedWidth ||
+ this.dtpPanel.checkIfVertical() ||
+ this.dtpPanel.taskbar.fullScrollView
- this._windowTitle[(maxLabelWidth > 0 ? 'show' : 'hide')]();
- this._windowTitle.set_width(variableWidth ? -1 : maxLabelWidth + TITLE_RIGHT_PADDING * scaleFactor);
+ this._windowTitle[maxLabelWidth > 0 ? 'show' : 'hide']()
+ this._windowTitle.set_width(
+ variableWidth
+ ? -1
+ : maxLabelWidth + TITLE_RIGHT_PADDING * scaleFactor,
+ )
- this._windowTitle.clutter_text.natural_width = useFixedWidth ? maxLabelWidth : 0;
- this._windowTitle.clutter_text.natural_width_set = useFixedWidth;
+ this._windowTitle.clutter_text.natural_width = useFixedWidth
+ ? maxLabelWidth
+ : 0
+ this._windowTitle.clutter_text.natural_width_set = useFixedWidth
- this._windowTitle.set_style('font-size: ' + SETTINGS.get_int('group-apps-label-font-size') * fontScale + 'px;' +
- 'font-weight: ' + fontWeight + ';' +
- (useFixedWidth ? '' : 'max-width: ' + maxLabelWidth + 'px;') +
- 'color: ' + fontColor);
- }
+ this._windowTitle.set_style(
+ 'font-size: ' +
+ SETTINGS.get_int('group-apps-label-font-size') * fontScale +
+ 'px;' +
+ 'font-weight: ' +
+ fontWeight +
+ ';' +
+ (useFixedWidth ? '' : 'max-width: ' + maxLabelWidth + 'px;') +
+ 'color: ' +
+ fontColor,
+ )
+ }
}
_updateWindowTitle() {
- if (this._windowTitle.text != this.window.title) {
- this._windowTitle.text = (this.window.title ? this.window.title : this.app.get_name()).replace(/\r?\n|\r/g, '').trim();
+ if (this._windowTitle.text != this.window.title) {
+ this._windowTitle.text = (
+ this.window.title ? this.window.title : this.app.get_name()
+ )
+ .replace(/\r?\n|\r/g, '')
+ .trim()
- if (this._focusedDots) {
- this._displayProperIndicator();
- }
+ if (this._focusedDots) {
+ this._displayProperIndicator()
}
+ }
}
_setIconStyle(isFocused) {
- let inlineStyle = 'margin: 0;';
+ let inlineStyle = 'margin: 0;'
- if (SETTINGS.get_boolean('focus-highlight') &&
- this._checkIfFocusedApp() && !this.isLauncher &&
- (!this.window || isFocused) && !this._isThemeProvidingIndicator() && this._checkIfMonitorHasFocus()) {
- let focusedDotStyle = SETTINGS.get_string('dot-style-focused');
- let pos = SETTINGS.get_string('dot-position');
- let highlightMargin = this._focusedIsWide ? SETTINGS.get_int('dot-size') : 0;
+ if (
+ SETTINGS.get_boolean('focus-highlight') &&
+ this._checkIfFocusedApp() &&
+ !this.isLauncher &&
+ (!this.window || isFocused) &&
+ !this._isThemeProvidingIndicator() &&
+ this._checkIfMonitorHasFocus()
+ ) {
+ let focusedDotStyle = SETTINGS.get_string('dot-style-focused')
+ let pos = SETTINGS.get_string('dot-position')
+ let highlightMargin = this._focusedIsWide
+ ? SETTINGS.get_int('dot-size')
+ : 0
- if (!this.window) {
- let containerWidth = this._dtpIconContainer.get_width() / Utils.getScaleFactor();
- let backgroundSize = containerWidth + "px " +
- (containerWidth - (pos == DOT_POSITION.BOTTOM ? highlightMargin : 0)) + "px;";
+ if (!this.window) {
+ let containerWidth =
+ this._dtpIconContainer.get_width() / Utils.getScaleFactor()
+ let backgroundSize =
+ containerWidth +
+ 'px ' +
+ (containerWidth -
+ (pos == DOT_POSITION.BOTTOM ? highlightMargin : 0)) +
+ 'px;'
- if (focusedDotStyle == DOT_STYLE.CILIORA || focusedDotStyle == DOT_STYLE.SEGMENTED)
- highlightMargin += 1;
+ if (
+ focusedDotStyle == DOT_STYLE.CILIORA ||
+ focusedDotStyle == DOT_STYLE.SEGMENTED
+ )
+ highlightMargin += 1
- if (this._nWindows > 1 && focusedDotStyle == DOT_STYLE.METRO) {
- let bgSvg = '/img/highlight_stacked_bg';
+ if (this._nWindows > 1 && focusedDotStyle == DOT_STYLE.METRO) {
+ let bgSvg = '/img/highlight_stacked_bg'
- if (pos == DOT_POSITION.LEFT || pos == DOT_POSITION.RIGHT) {
- bgSvg += (this.dtpPanel.checkIfVertical() ? '_2' : '_3');
- }
-
- inlineStyle += "background-image: url('" + EXTENSION_PATH + bgSvg + ".svg');" +
- "background-position: 0 " + (pos == DOT_POSITION.TOP ? highlightMargin : 0) + "px;" +
- "background-size: " + backgroundSize;
- }
+ if (pos == DOT_POSITION.LEFT || pos == DOT_POSITION.RIGHT) {
+ bgSvg += this.dtpPanel.checkIfVertical() ? '_2' : '_3'
}
- let highlightColor = this._getFocusHighlightColor();
- inlineStyle += "background-color: " + cssHexTocssRgba(highlightColor, SETTINGS.get_int('focus-highlight-opacity') * 0.01) + ";";
- inlineStyle += this._appicon_normalstyle;
+ inlineStyle +=
+ "background-image: url('" +
+ EXTENSION_PATH +
+ bgSvg +
+ ".svg');" +
+ 'background-position: 0 ' +
+ (pos == DOT_POSITION.TOP ? highlightMargin : 0) +
+ 'px;' +
+ 'background-size: ' +
+ backgroundSize
+ }
}
- if (this._dotsContainer.get_style() != inlineStyle) {
- this._dotsContainer.set_style(inlineStyle);
- }
+ let highlightColor = this._getFocusHighlightColor()
+ inlineStyle +=
+ 'background-color: ' +
+ cssHexTocssRgba(
+ highlightColor,
+ SETTINGS.get_int('focus-highlight-opacity') * 0.01,
+ ) +
+ ';'
+ inlineStyle += this._appicon_normalstyle
+ }
+
+ if (this._dotsContainer.get_style() != inlineStyle) {
+ this._dotsContainer.set_style(inlineStyle)
+ }
}
_checkIfFocusedApp() {
- return tracker.focus_app == this.app;
+ return tracker.focus_app == this.app
}
_checkIfMonitorHasFocus() {
- return global.display.focus_window &&
- (!SETTINGS.get_boolean('multi-monitors') || // only check same monitor index if multi window is enabled.
- !SETTINGS.get_boolean('isolate-monitors') ||
- global.display.focus_window.get_monitor() === this.dtpPanel.monitor.index);
+ return (
+ global.display.focus_window &&
+ (!SETTINGS.get_boolean('multi-monitors') || // only check same monitor index if multi window is enabled.
+ !SETTINGS.get_boolean('isolate-monitors') ||
+ global.display.focus_window.get_monitor() ===
+ this.dtpPanel.monitor.index)
+ )
}
_setAppIconPadding() {
- const padding = getIconPadding(this.dtpPanel.monitor.index);
- const margin = SETTINGS.get_int('appicon-margin');
- const margin_todesktop = SETTINGS.get_int('appicon-margin-todesktop');
- const margin_toscreenborder = SETTINGS.get_int('appicon-margin-toscreenborder');
+ const padding = getIconPadding(this.dtpPanel.monitor.index)
+ const margin = SETTINGS.get_int('appicon-margin')
+ const margin_todesktop = SETTINGS.get_int('appicon-margin-todesktop')
+ const margin_toscreenborder = SETTINGS.get_int(
+ 'appicon-margin-toscreenborder',
+ )
- let margin_style = '';
- const panelPosition = this.dtpPanel.getPosition();
- if (panelPosition == St.Side.TOP) {
- margin_style = `${margin_toscreenborder}px ${margin}px ${margin_todesktop}px ${margin}px`;
- } else if (panelPosition == St.Side.RIGHT) {
- margin_style = `${margin}px ${margin_toscreenborder}px ${margin}px ${margin_todesktop}px`;
- } else if (panelPosition == St.Side.LEFT) {
- margin_style = `${margin}px ${margin_todesktop}px ${margin}px ${margin_toscreenborder}px`;
- } else {
- margin_style = `${margin_todesktop}px ${margin}px ${margin_toscreenborder}px ${margin}px`;
- }
- this.set_style(`padding: ${margin_style};`);
- this._iconContainer.set_style('padding: ' + padding + 'px;');
+ let margin_style = ''
+ const panelPosition = this.dtpPanel.getPosition()
+ if (panelPosition == St.Side.TOP) {
+ margin_style = `${margin_toscreenborder}px ${margin}px ${margin_todesktop}px ${margin}px`
+ } else if (panelPosition == St.Side.RIGHT) {
+ margin_style = `${margin}px ${margin_toscreenborder}px ${margin}px ${margin_todesktop}px`
+ } else if (panelPosition == St.Side.LEFT) {
+ margin_style = `${margin}px ${margin_todesktop}px ${margin}px ${margin_toscreenborder}px`
+ } else {
+ margin_style = `${margin_todesktop}px ${margin}px ${margin_toscreenborder}px ${margin}px`
+ }
+ this.set_style(`padding: ${margin_style};`)
+ this._iconContainer.set_style('padding: ' + padding + 'px;')
}
_setAppIconStyle() {
- let appIconStyle = SETTINGS.get_string('appicon-style');
+ let appIconStyle = SETTINGS.get_string('appicon-style')
- if (appIconStyle === APPICON_STYLE.SYMBOLIC) {
- this.add_style_class_name('symbolic-icon-style');
- } else if (appIconStyle === APPICON_STYLE.GRAYSCALE) {
- this._iconContainer.add_effect_with_name('desaturate', new Clutter.DesaturateEffect({ factor: 1 }));
- }
+ if (appIconStyle === APPICON_STYLE.SYMBOLIC) {
+ this.add_style_class_name('symbolic-icon-style')
+ } else if (appIconStyle === APPICON_STYLE.GRAYSCALE) {
+ this._iconContainer.add_effect_with_name(
+ 'desaturate',
+ new Clutter.DesaturateEffect({ factor: 1 }),
+ )
+ }
}
popupMenu() {
- this._removeMenuTimeout();
- this.fake_release();
+ this._removeMenuTimeout()
+ this.fake_release()
- if (!this._menu) {
- this._menu = new TaskbarSecondaryMenu(this, this.dtpPanel.geom.position);
- this._menu.setApp(this.app);
- this._menu.connect('open-state-changed', (menu, isPoppedUp) => {
- if (!isPoppedUp)
- this._onMenuPoppedDown();
- else
- this._previewMenu.close(true);
- });
- let id = Main.overview.connect('hiding', () => {
- this._menu.close();
- });
- this.connect('destroy', () => {
- Main.overview.disconnect(id);
- });
+ if (!this._menu) {
+ this._menu = new TaskbarSecondaryMenu(this, this.dtpPanel.geom.position)
+ this._menu.setApp(this.app)
+ this._menu.connect('open-state-changed', (menu, isPoppedUp) => {
+ if (!isPoppedUp) this._onMenuPoppedDown()
+ else this._previewMenu.close(true)
+ })
+ let id = Main.overview.connect('hiding', () => {
+ this._menu.close()
+ })
+ this.connect('destroy', () => {
+ Main.overview.disconnect(id)
+ })
- // We want to keep the item hovered while the menu is up
- this._menu.blockSourceEvents = true;
+ // We want to keep the item hovered while the menu is up
+ this._menu.blockSourceEvents = true
- Main.uiGroup.add_child(this._menu.actor);
- this._menuManager.addMenu(this._menu);
- }
- this._menu.updateQuitText();
+ Main.uiGroup.add_child(this._menu.actor)
+ this._menuManager.addMenu(this._menu)
+ }
+ this._menu.updateQuitText()
- this.emit('menu-state-changed', true);
+ this.emit('menu-state-changed', true)
- this.set_hover(true);
- this._menu.open(BoxPointer.PopupAnimation.FULL);
- this._menuManager.ignoreRelease();
- this.emit('sync-tooltip');
+ this.set_hover(true)
+ this._menu.open(BoxPointer.PopupAnimation.FULL)
+ this._menuManager.ignoreRelease()
+ this.emit('sync-tooltip')
- return false;
+ return false
}
_onFocusAppChanged(windowTracker) {
- this._displayProperIndicator();
+ this._displayProperIndicator()
}
_onOverviewWindowDragEnd(windowTracker) {
- this._timeoutsHandler.add([T4, 0, () => {
- if (SETTINGS.get_boolean('isolate-workspaces'))
- this._updateWindows()
+ this._timeoutsHandler.add([
+ T4,
+ 0,
+ () => {
+ if (SETTINGS.get_boolean('isolate-workspaces')) this._updateWindows()
- this._displayProperIndicator()
- }]);
+ this._displayProperIndicator()
+ },
+ ])
}
_onSwitchWorkspace(windowTracker) {
- if (this._isGroupApps) {
- this._timeoutsHandler.add([T5, 0, () => this._displayProperIndicator()]);
- } else {
- this._displayProperIndicator();
- }
+ if (this._isGroupApps) {
+ this._timeoutsHandler.add([T5, 0, () => this._displayProperIndicator()])
+ } else {
+ this._displayProperIndicator()
+ }
}
_displayProperIndicator() {
- let isFocused = this._isFocusedWindow();
- let position = SETTINGS.get_string('dot-position');
- let isHorizontalDots = position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM;
+ let isFocused = this._isFocusedWindow()
+ let position = SETTINGS.get_string('dot-position')
+ let isHorizontalDots =
+ position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM
- this._setIconStyle(isFocused);
+ this._setIconStyle(isFocused)
- if (!this._isGroupApps) {
- if (this.window && (SETTINGS.get_boolean('group-apps-underline-unfocused') || isFocused)) {
- let align = Clutter.ActorAlign[position == DOT_POSITION.TOP || position == DOT_POSITION.LEFT ? 'START' : 'END'];
+ if (!this._isGroupApps) {
+ if (
+ this.window &&
+ (SETTINGS.get_boolean('group-apps-underline-unfocused') || isFocused)
+ ) {
+ let align =
+ Clutter.ActorAlign[
+ position == DOT_POSITION.TOP || position == DOT_POSITION.LEFT
+ ? 'START'
+ : 'END'
+ ]
- this._focusedDots.set_size(0, 0);
- this._focusedDots[isHorizontalDots ? 'height' : 'width'] = this._getRunningIndicatorSize();
+ this._focusedDots.set_size(0, 0)
+ this._focusedDots[isHorizontalDots ? 'height' : 'width'] =
+ this._getRunningIndicatorSize()
- this._focusedDots.y_align = this._focusedDots.x_align = Clutter.ActorAlign.FILL;
- this._focusedDots[(isHorizontalDots ? 'y' : 'x') + '_align'] = align;
- this._focusedDots.background_color = this._getRunningIndicatorColor(isFocused);
- this._focusedDots.show();
- } else if (this._focusedDots.visible) {
- this._focusedDots.hide();
- }
- } else {
- let sizeProp = isHorizontalDots ? 'width' : 'height';
- let newFocusedDotsSize = 0;
- let newFocusedDotsOpacity = 0;
- let newUnfocusedDotsSize = 0;
- let newUnfocusedDotsOpacity = 0;
-
- isFocused = this._checkIfFocusedApp() && this._checkIfMonitorHasFocus();
-
- this._timeoutsHandler.add([T6, 0, () => {
- if (isFocused)
- this.add_style_class_name('focused');
- else
- this.remove_style_class_name('focused');
- }]);
-
- if (this._focusedIsWide) {
- newFocusedDotsSize = (isFocused && this._nWindows > 0) ? this._containerSize : 0;
- newFocusedDotsOpacity = 255;
- } else {
- newFocusedDotsSize = this._containerSize;
- newFocusedDotsOpacity = (isFocused && this._nWindows > 0) ? 255 : 0;
- }
-
- if (this._unfocusedIsWide) {
- newUnfocusedDotsSize = (!isFocused && this._nWindows > 0) ? this._containerSize : 0;
- newUnfocusedDotsOpacity = 255;
- } else {
- newUnfocusedDotsSize = this._containerSize;
- newUnfocusedDotsOpacity = (!isFocused && this._nWindows > 0) ? 255 : 0;
- }
-
- // Only animate if...
- // animation is enabled in settings
- // AND (going from a wide style to a narrow style indicator or vice-versa
- // OR going from an open app to a closed app or vice versa)
- let animate = SETTINGS.get_boolean('animate-app-switch') &&
- ((this._focusedIsWide != this._unfocusedIsWide) ||
- (this._focusedDots[sizeProp] != newUnfocusedDotsSize || this._unfocusedDots[sizeProp] != newFocusedDotsSize))
- let duration = animate ? Taskbar.DASH_ANIMATION_TIME : 0.001;
-
- this._animateDotDisplay(this._focusedDots, newFocusedDotsSize, this._unfocusedDots, newUnfocusedDotsOpacity, sizeProp, duration);
- this._animateDotDisplay(this._unfocusedDots, newUnfocusedDotsSize, this._focusedDots, newFocusedDotsOpacity, sizeProp, duration);
+ this._focusedDots.y_align = this._focusedDots.x_align =
+ Clutter.ActorAlign.FILL
+ this._focusedDots[(isHorizontalDots ? 'y' : 'x') + '_align'] = align
+ this._focusedDots.background_color =
+ this._getRunningIndicatorColor(isFocused)
+ this._focusedDots.show()
+ } else if (this._focusedDots.visible) {
+ this._focusedDots.hide()
}
+ } else {
+ let sizeProp = isHorizontalDots ? 'width' : 'height'
+ let newFocusedDotsSize = 0
+ let newFocusedDotsOpacity = 0
+ let newUnfocusedDotsSize = 0
+ let newUnfocusedDotsOpacity = 0
+
+ isFocused = this._checkIfFocusedApp() && this._checkIfMonitorHasFocus()
+
+ this._timeoutsHandler.add([
+ T6,
+ 0,
+ () => {
+ if (isFocused) this.add_style_class_name('focused')
+ else this.remove_style_class_name('focused')
+ },
+ ])
+
+ if (this._focusedIsWide) {
+ newFocusedDotsSize =
+ isFocused && this._nWindows > 0 ? this._containerSize : 0
+ newFocusedDotsOpacity = 255
+ } else {
+ newFocusedDotsSize = this._containerSize
+ newFocusedDotsOpacity = isFocused && this._nWindows > 0 ? 255 : 0
+ }
+
+ if (this._unfocusedIsWide) {
+ newUnfocusedDotsSize =
+ !isFocused && this._nWindows > 0 ? this._containerSize : 0
+ newUnfocusedDotsOpacity = 255
+ } else {
+ newUnfocusedDotsSize = this._containerSize
+ newUnfocusedDotsOpacity = !isFocused && this._nWindows > 0 ? 255 : 0
+ }
+
+ // Only animate if...
+ // animation is enabled in settings
+ // AND (going from a wide style to a narrow style indicator or vice-versa
+ // OR going from an open app to a closed app or vice versa)
+ let animate =
+ SETTINGS.get_boolean('animate-app-switch') &&
+ (this._focusedIsWide != this._unfocusedIsWide ||
+ this._focusedDots[sizeProp] != newUnfocusedDotsSize ||
+ this._unfocusedDots[sizeProp] != newFocusedDotsSize)
+ let duration = animate ? Taskbar.DASH_ANIMATION_TIME : 0.001
+
+ this._animateDotDisplay(
+ this._focusedDots,
+ newFocusedDotsSize,
+ this._unfocusedDots,
+ newUnfocusedDotsOpacity,
+ sizeProp,
+ duration,
+ )
+ this._animateDotDisplay(
+ this._unfocusedDots,
+ newUnfocusedDotsSize,
+ this._focusedDots,
+ newFocusedDotsOpacity,
+ sizeProp,
+ duration,
+ )
+ }
}
- _animateDotDisplay(dots, newSize, otherDots, newOtherOpacity, sizeProp, duration) {
- Utils.stopAnimations(dots)
+ _animateDotDisplay(
+ dots,
+ newSize,
+ otherDots,
+ newOtherOpacity,
+ sizeProp,
+ duration,
+ ) {
+ Utils.stopAnimations(dots)
- let tweenOpts = {
- time: duration,
- transition: 'easeInOutCubic',
- onComplete: () => {
- if (newOtherOpacity > 0)
- otherDots.opacity = newOtherOpacity;
- }
- };
+ let tweenOpts = {
+ time: duration,
+ transition: 'easeInOutCubic',
+ onComplete: () => {
+ if (newOtherOpacity > 0) otherDots.opacity = newOtherOpacity
+ },
+ }
- if (newOtherOpacity == 0)
- otherDots.opacity = newOtherOpacity;
+ if (newOtherOpacity == 0) otherDots.opacity = newOtherOpacity
- tweenOpts[sizeProp] = newSize;
+ tweenOpts[sizeProp] = newSize
- Utils.animate(dots, tweenOpts);
+ Utils.animate(dots, tweenOpts)
}
_isFocusedWindow() {
- let focusedWindow = global.display.focus_window;
+ let focusedWindow = global.display.focus_window
- while (focusedWindow) {
- if (focusedWindow == this.window) {
- return true;
- }
-
- focusedWindow = focusedWindow.get_transient_for();
+ while (focusedWindow) {
+ if (focusedWindow == this.window) {
+ return true
}
- return false;
+ focusedWindow = focusedWindow.get_transient_for()
+ }
+
+ return false
}
_isWideDotStyle(dotStyle) {
- return dotStyle == DOT_STYLE.SEGMENTED ||
- dotStyle == DOT_STYLE.CILIORA ||
- dotStyle == DOT_STYLE.METRO ||
- dotStyle == DOT_STYLE.SOLID;
+ return (
+ dotStyle == DOT_STYLE.SEGMENTED ||
+ dotStyle == DOT_STYLE.CILIORA ||
+ dotStyle == DOT_STYLE.METRO ||
+ dotStyle == DOT_STYLE.SOLID
+ )
}
_isThemeProvidingIndicator() {
- // This is an attempt to determine if the theme is providing their own
- // running indicator by way of a border image on the icon, for example in
- // the theme Ciliora
- return (this.icon.get_stage() &&
- this.icon.get_theme_node().get_border_image());
+ // This is an attempt to determine if the theme is providing their own
+ // running indicator by way of a border image on the icon, for example in
+ // the theme Ciliora
+ return (
+ this.icon.get_stage() && this.icon.get_theme_node().get_border_image()
+ )
}
activate(button, modifiers, handleAsGrouped) {
- let event = Clutter.get_current_event();
+ let event = Clutter.get_current_event()
- modifiers = event ? event.get_state() : modifiers || 0;
+ modifiers = event ? event.get_state() : modifiers || 0
- // Only consider SHIFT and CONTROL as modifiers (exclude SUPER, CAPS-LOCK, etc.)
- modifiers = modifiers & (Clutter.ModifierType.SHIFT_MASK | Clutter.ModifierType.CONTROL_MASK);
+ // Only consider SHIFT and CONTROL as modifiers (exclude SUPER, CAPS-LOCK, etc.)
+ modifiers =
+ modifiers &
+ (Clutter.ModifierType.SHIFT_MASK | Clutter.ModifierType.CONTROL_MASK)
- let ctrlPressed = modifiers & Clutter.ModifierType.CONTROL_MASK
+ let ctrlPressed = modifiers & Clutter.ModifierType.CONTROL_MASK
- if (ctrlPressed) {
- // CTRL-click or hotkey with ctrl
- return this._launchNewInstance(true);
- }
+ if (ctrlPressed) {
+ // CTRL-click or hotkey with ctrl
+ return this._launchNewInstance(true)
+ }
- // We check what type of click we have and if the modifier SHIFT is
- // being used. We then define what buttonAction should be for this
- // event.
- let buttonAction = 0;
- let doubleClick;
+ // We check what type of click we have and if the modifier SHIFT is
+ // being used. We then define what buttonAction should be for this
+ // event.
+ let buttonAction = 0
+ let doubleClick
- if (button && button == 2) {
- if (modifiers & Clutter.ModifierType.SHIFT_MASK)
- buttonAction = SETTINGS.get_string('shift-middle-click-action');
- else
- buttonAction = SETTINGS.get_string('middle-click-action');
- }
- // fixed issue #1676 by checking for button 0 or 1 to also handle touchscreen
- // input, probably not the proper fix as i'm not aware button 0 should exist
- // but from using this fix for months it seems to not create any issues
- else if (button === 0 || button === 1) {
- let now = global.get_current_time()
+ if (button && button == 2) {
+ if (modifiers & Clutter.ModifierType.SHIFT_MASK)
+ buttonAction = SETTINGS.get_string('shift-middle-click-action')
+ else buttonAction = SETTINGS.get_string('middle-click-action')
+ }
+ // fixed issue #1676 by checking for button 0 or 1 to also handle touchscreen
+ // input, probably not the proper fix as i'm not aware button 0 should exist
+ // but from using this fix for months it seems to not create any issues
+ else if (button === 0 || button === 1) {
+ let now = global.get_current_time()
- doubleClick = now - this.lastClick < DOUBLE_CLICK_DELAY_MS
- this.lastClick = now
+ doubleClick = now - this.lastClick < DOUBLE_CLICK_DELAY_MS
+ this.lastClick = now
- if (modifiers & Clutter.ModifierType.SHIFT_MASK)
- buttonAction = SETTINGS.get_string('shift-click-action');
- else
- buttonAction = SETTINGS.get_string('click-action');
- }
+ if (modifiers & Clutter.ModifierType.SHIFT_MASK)
+ buttonAction = SETTINGS.get_string('shift-click-action')
+ else buttonAction = SETTINGS.get_string('click-action')
+ }
- let closePreview = () => this._previewMenu.close(SETTINGS.get_boolean('window-preview-hide-immediate-click'));
- let appCount = this.getAppIconInterestingWindows().length;
- let previewedAppIcon = this._previewMenu.getCurrentAppIcon();
+ let closePreview = () =>
+ this._previewMenu.close(
+ SETTINGS.get_boolean('window-preview-hide-immediate-click'),
+ )
+ let appCount = this.getAppIconInterestingWindows().length
+ let previewedAppIcon = this._previewMenu.getCurrentAppIcon()
- if (this.window || buttonAction != 'TOGGLE-SHOWPREVIEW')
- closePreview()
+ if (this.window || buttonAction != 'TOGGLE-SHOWPREVIEW') closePreview()
- // We check if the app is running, and that the # of windows is > 0 in
- // case we use workspace isolation,
- let appIsRunning = this.app.state == Shell.AppState.RUNNING && appCount > 0;
+ // We check if the app is running, and that the # of windows is > 0 in
+ // case we use workspace isolation,
+ let appIsRunning =
+ this.app.state == Shell.AppState.RUNNING && appCount > 0
- // We customize the action only when the application is already running
- if (appIsRunning && !this.isLauncher) {
- if (this.window && !handleAsGrouped) {
- //ungrouped applications behaviors
- switch (buttonAction) {
- case 'RAISE': case 'CYCLE': case 'CYCLE-MIN': case 'MINIMIZE': case 'TOGGLE-SHOWPREVIEW': case 'TOGGLE-CYCLE':
- if (!Main.overview._shown &&
- (buttonAction == 'MINIMIZE' || buttonAction == 'TOGGLE-SHOWPREVIEW' || buttonAction == 'TOGGLE-CYCLE' || buttonAction == 'CYCLE-MIN') &&
- (this._isFocusedWindow() || (buttonAction == 'MINIMIZE' && (button == 2 || modifiers & Clutter.ModifierType.SHIFT_MASK)))) {
- this.window.minimize();
- } else {
- Main.activateWindow(this.window);
- }
+ // We customize the action only when the application is already running
+ if (appIsRunning && !this.isLauncher) {
+ if (this.window && !handleAsGrouped) {
+ //ungrouped applications behaviors
+ switch (buttonAction) {
+ case 'RAISE':
+ case 'CYCLE':
+ case 'CYCLE-MIN':
+ case 'MINIMIZE':
+ case 'TOGGLE-SHOWPREVIEW':
+ case 'TOGGLE-CYCLE':
+ if (
+ !Main.overview._shown &&
+ (buttonAction == 'MINIMIZE' ||
+ buttonAction == 'TOGGLE-SHOWPREVIEW' ||
+ buttonAction == 'TOGGLE-CYCLE' ||
+ buttonAction == 'CYCLE-MIN') &&
+ (this._isFocusedWindow() ||
+ (buttonAction == 'MINIMIZE' &&
+ (button == 2 ||
+ modifiers & Clutter.ModifierType.SHIFT_MASK)))
+ ) {
+ this.window.minimize()
+ } else {
+ Main.activateWindow(this.window)
+ }
- break;
+ break
- case "LAUNCH":
- this._launchNewInstance();
- break;
+ case 'LAUNCH':
+ this._launchNewInstance()
+ break
- case "QUIT":
- this.window.delete(global.get_current_time());
- break;
+ case 'QUIT':
+ this.window.delete(global.get_current_time())
+ break
+ }
+ } else {
+ //grouped application behaviors
+ let monitor = this.dtpPanel.monitor
+ let appHasFocus =
+ this._checkIfFocusedApp() && this._checkIfMonitorHasFocus()
+
+ switch (buttonAction) {
+ case 'RAISE':
+ activateAllWindows(this.app, monitor)
+ break
+
+ case 'LAUNCH':
+ this._launchNewInstance()
+ break
+
+ case 'MINIMIZE':
+ // In overview just activate the app, unless the acion is explicitely
+ // requested with a keyboard modifier
+ if (!Main.overview._shown || modifiers) {
+ // If we have button=2 or a modifier, allow minimization even if
+ // the app is not focused
+ if (
+ appHasFocus ||
+ button == 2 ||
+ modifiers & Clutter.ModifierType.SHIFT_MASK
+ ) {
+ // minimize all windows on double click and always in the case of primary click without
+ // additional modifiers
+ let all_windows = (button == 1 && !modifiers) || doubleClick
+ minimizeWindow(this.app, all_windows, monitor)
+ } else activateAllWindows(this.app, monitor)
+ } else this.app.activate()
+ break
+
+ case 'CYCLE':
+ if (!Main.overview._shown) {
+ if (appHasFocus)
+ cycleThroughWindows(this.app, false, false, monitor)
+ else {
+ activateFirstWindow(this.app, monitor)
}
- } else {
- //grouped application behaviors
- let monitor = this.dtpPanel.monitor;
- let appHasFocus = this._checkIfFocusedApp() && this._checkIfMonitorHasFocus();
-
- switch (buttonAction) {
- case "RAISE":
- activateAllWindows(this.app, monitor);
- break;
-
- case "LAUNCH":
- this._launchNewInstance();
- break;
-
- case "MINIMIZE":
- // In overview just activate the app, unless the acion is explicitely
- // requested with a keyboard modifier
- if (!Main.overview._shown || modifiers) {
- // If we have button=2 or a modifier, allow minimization even if
- // the app is not focused
- if (appHasFocus || button == 2 || modifiers & Clutter.ModifierType.SHIFT_MASK) {
- // minimize all windows on double click and always in the case of primary click without
- // additional modifiers
- let all_windows = (button == 1 && !modifiers) || doubleClick;
- minimizeWindow(this.app, all_windows, monitor);
- }
- else
- activateAllWindows(this.app, monitor);
- }
- else
- this.app.activate();
- break;
-
- case "CYCLE":
- if (!Main.overview._shown) {
- if (appHasFocus)
- cycleThroughWindows(this.app, false, false, monitor);
- else {
- activateFirstWindow(this.app, monitor);
- }
- }
- else
- this.app.activate();
- break;
- case "CYCLE-MIN":
- if (!Main.overview._shown) {
- if (appHasFocus || (recentlyClickedApp == this.app && recentlyClickedAppWindows[recentlyClickedAppIndex % recentlyClickedAppWindows.length] == "MINIMIZE"))
- cycleThroughWindows(this.app, false, true, monitor);
- else {
- activateFirstWindow(this.app, monitor);
- }
- }
- else
- this.app.activate();
- break;
- case "TOGGLE-SHOWPREVIEW":
- if (!Main.overview._shown) {
- if (appCount == 1) {
- closePreview()
-
- if (appHasFocus)
- minimizeWindow(this.app, false, monitor);
- else
- activateFirstWindow(this.app, monitor);
- } else {
- if (doubleClick) {
- // minimize all windows if double clicked
- closePreview()
- minimizeWindow(this.app, true, monitor);
- } else if (previewedAppIcon != this) {
- this._previewMenu.open(this);
- }
-
- this.emit('sync-tooltip');
- }
- }
- else
- this.app.activate();
- break;
- case "TOGGLE-CYCLE":
- if (!Main.overview._shown) {
- if (appCount == 1) {
- if (appHasFocus)
- minimizeWindow(this.app, false, monitor);
- else
- activateFirstWindow(this.app, monitor);
- } else {
- cycleThroughWindows(this.app, false, false, monitor);
- }
- }
- else
- this.app.activate();
- break;
- case "QUIT":
- closeAllWindows(this.app, monitor);
- break;
+ } else this.app.activate()
+ break
+ case 'CYCLE-MIN':
+ if (!Main.overview._shown) {
+ if (
+ appHasFocus ||
+ (recentlyClickedApp == this.app &&
+ recentlyClickedAppWindows[
+ recentlyClickedAppIndex % recentlyClickedAppWindows.length
+ ] == 'MINIMIZE')
+ )
+ cycleThroughWindows(this.app, false, true, monitor)
+ else {
+ activateFirstWindow(this.app, monitor)
}
- }
- }
- else {
- this._launchNewInstance();
- }
+ } else this.app.activate()
+ break
+ case 'TOGGLE-SHOWPREVIEW':
+ if (!Main.overview._shown) {
+ if (appCount == 1) {
+ closePreview()
- global.display.emit('grab-op-begin', null, null);
- Main.overview.hide();
+ if (appHasFocus) minimizeWindow(this.app, false, monitor)
+ else activateFirstWindow(this.app, monitor)
+ } else {
+ if (doubleClick) {
+ // minimize all windows if double clicked
+ closePreview()
+ minimizeWindow(this.app, true, monitor)
+ } else if (previewedAppIcon != this) {
+ this._previewMenu.open(this)
+ }
+
+ this.emit('sync-tooltip')
+ }
+ } else this.app.activate()
+ break
+ case 'TOGGLE-CYCLE':
+ if (!Main.overview._shown) {
+ if (appCount == 1) {
+ if (appHasFocus) minimizeWindow(this.app, false, monitor)
+ else activateFirstWindow(this.app, monitor)
+ } else {
+ cycleThroughWindows(this.app, false, false, monitor)
+ }
+ } else this.app.activate()
+ break
+ case 'QUIT':
+ closeAllWindows(this.app, monitor)
+ break
+ }
+ }
+ } else {
+ this._launchNewInstance()
+ }
+
+ global.display.emit('grab-op-begin', null, null)
+ Main.overview.hide()
}
_launchNewInstance(ctrlPressed) {
- let maybeAnimate = () => SETTINGS.get_boolean('animate-window-launch') && this.animateLaunch()
+ let maybeAnimate = () =>
+ SETTINGS.get_boolean('animate-window-launch') && this.animateLaunch()
- if ((ctrlPressed || this.app.state == Shell.AppState.RUNNING) &&
- this.app.can_open_new_window()) {
- maybeAnimate();
- this.app.open_new_window(-1);
+ if (
+ (ctrlPressed || this.app.state == Shell.AppState.RUNNING) &&
+ this.app.can_open_new_window()
+ ) {
+ maybeAnimate()
+ this.app.open_new_window(-1)
+ } else {
+ let windows = this.window ? [this.window] : this.app.get_windows()
+
+ if (windows.length) {
+ Main.activateWindow(windows[0])
} else {
- let windows = this.window ? [this.window] : this.app.get_windows();
-
- if (windows.length) {
- Main.activateWindow(windows[0]);
- } else {
- maybeAnimate();
- this.app.activate();
- }
+ maybeAnimate()
+ this.app.activate()
}
+ }
}
_updateWindows() {
- let windows = [this.window];
+ let windows = [this.window]
- if (!this.window) {
- windows = this.getAppIconInterestingWindows();
+ if (!this.window) {
+ windows = this.getAppIconInterestingWindows()
- this._nWindows = windows.length;
+ this._nWindows = windows.length
- for (let i = 1; i <= MAX_INDICATORS; i++) {
- let className = 'running' + i;
- if (i != this._nWindows)
- this.remove_style_class_name(className);
- else
- this.add_style_class_name(className);
- }
+ for (let i = 1; i <= MAX_INDICATORS; i++) {
+ let className = 'running' + i
+ if (i != this._nWindows) this.remove_style_class_name(className)
+ else this.add_style_class_name(className)
}
+ }
- this._previewMenu.update(this, windows);
+ this._previewMenu.update(this, windows)
}
_getRunningIndicatorCount() {
- return Math.min(this._nWindows, MAX_INDICATORS);
+ return Math.min(this._nWindows, MAX_INDICATORS)
}
_getRunningIndicatorSize() {
- return SETTINGS.get_int('dot-size') * Utils.getScaleFactor();
+ return SETTINGS.get_int('dot-size') * Utils.getScaleFactor()
}
_getRunningIndicatorColor(isFocused) {
- let color;
- const fallbackColor = new Utils.ColorUtils.Color({ red: 82, green: 148, blue: 226, alpha: 255 });
+ let color
+ const fallbackColor = new Utils.ColorUtils.Color({
+ red: 82,
+ green: 148,
+ blue: 226,
+ alpha: 255,
+ })
- if (SETTINGS.get_boolean('dot-color-dominant')) {
- let dce = new Utils.DominantColorExtractor(this.app);
- let palette = dce._getColorPalette();
- if (palette) {
- color = Utils.ColorUtils.color_from_string(palette.original)[1];
- } else { // unable to determine color, fall back to theme
- let themeNode = this._dot.get_theme_node();
- color = themeNode.get_background_color();
-
- // theme didn't provide one, use a default
- if (color.alpha == 0) color = fallbackColor;
- }
- } else if (SETTINGS.get_boolean('dot-color-override')) {
- let dotColorSettingPrefix = 'dot-color-';
-
- if (!isFocused && SETTINGS.get_boolean('dot-color-unfocused-different'))
- dotColorSettingPrefix = 'dot-color-unfocused-';
-
- color = Utils.ColorUtils.color_from_string(SETTINGS.get_string(dotColorSettingPrefix + (this._getRunningIndicatorCount() || 1)))[1];
+ if (SETTINGS.get_boolean('dot-color-dominant')) {
+ let dce = new Utils.DominantColorExtractor(this.app)
+ let palette = dce._getColorPalette()
+ if (palette) {
+ color = Utils.ColorUtils.color_from_string(palette.original)[1]
} else {
- // Re-use the style - background color, and border width and color -
- // of the default dot
- let themeNode = this._dot.get_theme_node();
- color = themeNode.get_background_color();
+ // unable to determine color, fall back to theme
+ let themeNode = this._dot.get_theme_node()
+ color = themeNode.get_background_color()
- // theme didn't provide one, use a default
- if (color.alpha == 0) color = fallbackColor;
+ // theme didn't provide one, use a default
+ if (color.alpha == 0) color = fallbackColor
}
+ } else if (SETTINGS.get_boolean('dot-color-override')) {
+ let dotColorSettingPrefix = 'dot-color-'
- return color;
+ if (!isFocused && SETTINGS.get_boolean('dot-color-unfocused-different'))
+ dotColorSettingPrefix = 'dot-color-unfocused-'
+
+ color = Utils.ColorUtils.color_from_string(
+ SETTINGS.get_string(
+ dotColorSettingPrefix + (this._getRunningIndicatorCount() || 1),
+ ),
+ )[1]
+ } else {
+ // Re-use the style - background color, and border width and color -
+ // of the default dot
+ let themeNode = this._dot.get_theme_node()
+ color = themeNode.get_background_color()
+
+ // theme didn't provide one, use a default
+ if (color.alpha == 0) color = fallbackColor
+ }
+
+ return color
}
_getFocusHighlightColor() {
- if (SETTINGS.get_boolean('focus-highlight-dominant')) {
- let dce = new Utils.DominantColorExtractor(this.app);
- let palette = dce._getColorPalette();
- if (palette) return palette.original;
- }
- return SETTINGS.get_string('focus-highlight-color');
+ if (SETTINGS.get_boolean('focus-highlight-dominant')) {
+ let dce = new Utils.DominantColorExtractor(this.app)
+ let palette = dce._getColorPalette()
+ if (palette) return palette.original
+ }
+ return SETTINGS.get_string('focus-highlight-color')
}
_drawRunningIndicator(area, type, isFocused) {
- let n = this._getRunningIndicatorCount();
+ let n = this._getRunningIndicatorCount()
- if (!n) {
- return;
+ if (!n) {
+ return
+ }
+
+ let position = SETTINGS.get_string('dot-position')
+ let isHorizontalDots =
+ position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM
+ let bodyColor = this._getRunningIndicatorColor(isFocused)
+ let [areaWidth, areaHeight] = area.get_surface_size()
+ let cr = area.get_context()
+ let size = this._getRunningIndicatorSize()
+
+ let areaSize = areaWidth
+ let startX = 0
+ let startY = 0
+
+ if (isHorizontalDots) {
+ if (position == DOT_POSITION.BOTTOM) {
+ startY = areaHeight - size
}
+ } else {
+ areaSize = areaHeight
- let position = SETTINGS.get_string('dot-position');
- let isHorizontalDots = position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM;
- let bodyColor = this._getRunningIndicatorColor(isFocused);
- let [areaWidth, areaHeight] = area.get_surface_size();
- let cr = area.get_context();
- let size = this._getRunningIndicatorSize();
+ if (position == DOT_POSITION.RIGHT) {
+ startX = areaWidth - size
+ }
+ }
- let areaSize = areaWidth;
- let startX = 0;
- let startY = 0;
-
- if (isHorizontalDots) {
- if (position == DOT_POSITION.BOTTOM) {
- startY = areaHeight - size;
- }
+ if (type == DOT_STYLE.SOLID || type == DOT_STYLE.METRO) {
+ if (type == DOT_STYLE.SOLID || n <= 1) {
+ cr.translate(startX, startY)
+ cr.setSourceColor(bodyColor)
+ cr.newSubPath()
+ cr.rectangle.apply(
+ cr,
+ [0, 0].concat(
+ isHorizontalDots ? [areaSize, size] : [size, areaSize],
+ ),
+ )
+ cr.fill()
} else {
- areaSize = areaHeight;
+ let blackenedLength = (1 / 48) * areaSize // need to scale with the SVG for the stacked highlight
+ let darkenedLength = isFocused
+ ? (2 / 48) * areaSize
+ : (10 / 48) * areaSize
+ let blackenedColor = new Utils.ColorUtils.Color({
+ red: bodyColor.red * 0.3,
+ green: bodyColor.green * 0.3,
+ blue: bodyColor.blue * 0.3,
+ alpha: bodyColor.alpha,
+ })
+ let darkenedColor = new Utils.ColorUtils.Color({
+ red: bodyColor.red * 0.7,
+ green: bodyColor.green * 0.7,
+ blue: bodyColor.blue * 0.7,
+ alpha: bodyColor.alpha,
+ })
+ let solidDarkLength = areaSize - darkenedLength
+ let solidLength = solidDarkLength - blackenedLength
- if (position == DOT_POSITION.RIGHT) {
- startX = areaWidth - size;
- }
+ cr.translate(startX, startY)
+
+ cr.setSourceColor(bodyColor)
+ cr.newSubPath()
+ cr.rectangle.apply(
+ cr,
+ [0, 0].concat(
+ isHorizontalDots ? [solidLength, size] : [size, solidLength],
+ ),
+ )
+ cr.fill()
+ cr.setSourceColor(blackenedColor)
+ cr.newSubPath()
+ cr.rectangle.apply(
+ cr,
+ isHorizontalDots
+ ? [solidLength, 0, 1, size]
+ : [0, solidLength, size, 1],
+ )
+ cr.fill()
+ cr.setSourceColor(darkenedColor)
+ cr.newSubPath()
+ cr.rectangle.apply(
+ cr,
+ isHorizontalDots
+ ? [solidDarkLength, 0, darkenedLength, size]
+ : [0, solidDarkLength, size, darkenedLength],
+ )
+ cr.fill()
+ }
+ } else {
+ let spacing = Math.ceil(areaSize / 18) // separation between the indicators
+ let length
+ let dist
+ let indicatorSize
+ let translate
+ let preDraw = () => {}
+ let draw
+ let drawDash = (i, dashLength) => {
+ dist = i * dashLength + i * spacing
+ cr.rectangle.apply(
+ cr,
+ isHorizontalDots
+ ? [dist, 0, dashLength, size]
+ : [0, dist, size, dashLength],
+ )
}
- if (type == DOT_STYLE.SOLID || type == DOT_STYLE.METRO) {
- if (type == DOT_STYLE.SOLID || n <= 1) {
- cr.translate(startX, startY);
- cr.setSourceColor(bodyColor);
- cr.newSubPath();
- cr.rectangle.apply(cr, [0, 0].concat(isHorizontalDots ? [areaSize, size] : [size, areaSize]));
- cr.fill();
- } else {
- let blackenedLength = (1 / 48) * areaSize; // need to scale with the SVG for the stacked highlight
- let darkenedLength = isFocused ? (2 / 48) * areaSize : (10 / 48) * areaSize;
- let blackenedColor = new Utils.ColorUtils.Color({ red: bodyColor.red * .3, green: bodyColor.green * .3, blue: bodyColor.blue * .3, alpha: bodyColor.alpha });
- let darkenedColor = new Utils.ColorUtils.Color({ red: bodyColor.red * .7, green: bodyColor.green * .7, blue: bodyColor.blue * .7, alpha: bodyColor.alpha });
- let solidDarkLength = areaSize - darkenedLength;
- let solidLength = solidDarkLength - blackenedLength;
-
- cr.translate(startX, startY);
-
- cr.setSourceColor(bodyColor);
- cr.newSubPath();
- cr.rectangle.apply(cr, [0, 0].concat(isHorizontalDots ? [solidLength, size] : [size, solidLength]));
- cr.fill();
- cr.setSourceColor(blackenedColor);
- cr.newSubPath();
- cr.rectangle.apply(cr, isHorizontalDots ? [solidLength, 0, 1, size] : [0, solidLength, size, 1]);
- cr.fill();
- cr.setSourceColor(darkenedColor);
- cr.newSubPath();
- cr.rectangle.apply(cr, isHorizontalDots ? [solidDarkLength, 0, darkenedLength, size] : [0, solidDarkLength, size, darkenedLength]);
- cr.fill();
+ switch (type) {
+ case DOT_STYLE.CILIORA:
+ spacing = size
+ length = areaSize - size * (n - 1) - spacing * (n - 1)
+ translate = () => cr.translate(startX, startY)
+ preDraw = () => {
+ cr.newSubPath()
+ cr.rectangle.apply(
+ cr,
+ [0, 0].concat(
+ isHorizontalDots ? [length, size] : [size, length],
+ ),
+ )
}
- } else {
- let spacing = Math.ceil(areaSize / 18); // separation between the indicators
- let length;
- let dist;
- let indicatorSize;
- let translate;
- let preDraw = () => { };
- let draw;
- let drawDash = (i, dashLength) => {
- dist = i * dashLength + i * spacing;
- cr.rectangle.apply(cr, (isHorizontalDots ? [dist, 0, dashLength, size] : [0, dist, size, dashLength]));
- };
-
- switch (type) {
- case DOT_STYLE.CILIORA:
- spacing = size;
- length = areaSize - (size * (n - 1)) - (spacing * (n - 1));
- translate = () => cr.translate(startX, startY);
- preDraw = () => {
- cr.newSubPath();
- cr.rectangle.apply(cr, [0, 0].concat(isHorizontalDots ? [length, size] : [size, length]));
- };
- draw = i => {
- dist = length + (i * spacing) + ((i - 1) * size);
- cr.rectangle.apply(cr, (isHorizontalDots ? [dist, 0] : [0, dist]).concat([size, size]));
- };
- break;
- case DOT_STYLE.DOTS:
- let radius = size / 2;
-
- translate = () => {
- indicatorSize = Math.floor((areaSize - n * size - (n - 1) * spacing) / 2);
- cr.translate.apply(cr, isHorizontalDots ? [indicatorSize, startY] : [startX, indicatorSize]);
- }
- draw = i => {
- dist = (2 * i + 1) * radius + i * spacing;
- cr.arc.apply(cr, (isHorizontalDots ? [dist, radius] : [radius, dist]).concat([radius, 0, 2 * Math.PI]));
- };
- break;
- case DOT_STYLE.SQUARES:
- translate = () => {
- indicatorSize = Math.floor((areaSize - n * size - (n - 1) * spacing) / 2);
- cr.translate.apply(cr, isHorizontalDots ? [indicatorSize, startY] : [startX, indicatorSize]);
- }
- draw = i => {
- dist = i * size + i * spacing;
- cr.rectangle.apply(cr, (isHorizontalDots ? [dist, 0] : [0, dist]).concat([size, size]));
- };
- break;
- case DOT_STYLE.DASHES:
- length = Math.floor(areaSize / 4) - spacing;
- translate = () => {
- indicatorSize = Math.floor((areaSize - n * length - (n - 1) * spacing) / 2);
- cr.translate.apply(cr, isHorizontalDots ? [indicatorSize, startY] : [startX, indicatorSize]);
- }
- draw = i => drawDash(i, length);
- break;
- case DOT_STYLE.SEGMENTED:
- length = Math.ceil((areaSize - ((n - 1) * spacing)) / n);
- translate = () => cr.translate(startX, startY);
- draw = i => drawDash(i, length);
- break;
+ draw = (i) => {
+ dist = length + i * spacing + (i - 1) * size
+ cr.rectangle.apply(
+ cr,
+ (isHorizontalDots ? [dist, 0] : [0, dist]).concat([size, size]),
+ )
}
+ break
+ case DOT_STYLE.DOTS:
+ let radius = size / 2
- translate();
-
- cr.setSourceColor(bodyColor);
- preDraw();
- for (let i = 0; i < n; i++) {
- cr.newSubPath();
- draw(i);
+ translate = () => {
+ indicatorSize = Math.floor(
+ (areaSize - n * size - (n - 1) * spacing) / 2,
+ )
+ cr.translate.apply(
+ cr,
+ isHorizontalDots
+ ? [indicatorSize, startY]
+ : [startX, indicatorSize],
+ )
}
- cr.fill();
+ draw = (i) => {
+ dist = (2 * i + 1) * radius + i * spacing
+ cr.arc.apply(
+ cr,
+ (isHorizontalDots ? [dist, radius] : [radius, dist]).concat([
+ radius,
+ 0,
+ 2 * Math.PI,
+ ]),
+ )
+ }
+ break
+ case DOT_STYLE.SQUARES:
+ translate = () => {
+ indicatorSize = Math.floor(
+ (areaSize - n * size - (n - 1) * spacing) / 2,
+ )
+ cr.translate.apply(
+ cr,
+ isHorizontalDots
+ ? [indicatorSize, startY]
+ : [startX, indicatorSize],
+ )
+ }
+ draw = (i) => {
+ dist = i * size + i * spacing
+ cr.rectangle.apply(
+ cr,
+ (isHorizontalDots ? [dist, 0] : [0, dist]).concat([size, size]),
+ )
+ }
+ break
+ case DOT_STYLE.DASHES:
+ length = Math.floor(areaSize / 4) - spacing
+ translate = () => {
+ indicatorSize = Math.floor(
+ (areaSize - n * length - (n - 1) * spacing) / 2,
+ )
+ cr.translate.apply(
+ cr,
+ isHorizontalDots
+ ? [indicatorSize, startY]
+ : [startX, indicatorSize],
+ )
+ }
+ draw = (i) => drawDash(i, length)
+ break
+ case DOT_STYLE.SEGMENTED:
+ length = Math.ceil((areaSize - (n - 1) * spacing) / n)
+ translate = () => cr.translate(startX, startY)
+ draw = (i) => drawDash(i, length)
+ break
}
- cr.$dispose();
+ translate()
+
+ cr.setSourceColor(bodyColor)
+ preDraw()
+ for (let i = 0; i < n; i++) {
+ cr.newSubPath()
+ draw(i)
+ }
+ cr.fill()
+ }
+
+ cr.$dispose()
}
_numberOverlay() {
- // Add label for a Hot-Key visual aid
- this._numberOverlayLabel = new St.Label({ style_class: 'badge' });
- this._numberOverlayBin = new St.Bin({
- child: this._numberOverlayLabel, y: 2
- });
- this._numberOverlayLabel.add_style_class_name('number-overlay');
- this._numberOverlayOrder = -1;
- this._numberOverlayBin.hide();
+ // Add label for a Hot-Key visual aid
+ this._numberOverlayLabel = new St.Label({ style_class: 'badge' })
+ this._numberOverlayBin = new St.Bin({
+ child: this._numberOverlayLabel,
+ y: 2,
+ })
+ this._numberOverlayLabel.add_style_class_name('number-overlay')
+ this._numberOverlayOrder = -1
+ this._numberOverlayBin.hide()
- this._dtpIconContainer.add_child(this._numberOverlayBin);
+ this._dtpIconContainer.add_child(this._numberOverlayBin)
}
updateHotkeyNumberOverlay() {
- this.updateNumberOverlay(this._numberOverlayBin, true);
+ this.updateNumberOverlay(this._numberOverlayBin, true)
}
updateNumberOverlay(bin, fixedSize) {
- // We apply an overall scale factor that might come from a HiDPI monitor.
- // Clutter dimensions are in physical pixels, but CSS measures are in logical
- // pixels, so make sure to consider the scale.
- // Set the font size to something smaller than the whole icon so it is
- // still visible. The border radius is large to make the shape circular
- let [minWidth, natWidth] = this._dtpIconContainer.get_preferred_width(-1);
- let font_size = Math.round(Math.max(12, 0.3 * natWidth) / Utils.getScaleFactor());
- let size = Math.round(font_size * 1.3);
- let label = bin.child;
- let style = 'font-size: ' + font_size + 'px;' +
- 'border-radius: ' + this.icon.iconSize + 'px;' +
- 'height: ' + size + 'px;';
+ // We apply an overall scale factor that might come from a HiDPI monitor.
+ // Clutter dimensions are in physical pixels, but CSS measures are in logical
+ // pixels, so make sure to consider the scale.
+ // Set the font size to something smaller than the whole icon so it is
+ // still visible. The border radius is large to make the shape circular
+ let [minWidth, natWidth] = this._dtpIconContainer.get_preferred_width(-1)
+ let font_size = Math.round(
+ Math.max(12, 0.3 * natWidth) / Utils.getScaleFactor(),
+ )
+ let size = Math.round(font_size * 1.3)
+ let label = bin.child
+ let style =
+ 'font-size: ' +
+ font_size +
+ 'px;' +
+ 'border-radius: ' +
+ this.icon.iconSize +
+ 'px;' +
+ 'height: ' +
+ size +
+ 'px;'
- if (fixedSize || label.get_text().length == 1) {
- style += 'width: ' + size + 'px;';
- } else {
- style += 'padding: 0 2px;';
- }
+ if (fixedSize || label.get_text().length == 1) {
+ style += 'width: ' + size + 'px;'
+ } else {
+ style += 'padding: 0 2px;'
+ }
- bin.x = 2;
- label.set_style(style);
+ bin.x = 2
+ label.set_style(style)
}
setNumberOverlay(number) {
- this._numberOverlayOrder = number;
- this._numberOverlayLabel.set_text(number.toString());
+ this._numberOverlayOrder = number
+ this._numberOverlayLabel.set_text(number.toString())
}
toggleNumberOverlay(activate) {
- if (activate && this._numberOverlayOrder > -1)
- this._numberOverlayBin.show();
- else
- this._numberOverlayBin.hide();
+ if (activate && this._numberOverlayOrder > -1)
+ this._numberOverlayBin.show()
+ else this._numberOverlayBin.hide()
}
handleDragOver(source, actor, x, y, time) {
- if (source == Main.xdndHandler) {
- this._previewMenu.close(true);
- }
+ if (source == Main.xdndHandler) {
+ this._previewMenu.close(true)
+ }
- return DND.DragMotionResult.CONTINUE;
+ return DND.DragMotionResult.CONTINUE
}
getAppIconInterestingWindows(isolateMonitors) {
- return getInterestingWindows(this.app, this.dtpPanel.monitor, isolateMonitors);
+ return getInterestingWindows(
+ this.app,
+ this.dtpPanel.monitor,
+ isolateMonitors,
+ )
}
-});
-TaskbarAppIcon.prototype.scaleAndFade = TaskbarAppIcon.prototype.undoScaleAndFade = () => { };
+ },
+)
+TaskbarAppIcon.prototype.scaleAndFade =
+ TaskbarAppIcon.prototype.undoScaleAndFade = () => {}
export function minimizeWindow(app, param, monitor) {
- // Param true make all app windows minimize
- let windows = getInterestingWindows(app, monitor);
- let current_workspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace();
- for (let i = 0; i < windows.length; i++) {
- let w = windows[i];
- if (w.get_workspace() == current_workspace && w.showing_on_its_workspace()) {
- w.minimize();
- // Just minimize one window. By specification it should be the
- // focused window on the current workspace.
- if (!param)
- break;
- }
+ // Param true make all app windows minimize
+ let windows = getInterestingWindows(app, monitor)
+ let current_workspace =
+ Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace()
+ for (let i = 0; i < windows.length; i++) {
+ let w = windows[i]
+ if (
+ w.get_workspace() == current_workspace &&
+ w.showing_on_its_workspace()
+ ) {
+ w.minimize()
+ // Just minimize one window. By specification it should be the
+ // focused window on the current workspace.
+ if (!param) break
}
+ }
}
/*
@@ -1419,136 +1836,141 @@ export function minimizeWindow(app, param, monitor) {
* This activates all windows in the current workspace.
*/
export function activateAllWindows(app, monitor) {
+ // First activate first window so workspace is switched if needed,
+ // then activate all other app windows in the current workspace.
+ let windows = getInterestingWindows(app, monitor)
+ let w = windows[0]
+ Main.activateWindow(w)
+ let activeWorkspace =
+ Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace_index()
- // First activate first window so workspace is switched if needed,
- // then activate all other app windows in the current workspace.
- let windows = getInterestingWindows(app, monitor);
- let w = windows[0];
- Main.activateWindow(w);
- let activeWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace_index();
+ if (windows.length <= 0) return
- if (windows.length <= 0)
- return;
-
- for (let i = windows.length - 1; i >= 0; i--) {
- if (windows[i].get_workspace().index() == activeWorkspace) {
- Main.activateWindow(windows[i]);
- }
+ for (let i = windows.length - 1; i >= 0; i--) {
+ if (windows[i].get_workspace().index() == activeWorkspace) {
+ Main.activateWindow(windows[i])
}
+ }
}
export function activateFirstWindow(app, monitor) {
-
- let windows = getInterestingWindows(app, monitor);
- Main.activateWindow(windows[0]);
+ let windows = getInterestingWindows(app, monitor)
+ Main.activateWindow(windows[0])
}
export function cycleThroughWindows(app, reversed, shouldMinimize, monitor) {
- // Store for a little amount of time last clicked app and its windows
- // since the order changes upon window interaction
- let MEMORY_TIME = 3000;
+ // Store for a little amount of time last clicked app and its windows
+ // since the order changes upon window interaction
+ let MEMORY_TIME = 3000
- let app_windows = getInterestingWindows(app, monitor);
+ let app_windows = getInterestingWindows(app, monitor)
- if (shouldMinimize)
- app_windows.push("MINIMIZE");
+ if (shouldMinimize) app_windows.push('MINIMIZE')
- if (recentlyClickedAppLoopId > 0)
- GLib.Source.remove(recentlyClickedAppLoopId);
+ if (recentlyClickedAppLoopId > 0) GLib.Source.remove(recentlyClickedAppLoopId)
- recentlyClickedAppLoopId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
- MEMORY_TIME, resetRecentlyClickedApp);
+ recentlyClickedAppLoopId = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ MEMORY_TIME,
+ resetRecentlyClickedApp,
+ )
- // If there isn't already a list of windows for the current app,
- // or the stored list is outdated, use the current windows list.
- if (!recentlyClickedApp ||
- recentlyClickedApp.get_id() != app.get_id() ||
- recentlyClickedAppWindows.length != app_windows.length ||
- recentlyClickedAppMonitorIndex != monitor.index) {
- recentlyClickedApp = app;
- recentlyClickedAppWindows = app_windows;
- recentlyClickedAppIndex = 0;
- recentlyClickedAppMonitorIndex = monitor.index;
- }
+ // If there isn't already a list of windows for the current app,
+ // or the stored list is outdated, use the current windows list.
+ if (
+ !recentlyClickedApp ||
+ recentlyClickedApp.get_id() != app.get_id() ||
+ recentlyClickedAppWindows.length != app_windows.length ||
+ recentlyClickedAppMonitorIndex != monitor.index
+ ) {
+ recentlyClickedApp = app
+ recentlyClickedAppWindows = app_windows
+ recentlyClickedAppIndex = 0
+ recentlyClickedAppMonitorIndex = monitor.index
+ }
- if (reversed) {
- recentlyClickedAppIndex--;
- if (recentlyClickedAppIndex < 0) recentlyClickedAppIndex = recentlyClickedAppWindows.length - 1;
- } else {
- recentlyClickedAppIndex++;
- }
- let index = recentlyClickedAppIndex % recentlyClickedAppWindows.length;
+ if (reversed) {
+ recentlyClickedAppIndex--
+ if (recentlyClickedAppIndex < 0)
+ recentlyClickedAppIndex = recentlyClickedAppWindows.length - 1
+ } else {
+ recentlyClickedAppIndex++
+ }
+ let index = recentlyClickedAppIndex % recentlyClickedAppWindows.length
- if (recentlyClickedAppWindows[index] === "MINIMIZE")
- minimizeWindow(app, true, monitor);
- else
- Main.activateWindow(recentlyClickedAppWindows[index]);
+ if (recentlyClickedAppWindows[index] === 'MINIMIZE')
+ minimizeWindow(app, true, monitor)
+ else Main.activateWindow(recentlyClickedAppWindows[index])
}
export function resetRecentlyClickedApp() {
- if (recentlyClickedAppLoopId > 0)
- GLib.Source.remove(recentlyClickedAppLoopId);
+ if (recentlyClickedAppLoopId > 0) GLib.Source.remove(recentlyClickedAppLoopId)
- recentlyClickedAppLoopId = 0;
- recentlyClickedApp = null;
- recentlyClickedAppWindows = null;
- recentlyClickedAppIndex = 0;
- recentlyClickedAppMonitorIndex = null;
+ recentlyClickedAppLoopId = 0
+ recentlyClickedApp = null
+ recentlyClickedAppWindows = null
+ recentlyClickedAppIndex = 0
+ recentlyClickedAppMonitorIndex = null
- return false;
+ return false
}
export function closeAllWindows(app, monitor) {
- let windows = getInterestingWindows(app, monitor);
- for (let i = 0; i < windows.length; i++)
- windows[i].delete(global.get_current_time());
+ let windows = getInterestingWindows(app, monitor)
+ for (let i = 0; i < windows.length; i++)
+ windows[i].delete(global.get_current_time())
}
// Filter out unnecessary windows, for instance
// nautilus desktop window.
export function getInterestingWindows(app, monitor, isolateMonitors) {
- let windows = (
- app ?
- app.get_windows() :
- global.get_window_actors().map(wa => wa.get_meta_window())
- ).filter(w => !w.skip_taskbar);
+ let windows = (
+ app
+ ? app.get_windows()
+ : global.get_window_actors().map((wa) => wa.get_meta_window())
+ ).filter((w) => !w.skip_taskbar)
- // When using workspace or monitor isolation, we filter out windows
- // that are not in the current workspace or on the same monitor as the appicon
- if (SETTINGS.get_boolean('isolate-workspaces'))
- windows = windows.filter(function (w) {
- return w.get_workspace() &&
- w.get_workspace() == Utils.getCurrentWorkspace();
- });
+ // When using workspace or monitor isolation, we filter out windows
+ // that are not in the current workspace or on the same monitor as the appicon
+ if (SETTINGS.get_boolean('isolate-workspaces'))
+ windows = windows.filter(function (w) {
+ return (
+ w.get_workspace() && w.get_workspace() == Utils.getCurrentWorkspace()
+ )
+ })
- if (monitor && SETTINGS.get_boolean('multi-monitors') && (isolateMonitors || SETTINGS.get_boolean('isolate-monitors'))) {
- windows = windows.filter(function (w) {
- return w.get_monitor() == monitor.index;
- });
- }
+ if (
+ monitor &&
+ SETTINGS.get_boolean('multi-monitors') &&
+ (isolateMonitors || SETTINGS.get_boolean('isolate-monitors'))
+ ) {
+ windows = windows.filter(function (w) {
+ return w.get_monitor() == monitor.index
+ })
+ }
- return windows;
+ return windows
}
export function cssHexTocssRgba(cssHex, opacity) {
- let bigint = parseInt(cssHex.slice(1), 16);
- let r = (bigint >> 16) & 255;
- let g = (bigint >> 8) & 255;
- let b = bigint & 255;
+ let bigint = parseInt(cssHex.slice(1), 16)
+ let r = (bigint >> 16) & 255
+ let g = (bigint >> 8) & 255
+ let b = bigint & 255
- return 'rgba(' + [r, g, b].join(',') + ',' + opacity + ')';
+ return 'rgba(' + [r, g, b].join(',') + ',' + opacity + ')'
}
export function getIconPadding(monitorIndex) {
- let panelSize = PanelSettings.getPanelSize(SETTINGS, monitorIndex);
- let padding = SETTINGS.get_int('appicon-padding');
- let availSize = panelSize - Taskbar.MIN_ICON_SIZE - panelSize % 2;
+ let panelSize = PanelSettings.getPanelSize(SETTINGS, monitorIndex)
+ let padding = SETTINGS.get_int('appicon-padding')
+ let availSize = panelSize - Taskbar.MIN_ICON_SIZE - (panelSize % 2)
- if (padding * 2 > availSize) {
- padding = availSize * .5;
- }
+ if (padding * 2 > availSize) {
+ padding = availSize * 0.5
+ }
- return padding;
+ return padding
}
/**
@@ -1561,140 +1983,141 @@ export function getIconPadding(monitorIndex) {
*/
export class TaskbarSecondaryMenu extends AppMenu.AppMenu {
+ constructor(source, side) {
+ super(source, side)
+ // constructor parameter does nos work for some reason
+ this._enableFavorites = true
+ this._showSingleWindows = true
- constructor(source, side) {
- super(source, side);
- // constructor parameter does nos work for some reason
- this._enableFavorites = true;
- this._showSingleWindows = true;
-
- // Remove "Show Details" menu item
- if (!SETTINGS.get_boolean('secondarymenu-contains-showdetails')) {
- let existingMenuItems = this._getMenuItems();
- for (let i = 0; i < existingMenuItems.length; i++) {
- let item = existingMenuItems[i];
- if (item !== undefined && item.label !== undefined) {
- if (item.label.text == "Show Details") {
- this.box.remove_child(item.actor);
- }
- }
- }
+ // Remove "Show Details" menu item
+ if (!SETTINGS.get_boolean('secondarymenu-contains-showdetails')) {
+ let existingMenuItems = this._getMenuItems()
+ for (let i = 0; i < existingMenuItems.length; i++) {
+ let item = existingMenuItems[i]
+ if (item !== undefined && item.label !== undefined) {
+ if (item.label.text == 'Show Details') {
+ this.box.remove_child(item.actor)
+ }
}
-
- // replace quit item
- delete this._quitItem;
- this._quitItem = this.addAction(_('Quit'), () => this._quitFromTaskbar());
+ }
}
- updateQuitText() {
- let count = this.sourceActor.window ? 1 :
- getInterestingWindows(this._app, this.sourceActor.dtpPanel.monitor).length;
+ // replace quit item
+ delete this._quitItem
+ this._quitItem = this.addAction(_('Quit'), () => this._quitFromTaskbar())
+ }
- if (count > 0) {
- let quitFromTaskbarMenuText = "";
- if (count == 1)
- quitFromTaskbarMenuText = _("Quit");
- else
- quitFromTaskbarMenuText = ngettext('Quit %d Window', 'Quit %d Windows', count).format(count);
+ updateQuitText() {
+ let count = this.sourceActor.window
+ ? 1
+ : getInterestingWindows(this._app, this.sourceActor.dtpPanel.monitor)
+ .length
- this._quitItem.label.set_text(quitFromTaskbarMenuText);
- }
+ if (count > 0) {
+ let quitFromTaskbarMenuText = ''
+ if (count == 1) quitFromTaskbarMenuText = _('Quit')
+ else
+ quitFromTaskbarMenuText = ngettext(
+ 'Quit %d Window',
+ 'Quit %d Windows',
+ count,
+ ).format(count)
+
+ this._quitItem.label.set_text(quitFromTaskbarMenuText)
}
+ }
- _quitFromTaskbar() {
- let time = global.get_current_time()
- let windows =
- this.sourceActor.window ? // ungrouped applications
- [this.sourceActor.window] :
- getInterestingWindows(this._app, this.sourceActor.dtpPanel.monitor)
+ _quitFromTaskbar() {
+ let time = global.get_current_time()
+ let windows = this.sourceActor.window // ungrouped applications
+ ? [this.sourceActor.window]
+ : getInterestingWindows(this._app, this.sourceActor.dtpPanel.monitor)
- if (windows.length == this._app.get_windows().length)
- this._app.request_quit()
+ if (windows.length == this._app.get_windows().length)
+ this._app.request_quit()
- GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
- windows.forEach((w) => !!w.get_compositor_private() && w.delete(time++));
+ GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
+ windows.forEach((w) => !!w.get_compositor_private() && w.delete(time++))
- return GLib.SOURCE_REMOVE;
- });
- }
+ return GLib.SOURCE_REMOVE
+ })
+ }
- setApp(app) {
- super.setApp(app);
-
- this._detailsItem.visible = !app.hideDetails
- }
+ setApp(app) {
+ super.setApp(app)
+
+ this._detailsItem.visible = !app.hideDetails
+ }
}
/**
* This function is used for extendDashItemContainer
*/
export function ItemShowLabel() {
- if (!this._labelText)
- return;
+ if (!this._labelText) return
- this.label.set_text(this._labelText);
- this.label.opacity = 0;
- this.label.show();
+ this.label.set_text(this._labelText)
+ this.label.opacity = 0
+ this.label.show()
- let [stageX, stageY] = this.get_transformed_position();
- let node = this.label.get_theme_node();
+ let [stageX, stageY] = this.get_transformed_position()
+ let node = this.label.get_theme_node()
- let itemWidth = this.allocation.x2 - this.allocation.x1;
- let itemHeight = this.allocation.y2 - this.allocation.y1;
+ let itemWidth = this.allocation.x2 - this.allocation.x1
+ let itemHeight = this.allocation.y2 - this.allocation.y1
- let labelWidth = this.label.get_width();
- let labelHeight = this.label.get_height();
+ let labelWidth = this.label.get_width()
+ let labelHeight = this.label.get_height()
- let position = this._dtpPanel.getPosition();
- let labelOffset = node.get_length('-x-offset');
+ let position = this._dtpPanel.getPosition()
+ let labelOffset = node.get_length('-x-offset')
- // From TaskbarItemContainer
- if (this._getIconAnimationOffset)
- labelOffset += this._getIconAnimationOffset();
+ // From TaskbarItemContainer
+ if (this._getIconAnimationOffset)
+ labelOffset += this._getIconAnimationOffset()
- let xOffset = Math.floor((itemWidth - labelWidth) / 2);
- let x = stageX + xOffset
- let y = stageY + (itemHeight - labelHeight) * .5;
+ let xOffset = Math.floor((itemWidth - labelWidth) / 2)
+ let x = stageX + xOffset
+ let y = stageY + (itemHeight - labelHeight) * 0.5
- switch (position) {
- case St.Side.TOP:
- y = stageY + labelOffset + itemHeight;
- break;
- case St.Side.BOTTOM:
- y = stageY - labelHeight - labelOffset;
- break;
- case St.Side.LEFT:
- x = stageX + labelOffset + itemWidth;
- break;
- case St.Side.RIGHT:
- x = stageX - labelWidth - labelOffset;
- break;
- }
+ switch (position) {
+ case St.Side.TOP:
+ y = stageY + labelOffset + itemHeight
+ break
+ case St.Side.BOTTOM:
+ y = stageY - labelHeight - labelOffset
+ break
+ case St.Side.LEFT:
+ x = stageX + labelOffset + itemWidth
+ break
+ case St.Side.RIGHT:
+ x = stageX - labelWidth - labelOffset
+ break
+ }
- // keep the label inside the screen border
- // Only needed for the x coordinate.
+ // keep the label inside the screen border
+ // Only needed for the x coordinate.
- // Leave a few pixel gap
- let gap = LABEL_GAP;
- let monitor = Main.layoutManager.findMonitorForActor(this);
- if (x - monitor.x < gap)
- x += monitor.x - x + labelOffset;
- else if (x + labelWidth > monitor.x + monitor.width - gap)
- x -= x + labelWidth - (monitor.x + monitor.width) + gap;
+ // Leave a few pixel gap
+ let gap = LABEL_GAP
+ let monitor = Main.layoutManager.findMonitorForActor(this)
+ if (x - monitor.x < gap) x += monitor.x - x + labelOffset
+ else if (x + labelWidth > monitor.x + monitor.width - gap)
+ x -= x + labelWidth - (monitor.x + monitor.width) + gap
- this.label.set_position(Math.round(x), Math.round(y));
+ this.label.set_position(Math.round(x), Math.round(y))
- let duration = Dash.DASH_ITEM_LABEL_SHOW_TIME;
+ let duration = Dash.DASH_ITEM_LABEL_SHOW_TIME
- if (duration > 1) {
- duration /= 1000;
- }
+ if (duration > 1) {
+ duration /= 1000
+ }
- Utils.animate(this.label, {
- opacity: 255,
- time: duration,
- transition: 'easeOutQuad',
- });
+ Utils.animate(this.label, {
+ opacity: 255,
+ time: duration,
+ transition: 'easeOutQuad',
+ })
}
/**
@@ -1710,304 +2133,340 @@ export function ItemShowLabel() {
*
*/
export const ShowAppsIconWrapper = class extends EventEmitter {
+ constructor(dtpPanel) {
+ super()
- constructor(dtpPanel) {
- super();
+ this.realShowAppsIcon = new Dash.ShowAppsIcon()
- this.realShowAppsIcon = new Dash.ShowAppsIcon();
-
- /* the variable equivalent to toggleButton has a different name in the appIcon class
+ /* the variable equivalent to toggleButton has a different name in the appIcon class
(actor): duplicate reference to easily reuse appIcon methods */
- this.actor = this.realShowAppsIcon.toggleButton;
- this.realShowAppsIcon.show(false);
+ this.actor = this.realShowAppsIcon.toggleButton
+ this.realShowAppsIcon.show(false)
- // Re-use appIcon methods
- this._removeMenuTimeout = AppDisplay.AppIcon.prototype._removeMenuTimeout;
- this._setPopupTimeout = AppDisplay.AppIcon.prototype._setPopupTimeout;
- this._onKeyboardPopupMenu = AppDisplay.AppIcon.prototype._onKeyboardPopupMenu;
+ // Re-use appIcon methods
+ this._removeMenuTimeout = AppDisplay.AppIcon.prototype._removeMenuTimeout
+ this._setPopupTimeout = AppDisplay.AppIcon.prototype._setPopupTimeout
+ this._onKeyboardPopupMenu =
+ AppDisplay.AppIcon.prototype._onKeyboardPopupMenu
- // No action on clicked (showing of the appsview is controlled elsewhere)
- this._onClicked = (actor, button) => this._removeMenuTimeout();
+ // No action on clicked (showing of the appsview is controlled elsewhere)
+ this._onClicked = (actor, button) => this._removeMenuTimeout()
- this.actor.connect('leave-event', this._onLeaveEvent.bind(this));
- this.actor.connect('button-press-event', this._onButtonPress.bind(this));
- this.actor.connect('touch-event', this._onTouchEvent.bind(this));
- this.actor.connect('clicked', this._onClicked.bind(this));
- this.actor.connect('popup-menu', this._onKeyboardPopupMenu.bind(this));
+ this.actor.connect('leave-event', this._onLeaveEvent.bind(this))
+ this.actor.connect('button-press-event', this._onButtonPress.bind(this))
+ this.actor.connect('touch-event', this._onTouchEvent.bind(this))
+ this.actor.connect('clicked', this._onClicked.bind(this))
+ this.actor.connect('popup-menu', this._onKeyboardPopupMenu.bind(this))
- this._menu = null;
- this._menuManager = new PopupMenu.PopupMenuManager(this.actor);
- this._menuTimeoutId = 0;
+ this._menu = null
+ this._menuManager = new PopupMenu.PopupMenuManager(this.actor)
+ this._menuTimeoutId = 0
- this.realShowAppsIcon._dtpPanel = dtpPanel;
- Taskbar.extendDashItemContainer(this.realShowAppsIcon);
+ this.realShowAppsIcon._dtpPanel = dtpPanel
+ Taskbar.extendDashItemContainer(this.realShowAppsIcon)
- let customIconPath = SETTINGS.get_string('show-apps-icon-file');
+ let customIconPath = SETTINGS.get_string('show-apps-icon-file')
- this.realShowAppsIcon.icon.createIcon = function (size) {
- this._iconActor = new St.Icon({
- icon_name: 'view-app-grid-symbolic',
- icon_size: size,
- style_class: 'show-apps-icon',
- track_hover: true
- });
+ this.realShowAppsIcon.icon.createIcon = function (size) {
+ this._iconActor = new St.Icon({
+ icon_name: 'view-app-grid-symbolic',
+ icon_size: size,
+ style_class: 'show-apps-icon',
+ track_hover: true,
+ })
- if (customIconPath) {
- this._iconActor.gicon = new Gio.FileIcon({ file: Gio.File.new_for_path(customIconPath) });
- }
+ if (customIconPath) {
+ this._iconActor.gicon = new Gio.FileIcon({
+ file: Gio.File.new_for_path(customIconPath),
+ })
+ }
- return this._iconActor;
- };
-
- this._changedShowAppsIconId = SETTINGS.connect('changed::show-apps-icon-file', () => {
- customIconPath = SETTINGS.get_string('show-apps-icon-file');
- this.realShowAppsIcon.icon._createIconTexture(this.realShowAppsIcon.icon.iconSize);
- });
-
- this._changedAppIconPaddingId = SETTINGS.connect('changed::appicon-padding', () => this.setShowAppsPadding());
- this._changedAppIconSidePaddingId = SETTINGS.connect('changed::show-apps-icon-side-padding', () => this.setShowAppsPadding());
-
- this.setShowAppsPadding();
+ return this._iconActor
}
- _onButtonPress(_actor, event) {
- let button = event.get_button();
- if (button == 1) {
- this._setPopupTimeout();
- } else if (button == 3) {
- this.popupMenu();
- return Clutter.EVENT_STOP;
- }
- return Clutter.EVENT_PROPAGATE;
+ this._changedShowAppsIconId = SETTINGS.connect(
+ 'changed::show-apps-icon-file',
+ () => {
+ customIconPath = SETTINGS.get_string('show-apps-icon-file')
+ this.realShowAppsIcon.icon._createIconTexture(
+ this.realShowAppsIcon.icon.iconSize,
+ )
+ },
+ )
+
+ this._changedAppIconPaddingId = SETTINGS.connect(
+ 'changed::appicon-padding',
+ () => this.setShowAppsPadding(),
+ )
+ this._changedAppIconSidePaddingId = SETTINGS.connect(
+ 'changed::show-apps-icon-side-padding',
+ () => this.setShowAppsPadding(),
+ )
+
+ this.setShowAppsPadding()
+ }
+
+ _onButtonPress(_actor, event) {
+ let button = event.get_button()
+ if (button == 1) {
+ this._setPopupTimeout()
+ } else if (button == 3) {
+ this.popupMenu()
+ return Clutter.EVENT_STOP
}
+ return Clutter.EVENT_PROPAGATE
+ }
- _onLeaveEvent(_actor, _event) {
- this.actor.fake_release();
- this._removeMenuTimeout();
+ _onLeaveEvent(_actor, _event) {
+ this.actor.fake_release()
+ this._removeMenuTimeout()
+ }
+
+ _onTouchEvent(actor, event) {
+ if (event.type() == Clutter.EventType.TOUCH_BEGIN) this._setPopupTimeout()
+
+ return Clutter.EVENT_PROPAGATE
+ }
+
+ _onMenuPoppedDown() {
+ this._menu.sourceActor = this.actor
+ this.actor.sync_hover()
+ this.emit('menu-state-changed', false)
+ }
+
+ setShowAppsPadding() {
+ let padding = getIconPadding(this.realShowAppsIcon._dtpPanel.monitor.index)
+ let sidePadding = SETTINGS.get_int('show-apps-icon-side-padding')
+ let isVertical = this.realShowAppsIcon._dtpPanel.checkIfVertical()
+
+ this.actor.set_style(
+ 'padding:' +
+ (padding + (isVertical ? sidePadding : 0)) +
+ 'px ' +
+ (padding + (isVertical ? 0 : sidePadding)) +
+ 'px;',
+ )
+ }
+
+ createMenu() {
+ if (!this._menu) {
+ this._menu = new MyShowAppsIconMenu(
+ this.realShowAppsIcon,
+ this.realShowAppsIcon._dtpPanel,
+ )
+ this._menu.connect('open-state-changed', (menu, isPoppedUp) => {
+ if (!isPoppedUp) this._onMenuPoppedDown()
+ })
+ let id = Main.overview.connect('hiding', () => {
+ this._menu.close()
+ })
+ this._menu.actor.connect('destroy', () => {
+ Main.overview.disconnect(id)
+ })
+
+ // We want to keep the item hovered while the menu is up
+ this._menu.blockSourceEvents = true
+
+ Main.uiGroup.add_child(this._menu.actor)
+ this._menuManager.addMenu(this._menu)
}
+ }
- _onTouchEvent(actor, event) {
- if (event.type() == Clutter.EventType.TOUCH_BEGIN)
- this._setPopupTimeout();
+ popupMenu(sourceActor = null) {
+ this._removeMenuTimeout()
+ this.actor.fake_release()
+ this.createMenu()
- return Clutter.EVENT_PROPAGATE;
- }
+ this._menu.updateItems(
+ sourceActor == null ? this.realShowAppsIcon : sourceActor,
+ )
- _onMenuPoppedDown() {
- this._menu.sourceActor = this.actor;
- this.actor.sync_hover();
- this.emit('menu-state-changed', false);
- }
+ this.actor.set_hover(true)
+ this._menu.open(BoxPointer.PopupAnimation.FULL)
+ this._menuManager.ignoreRelease()
+ this.emit('sync-tooltip')
- setShowAppsPadding() {
- let padding = getIconPadding(this.realShowAppsIcon._dtpPanel.monitor.index);
- let sidePadding = SETTINGS.get_int('show-apps-icon-side-padding');
- let isVertical = this.realShowAppsIcon._dtpPanel.checkIfVertical();
+ return false
+ }
- this.actor.set_style('padding:' + (padding + (isVertical ? sidePadding : 0)) + 'px ' + (padding + (isVertical ? 0 : sidePadding)) + 'px;');
- }
+ shouldShowTooltip() {
+ return (
+ SETTINGS.get_boolean('show-tooltip') &&
+ this.actor.hover &&
+ (!this._menu || !this._menu.isOpen)
+ )
+ }
- createMenu() {
- if (!this._menu) {
- this._menu = new MyShowAppsIconMenu(this.realShowAppsIcon, this.realShowAppsIcon._dtpPanel);
- this._menu.connect('open-state-changed', (menu, isPoppedUp) => {
- if (!isPoppedUp)
- this._onMenuPoppedDown();
- });
- let id = Main.overview.connect('hiding', () => {
- this._menu.close();
- });
- this._menu.actor.connect('destroy', () => {
- Main.overview.disconnect(id);
- });
+ destroy() {
+ SETTINGS.disconnect(this._changedShowAppsIconId)
+ SETTINGS.disconnect(this._changedAppIconSidePaddingId)
+ SETTINGS.disconnect(this._changedAppIconPaddingId)
- // We want to keep the item hovered while the menu is up
- this._menu.blockSourceEvents = true;
-
- Main.uiGroup.add_child(this._menu.actor);
- this._menuManager.addMenu(this._menu);
- }
- }
-
- popupMenu(sourceActor = null) {
- this._removeMenuTimeout();
- this.actor.fake_release();
- this.createMenu();
-
- this._menu.updateItems(sourceActor == null ? this.realShowAppsIcon : sourceActor);
-
- this.actor.set_hover(true);
- this._menu.open(BoxPointer.PopupAnimation.FULL);
- this._menuManager.ignoreRelease();
- this.emit('sync-tooltip');
-
- return false;
- }
-
- shouldShowTooltip() {
- return SETTINGS.get_boolean('show-tooltip') &&
- (this.actor.hover && (!this._menu || !this._menu.isOpen));
- }
-
- destroy() {
- SETTINGS.disconnect(this._changedShowAppsIconId);
- SETTINGS.disconnect(this._changedAppIconSidePaddingId);
- SETTINGS.disconnect(this._changedAppIconPaddingId);
-
- this.realShowAppsIcon.destroy();
- }
-};
+ this.realShowAppsIcon.destroy()
+ }
+}
/**
* A menu for the showAppsIcon
*/
export const MyShowAppsIconMenu = class extends PopupMenu.PopupMenu {
+ constructor(actor, dtpPanel) {
+ super(actor, 0, dtpPanel.getPosition())
- constructor(actor, dtpPanel) {
- super(actor, 0, dtpPanel.getPosition());
+ this._dtpPanel = dtpPanel
- this._dtpPanel = dtpPanel;
+ this.updateItems(actor)
+ }
- this.updateItems(actor);
+ updateItems(sourceActor) {
+ this.sourceActor = sourceActor
+
+ this.removeAll()
+
+ if (this.sourceActor != Main.layoutManager.dummyCursor) {
+ this._appendItem({
+ title: _('Power options'),
+ cmd: ['gnome-control-center', 'power'],
+ })
+
+ this._appendItem({
+ title: _('Event logs'),
+ cmd: ['gnome-logs'],
+ })
+
+ this._appendItem({
+ title: _('System'),
+ cmd: ['gnome-control-center', 'info-overview'],
+ })
+
+ this._appendItem({
+ title: _('Device Management'),
+ cmd: ['gnome-control-center', 'display'],
+ })
+
+ this._appendItem({
+ title: _('Disk Management'),
+ cmd: ['gnome-disks'],
+ })
+
+ this._appendList(
+ SETTINGS.get_strv('show-apps-button-context-menu-commands'),
+ SETTINGS.get_strv('show-apps-button-context-menu-titles'),
+ )
+
+ this._appendSeparator()
}
- updateItems(sourceActor) {
- this.sourceActor = sourceActor;
+ this._appendItem({
+ title: _('Terminal'),
+ cmd: [TERMINALSETTINGS.get_string('exec')],
+ })
- this.removeAll();
+ this._appendItem({
+ title: _('System monitor'),
+ cmd: ['gnome-system-monitor'],
+ })
- if (this.sourceActor != Main.layoutManager.dummyCursor) {
- this._appendItem({
- title: _('Power options'),
- cmd: ['gnome-control-center', 'power']
- });
+ this._appendItem({
+ title: _('Files'),
+ cmd: ['nautilus'],
+ })
- this._appendItem({
- title: _('Event logs'),
- cmd: ['gnome-logs']
- });
+ this._appendItem({
+ title: _('Extensions'),
+ cmd: ['gnome-extensions-app'],
+ })
- this._appendItem({
- title: _('System'),
- cmd: ['gnome-control-center', 'info-overview']
- });
+ this._appendItem({
+ title: _('Settings'),
+ cmd: ['gnome-control-center'],
+ })
- this._appendItem({
- title: _('Device Management'),
- cmd: ['gnome-control-center', 'display']
- });
+ this._appendList(
+ SETTINGS.get_strv('panel-context-menu-commands'),
+ SETTINGS.get_strv('panel-context-menu-titles'),
+ )
- this._appendItem({
- title: _('Disk Management'),
- cmd: ['gnome-disks']
- });
+ this._appendSeparator()
- this._appendList(
- SETTINGS.get_strv('show-apps-button-context-menu-commands'),
- SETTINGS.get_strv('show-apps-button-context-menu-titles')
- )
+ let lockTaskbarMenuItem = this._appendMenuItem(
+ SETTINGS.get_boolean('taskbar-locked')
+ ? _('Unlock taskbar')
+ : _('Lock taskbar'),
+ )
+ lockTaskbarMenuItem.connect('activate', () => {
+ SETTINGS.set_boolean(
+ 'taskbar-locked',
+ !SETTINGS.get_boolean('taskbar-locked'),
+ )
+ })
- this._appendSeparator();
- }
+ let settingsMenuItem = this._appendMenuItem(_('Dash to Panel Settings'))
+ settingsMenuItem.connect('activate', () => DTP_EXTENSION.openPreferences())
- this._appendItem({
- title: _('Terminal'),
- cmd: [TERMINALSETTINGS.get_string('exec')]
- });
+ if (this.sourceActor == Main.layoutManager.dummyCursor) {
+ this._appendSeparator()
+ let item = this._appendMenuItem(
+ this._dtpPanel._restoreWindowList
+ ? _('Restore Windows')
+ : _('Show Desktop'),
+ )
+ item.connect(
+ 'activate',
+ this._dtpPanel._onShowDesktopButtonPress.bind(this._dtpPanel),
+ )
+ }
+ }
- this._appendItem({
- title: _('System monitor'),
- cmd: ['gnome-system-monitor']
- });
+ // Only add menu entries for commands that exist in path
+ _appendItem(info) {
+ if (GLib.find_program_in_path(info.cmd[0])) {
+ let item = this._appendMenuItem(_(info.title))
- this._appendItem({
- title: _('Files'),
- cmd: ['nautilus']
- });
-
- this._appendItem({
- title: _('Extensions'),
- cmd: ['gnome-extensions-app']
- });
-
- this._appendItem({
- title: _('Settings'),
- cmd: ['gnome-control-center']
- });
-
- this._appendList(
- SETTINGS.get_strv('panel-context-menu-commands'),
- SETTINGS.get_strv('panel-context-menu-titles')
- )
-
- this._appendSeparator();
-
- let lockTaskbarMenuItem = this._appendMenuItem(SETTINGS.get_boolean('taskbar-locked') ? _('Unlock taskbar') : _('Lock taskbar'));
- lockTaskbarMenuItem.connect('activate', () => {
- SETTINGS.set_boolean('taskbar-locked', !SETTINGS.get_boolean('taskbar-locked'));
- });
-
- let settingsMenuItem = this._appendMenuItem(_('Dash to Panel Settings'));
- settingsMenuItem.connect('activate', () => DTP_EXTENSION.openPreferences())
-
- if (this.sourceActor == Main.layoutManager.dummyCursor) {
- this._appendSeparator();
- let item = this._appendMenuItem(this._dtpPanel._restoreWindowList ? _('Restore Windows') : _('Show Desktop'));
- item.connect('activate', this._dtpPanel._onShowDesktopButtonPress.bind(this._dtpPanel));
- }
+ item.connect('activate', function () {
+ print('activated: ' + info.title)
+ Util.spawn(info.cmd)
+ })
+ return item
}
+ return null
+ }
- // Only add menu entries for commands that exist in path
- _appendItem(info) {
- if (GLib.find_program_in_path(info.cmd[0])) {
- let item = this._appendMenuItem(_(info.title));
-
- item.connect('activate', function () {
- print("activated: " + info.title);
- Util.spawn(info.cmd);
- });
- return item;
- }
-
- return null;
+ _appendList(commandList, titleList) {
+ if (commandList.length != titleList.length) {
+ return
}
- _appendList(commandList, titleList) {
- if (commandList.length != titleList.length) {
- return;
- }
-
- for (let entry = 0; entry < commandList.length; entry++) {
- this._appendItem({
- title: titleList[entry],
- cmd: commandList[entry].split(' ')
- });
- }
+ for (let entry = 0; entry < commandList.length; entry++) {
+ this._appendItem({
+ title: titleList[entry],
+ cmd: commandList[entry].split(' '),
+ })
}
+ }
- _appendSeparator() {
- let separator = new PopupMenu.PopupSeparatorMenuItem();
- this.addMenuItem(separator);
- }
-
- _appendMenuItem(labelText) {
- // FIXME: app-well-menu-item style
- let item = new PopupMenu.PopupMenuItem(labelText);
- this.addMenuItem(item);
- return item;
- }
-};
+ _appendSeparator() {
+ let separator = new PopupMenu.PopupSeparatorMenuItem()
+ this.addMenuItem(separator)
+ }
+ _appendMenuItem(labelText) {
+ // FIXME: app-well-menu-item style
+ let item = new PopupMenu.PopupMenuItem(labelText)
+ this.addMenuItem(item)
+ return item
+ }
+}
export const getIconContainerStyle = function (isVertical) {
- let style = 'padding: ';
+ let style = 'padding: '
- if (SETTINGS.get_boolean('group-apps')) {
- style += (isVertical ? '0;' : '0 ' + DEFAULT_PADDING_SIZE + 'px;');
- } else {
- style += (isVertical ? '' : '0 ') + DEFAULT_PADDING_SIZE + 'px;';
- }
+ if (SETTINGS.get_boolean('group-apps')) {
+ style += isVertical ? '0;' : '0 ' + DEFAULT_PADDING_SIZE + 'px;'
+ } else {
+ style += (isVertical ? '' : '0 ') + DEFAULT_PADDING_SIZE + 'px;'
+ }
- return style;
+ return style
}
diff --git a/desktopIconsIntegration.js b/desktopIconsIntegration.js
index e403516..669fb6d 100644
--- a/desktopIconsIntegration.js
+++ b/desktopIconsIntegration.js
@@ -55,111 +55,117 @@
*
*******************************************************************************/
-import GLib from 'gi://GLib';
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
-import * as ExtensionUtils from 'resource:///org/gnome/shell/misc/extensionUtils.js';
-import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';
+import GLib from 'gi://GLib'
+import * as Main from 'resource:///org/gnome/shell/ui/main.js'
+import * as ExtensionUtils from 'resource:///org/gnome/shell/misc/extensionUtils.js'
+import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'
-const IDENTIFIER_UUID = "130cbc66-235c-4bd6-8571-98d2d8bba5e2";
+const IDENTIFIER_UUID = '130cbc66-235c-4bd6-8571-98d2d8bba5e2'
export class DesktopIconsUsableAreaClass {
- _checkIfExtensionIsEnabled(extension) {
- return (extension?.state === ExtensionUtils.ExtensionState.ENABLED) ||
- (extension?.state === ExtensionUtils.ExtensionState.ACTIVE);
- }
+ _checkIfExtensionIsEnabled(extension) {
+ return (
+ extension?.state === ExtensionUtils.ExtensionState.ENABLED ||
+ extension?.state === ExtensionUtils.ExtensionState.ACTIVE
+ )
+ }
- constructor() {
- const Me = Extension.lookupByURL(import.meta.url);
- this._UUID = Me.uuid;
- this._extensionManager = Main.extensionManager;
- this._timedMarginsID = 0;
- this._margins = {};
- this._emID = this._extensionManager.connect('extension-state-changed', (_obj, extension) => {
- if (!extension)
- return;
+ constructor() {
+ const Me = Extension.lookupByURL(import.meta.url)
+ this._UUID = Me.uuid
+ this._extensionManager = Main.extensionManager
+ this._timedMarginsID = 0
+ this._margins = {}
+ this._emID = this._extensionManager.connect(
+ 'extension-state-changed',
+ (_obj, extension) => {
+ if (!extension) return
- // If an extension is being enabled and lacks the DesktopIconsUsableArea object, we can avoid launching a refresh
- if (this._checkIfExtensionIsEnabled(extension)) {
- this._sendMarginsToExtension(extension);
- return;
- }
- // if the extension is being disabled, we must do a full refresh, because if there were other extensions originally
- // loaded after that extension, those extensions will be disabled and enabled again without notification
- this._changedMargins();
- });
- }
-
- /**
- * Sets or updates the top, bottom, left and right margins for a
- * monitor. Values are measured from the monitor border (and NOT from
- * the workspace border).
- *
- * @param {int} monitor Monitor number to which set the margins.
- * A negative value means "the primary monitor".
- * @param {int} top Top margin in pixels
- * @param {int} bottom Bottom margin in pixels
- * @param {int} left Left margin in pixels
- * @param {int} right Right margin in pixels
- */
- setMargins(monitor, top, bottom, left, right) {
- this._margins[monitor] = {
- 'top': top,
- 'bottom': bottom,
- 'left': left,
- 'right': right
- };
- this._changedMargins();
- }
-
- /**
- * Clears the current margins. Must be called before configuring the monitors
- * margins with setMargins().
- */
- resetMargins() {
- this._margins = {};
- this._changedMargins();
- }
-
- /**
- * Disconnects all the signals and removes the margins.
- */
- destroy() {
- if (this._emID) {
- this._extensionManager.disconnect(this._emID);
- this._emID = 0;
+ // If an extension is being enabled and lacks the DesktopIconsUsableArea object, we can avoid launching a refresh
+ if (this._checkIfExtensionIsEnabled(extension)) {
+ this._sendMarginsToExtension(extension)
+ return
}
- if (this._timedMarginsID) {
- GLib.source_remove(this._timedMarginsID);
- this._timedMarginsID = 0;
- }
- this._margins = null;
- this._changedMargins();
- }
+ // if the extension is being disabled, we must do a full refresh, because if there were other extensions originally
+ // loaded after that extension, those extensions will be disabled and enabled again without notification
+ this._changedMargins()
+ },
+ )
+ }
- _changedMargins() {
- if (this._timedMarginsID) {
- GLib.source_remove(this._timedMarginsID);
- }
- this._timedMarginsID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, ()=> {
- this._sendMarginsToAll();
- this._timedMarginsID = 0;
- return GLib.SOURCE_REMOVE;
- });
+ /**
+ * Sets or updates the top, bottom, left and right margins for a
+ * monitor. Values are measured from the monitor border (and NOT from
+ * the workspace border).
+ *
+ * @param {int} monitor Monitor number to which set the margins.
+ * A negative value means "the primary monitor".
+ * @param {int} top Top margin in pixels
+ * @param {int} bottom Bottom margin in pixels
+ * @param {int} left Left margin in pixels
+ * @param {int} right Right margin in pixels
+ */
+ setMargins(monitor, top, bottom, left, right) {
+ this._margins[monitor] = {
+ top: top,
+ bottom: bottom,
+ left: left,
+ right: right,
}
+ this._changedMargins()
+ }
- _sendMarginsToAll() {
- this._extensionManager.getUuids().forEach(uuid =>
- this._sendMarginsToExtension(this._extensionManager.lookup(uuid)));
+ /**
+ * Clears the current margins. Must be called before configuring the monitors
+ * margins with setMargins().
+ */
+ resetMargins() {
+ this._margins = {}
+ this._changedMargins()
+ }
+
+ /**
+ * Disconnects all the signals and removes the margins.
+ */
+ destroy() {
+ if (this._emID) {
+ this._extensionManager.disconnect(this._emID)
+ this._emID = 0
}
-
- _sendMarginsToExtension(extension) {
- // check that the extension is an extension that has the logic to accept
- // working margins
- if (!this._checkIfExtensionIsEnabled(extension))
- return;
-
- const usableArea = extension?.stateObj?.DesktopIconsUsableArea;
- if (usableArea?.uuid === IDENTIFIER_UUID)
- usableArea.setMarginsForExtension(this._UUID, this._margins);
+ if (this._timedMarginsID) {
+ GLib.source_remove(this._timedMarginsID)
+ this._timedMarginsID = 0
}
+ this._margins = null
+ this._changedMargins()
+ }
+
+ _changedMargins() {
+ if (this._timedMarginsID) {
+ GLib.source_remove(this._timedMarginsID)
+ }
+ this._timedMarginsID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, () => {
+ this._sendMarginsToAll()
+ this._timedMarginsID = 0
+ return GLib.SOURCE_REMOVE
+ })
+ }
+
+ _sendMarginsToAll() {
+ this._extensionManager
+ .getUuids()
+ .forEach((uuid) =>
+ this._sendMarginsToExtension(this._extensionManager.lookup(uuid)),
+ )
+ }
+
+ _sendMarginsToExtension(extension) {
+ // check that the extension is an extension that has the logic to accept
+ // working margins
+ if (!this._checkIfExtensionIsEnabled(extension)) return
+
+ const usableArea = extension?.stateObj?.DesktopIconsUsableArea
+ if (usableArea?.uuid === IDENTIFIER_UUID)
+ usableArea.setMarginsForExtension(this._UUID, this._margins)
+ }
}
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 0000000..5ac7b1d
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,9 @@
+import globals from 'globals'
+import pluginJs from '@eslint/js'
+import eslintConfigPrettier from 'eslint-config-prettier'
+
+export default [
+ { languageOptions: { globals: globals.node } },
+ pluginJs.configs.recommended,
+ eslintConfigPrettier,
+]
diff --git a/extension.js b/extension.js
index 13928dd..ab3faee 100644
--- a/extension.js
+++ b/extension.js
@@ -17,114 +17,129 @@
*
*/
+import Gio from 'gi://Gio'
-import Gio from 'gi://Gio';
+import * as Main from 'resource:///org/gnome/shell/ui/main.js'
+import { EventEmitter } from 'resource:///org/gnome/shell/misc/signals.js'
+import {
+ Extension,
+ gettext as _,
+} from 'resource:///org/gnome/shell/extensions/extension.js'
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
-import {EventEmitter} from 'resource:///org/gnome/shell/misc/signals.js';
-import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js';
+import * as PanelManager from './panelManager.js'
+import * as AppIcons from './appIcons.js'
-import * as PanelManager from './panelManager.js';
-import * as AppIcons from './appIcons.js';
+const UBUNTU_DOCK_UUID = 'ubuntu-dock@ubuntu.com'
+let panelManager
+let extensionChangedHandler
+let startupCompleteHandler
+let extensionSystem = Main.extensionManager
-const UBUNTU_DOCK_UUID = 'ubuntu-dock@ubuntu.com';
-
-let panelManager;
-let extensionChangedHandler;
-let startupCompleteHandler;
-let extensionSystem = Main.extensionManager;
-
-export let DTP_EXTENSION = null;
-export let SETTINGS = null;
-export let DESKTOPSETTINGS = null;
-export let TERMINALSETTINGS = null;
-export let PERSISTENTSTORAGE = null;
-export let EXTENSION_UUID = null;
-export let EXTENSION_PATH = null;
+export let DTP_EXTENSION = null
+export let SETTINGS = null
+export let DESKTOPSETTINGS = null
+export let TERMINALSETTINGS = null
+export let PERSISTENTSTORAGE = null
+export let EXTENSION_UUID = null
+export let EXTENSION_PATH = null
export default class DashToPanelExtension extends Extension {
- constructor(metadata) {
- super(metadata);
+ constructor(metadata) {
+ super(metadata)
- this._realHasOverview = Main.sessionMode.hasOverview;
-
- //create an object that persists until gnome-shell is restarted, even if the extension is disabled
- PERSISTENTSTORAGE = {};
- }
+ this._realHasOverview = Main.sessionMode.hasOverview
- enable() {
- DTP_EXTENSION = this;
+ //create an object that persists until gnome-shell is restarted, even if the extension is disabled
+ PERSISTENTSTORAGE = {}
+ }
- // The Ubuntu Dock extension might get enabled after this extension
- extensionChangedHandler = extensionSystem.connect('extension-state-changed', (data, extension) => {
- if (extension.uuid === UBUNTU_DOCK_UUID && extension.state === 1) {
- _enable(this);
- }
- });
+ enable() {
+ DTP_EXTENSION = this
- //create a global object that can emit signals and conveniently expose functionalities to other extensions
- global.dashToPanel = new EventEmitter();
-
- _enable(this);
- }
-
- disable(reset = false) {
- panelManager.disable();
-
- DTP_EXTENSION = null;
- SETTINGS = null;
- DESKTOPSETTINGS = null;
- TERMINALSETTINGS = null;
- panelManager = null;
-
- if (!reset) {
- extensionSystem.disconnect(extensionChangedHandler);
- delete global.dashToPanel;
-
- AppIcons.resetRecentlyClickedApp();
+ // The Ubuntu Dock extension might get enabled after this extension
+ extensionChangedHandler = extensionSystem.connect(
+ 'extension-state-changed',
+ (data, extension) => {
+ if (extension.uuid === UBUNTU_DOCK_UUID && extension.state === 1) {
+ _enable(this)
}
+ },
+ )
- if (startupCompleteHandler) {
- Main.layoutManager.disconnect(startupCompleteHandler);
- startupCompleteHandler = null;
- }
+ //create a global object that can emit signals and conveniently expose functionalities to other extensions
+ global.dashToPanel = new EventEmitter()
- Main.sessionMode.hasOverview = this._realHasOverview;
+ _enable(this)
+ }
+
+ disable(reset = false) {
+ panelManager.disable()
+
+ DTP_EXTENSION = null
+ SETTINGS = null
+ DESKTOPSETTINGS = null
+ TERMINALSETTINGS = null
+ panelManager = null
+
+ if (!reset) {
+ extensionSystem.disconnect(extensionChangedHandler)
+ delete global.dashToPanel
+
+ AppIcons.resetRecentlyClickedApp()
}
+
+ if (startupCompleteHandler) {
+ Main.layoutManager.disconnect(startupCompleteHandler)
+ startupCompleteHandler = null
+ }
+
+ Main.sessionMode.hasOverview = this._realHasOverview
+ }
}
function _enable(extension) {
- let enabled = global.settings.get_strv('enabled-extensions');
+ let enabled = global.settings.get_strv('enabled-extensions')
- if (enabled?.indexOf(UBUNTU_DOCK_UUID) >= 0)
- extensionSystem.disableExtension(UBUNTU_DOCK_UUID);
+ if (enabled?.indexOf(UBUNTU_DOCK_UUID) >= 0)
+ extensionSystem.disableExtension(UBUNTU_DOCK_UUID)
- if (panelManager)
- return
+ if (panelManager) return
- SETTINGS = extension.getSettings('org.gnome.shell.extensions.dash-to-panel');
- DESKTOPSETTINGS = new Gio.Settings({schema_id: 'org.gnome.desktop.interface'});
- TERMINALSETTINGS = new Gio.Settings({schema_id: 'org.gnome.desktop.default-applications.terminal'})
- EXTENSION_UUID = extension.uuid
- EXTENSION_PATH = extension.path
+ SETTINGS = extension.getSettings('org.gnome.shell.extensions.dash-to-panel')
+ DESKTOPSETTINGS = new Gio.Settings({
+ schema_id: 'org.gnome.desktop.interface',
+ })
+ TERMINALSETTINGS = new Gio.Settings({
+ schema_id: 'org.gnome.desktop.default-applications.terminal',
+ })
+ EXTENSION_UUID = extension.uuid
+ EXTENSION_PATH = extension.path
- Main.layoutManager.startInOverview = !SETTINGS.get_boolean('hide-overview-on-startup');
+ Main.layoutManager.startInOverview = !SETTINGS.get_boolean(
+ 'hide-overview-on-startup',
+ )
- if (SETTINGS.get_boolean('hide-overview-on-startup') && Main.layoutManager._startingUp) {
- Main.sessionMode.hasOverview = false;
- startupCompleteHandler = Main.layoutManager.connect('startup-complete', () => {
- Main.sessionMode.hasOverview = extension._realHasOverview
- });
- }
+ if (
+ SETTINGS.get_boolean('hide-overview-on-startup') &&
+ Main.layoutManager._startingUp
+ ) {
+ Main.sessionMode.hasOverview = false
+ startupCompleteHandler = Main.layoutManager.connect(
+ 'startup-complete',
+ () => {
+ Main.sessionMode.hasOverview = extension._realHasOverview
+ },
+ )
+ }
- // show the donate icon every 120 days (10368000000 milliseconds)
- let donateIconUnixtime = SETTINGS.get_string('hide-donate-icon-unixtime')
+ // show the donate icon every 120 days (10368000000 milliseconds)
+ let donateIconUnixtime = SETTINGS.get_string('hide-donate-icon-unixtime')
- if (donateIconUnixtime && donateIconUnixtime < Date.now() - 10368000000)
- SETTINGS.set_string('hide-donate-icon-unixtime', '')
+ if (donateIconUnixtime && donateIconUnixtime < Date.now() - 10368000000)
+ SETTINGS.set_string('hide-donate-icon-unixtime', '')
- panelManager = new PanelManager.PanelManager();
+ panelManager = new PanelManager.PanelManager()
- panelManager.enable();
-}
\ No newline at end of file
+ panelManager.enable()
+}
diff --git a/intellihide.js b/intellihide.js
index 9bc157e..4ccb762 100644
--- a/intellihide.js
+++ b/intellihide.js
@@ -15,413 +15,474 @@
* along with this program. If not, see .
*/
-import Clutter from 'gi://Clutter';
-import Meta from 'gi://Meta';
-import Shell from 'gi://Shell';
-import St from 'gi://St';
+import Clutter from 'gi://Clutter'
+import Meta from 'gi://Meta'
+import Shell from 'gi://Shell'
+import St from 'gi://St'
-import * as GrabHelper from 'resource:///org/gnome/shell/ui/grabHelper.js';
-import * as Layout from 'resource:///org/gnome/shell/ui/layout.js';
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
-import * as OverviewControls from 'resource:///org/gnome/shell/ui/overviewControls.js';
-import * as PointerWatcher from 'resource:///org/gnome/shell/ui/pointerWatcher.js';
+import * as GrabHelper from 'resource:///org/gnome/shell/ui/grabHelper.js'
+import * as Layout from 'resource:///org/gnome/shell/ui/layout.js'
+import * as Main from 'resource:///org/gnome/shell/ui/main.js'
+import * as OverviewControls from 'resource:///org/gnome/shell/ui/overviewControls.js'
+import * as PointerWatcher from 'resource:///org/gnome/shell/ui/pointerWatcher.js'
-import * as Proximity from './proximity.js';
-import * as Utils from './utils.js';
-import {SETTINGS} from './extension.js';
+import * as Proximity from './proximity.js'
+import * as Utils from './utils.js'
+import { SETTINGS } from './extension.js'
//timeout intervals
-const CHECK_POINTER_MS = 200;
-const CHECK_GRAB_MS = 400;
-const POST_ANIMATE_MS = 50;
-const MIN_UPDATE_MS = 250;
+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 T1 = 'checkGrabTimeout'
+const T2 = 'limitUpdateTimeout'
+const T3 = 'postAnimateTimeout'
-const SIDE_CONTROLS_ANIMATION_TIME = OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / (OverviewControls.SIDE_CONTROLS_ANIMATION_TIME > 1 ? 1000 : 1);
+const SIDE_CONTROLS_ANIMATION_TIME =
+ OverviewControls.SIDE_CONTROLS_ANIMATION_TIME /
+ (OverviewControls.SIDE_CONTROLS_ANIMATION_TIME > 1 ? 1000 : 1)
export const Hold = {
- NONE: 0,
- TEMPORARY: 1,
- PERMANENT: 2
-};
+ NONE: 0,
+ TEMPORARY: 1,
+ PERMANENT: 2,
+}
export const Intellihide = class {
+ constructor(dtpPanel) {
+ this._dtpPanel = dtpPanel
+ this._panelBox = dtpPanel.panelBox
+ this._panelManager = dtpPanel.panelManager
+ this._proximityManager = this._panelManager.proximityManager
+ this._holdStatus = Hold.NONE
- constructor(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._signalsHandler = new Utils.GlobalSignalsHandler()
+ this._timeoutsHandler = new Utils.TimeoutsHandler()
- this._intellihideChangedId = SETTINGS.connect('changed::intellihide', () => this._changeEnabledStatus());
- this._intellihideOnlySecondaryChangedId = SETTINGS.connect('changed::intellihide-only-secondary', () => this._changeEnabledStatus());
+ this._intellihideChangedId = SETTINGS.connect('changed::intellihide', () =>
+ this._changeEnabledStatus(),
+ )
+ this._intellihideOnlySecondaryChangedId = SETTINGS.connect(
+ 'changed::intellihide-only-secondary',
+ () => this._changeEnabledStatus(),
+ )
- this.enabled = false;
- this._changeEnabledStatus();
+ this.enabled = false
+ this._changeEnabledStatus()
+ }
+
+ enable() {
+ this.enabled = true
+ this._monitor = this._dtpPanel.monitor
+ this._animationDestination = -1
+ this._pendingUpdate = false
+ this._hoveredOut = false
+ this._windowOverlap = false
+ this._translationProp =
+ 'translation_' + (this._dtpPanel.checkIfVertical() ? 'x' : 'y')
+
+ this._panelBox.translation_y = 0
+ this._panelBox.translation_x = 0
+
+ this._setTrackPanel(true)
+ this._bindGeneralSignals()
+
+ if (SETTINGS.get_boolean('intellihide-hide-from-windows')) {
+ this._proximityWatchId = this._proximityManager.createWatch(
+ this._panelBox.get_parent(),
+ this._dtpPanel.monitor.index,
+ Proximity.Mode[SETTINGS.get_string('intellihide-behaviour')],
+ 0,
+ 0,
+ (overlap) => {
+ this._windowOverlap = overlap
+ this._queueUpdatePanelPosition()
+ },
+ )
}
- enable() {
- this.enabled = true;
- this._monitor = this._dtpPanel.monitor;
- this._animationDestination = -1;
- this._pendingUpdate = false;
- this._hoveredOut = false;
- this._windowOverlap = false;
- this._translationProp = 'translation_' + (this._dtpPanel.checkIfVertical() ? 'x' : 'y');
+ this._setRevealMechanism()
+ this._queueUpdatePanelPosition()
+ }
- this._panelBox.translation_y = 0;
- this._panelBox.translation_x = 0;
+ disable(reset) {
+ if (this._proximityWatchId) {
+ this._proximityManager.removeWatch(this._proximityWatchId)
+ }
- this._setTrackPanel(true);
- this._bindGeneralSignals();
+ this._setTrackPanel(false)
- if (SETTINGS.get_boolean('intellihide-hide-from-windows')) {
- this._proximityWatchId = this._proximityManager.createWatch(
- this._panelBox.get_parent(),
- this._dtpPanel.monitor.index,
- Proximity.Mode[SETTINGS.get_string('intellihide-behaviour')],
- 0, 0,
- overlap => {
- this._windowOverlap = overlap;
- this._queueUpdatePanelPosition();
- }
- );
+ this._signalsHandler.destroy()
+ this._timeoutsHandler.destroy()
+
+ this._removeRevealMechanism()
+
+ this._revealPanel(!reset)
+
+ this.enabled = false
+ }
+
+ destroy() {
+ SETTINGS.disconnect(this._intellihideChangedId)
+ SETTINGS.disconnect(this._intellihideOnlySecondaryChangedId)
+
+ if (this.enabled) {
+ this.disable()
+ }
+ }
+
+ toggle() {
+ this[this._holdStatus & Hold.PERMANENT ? 'release' : 'revealAndHold'](
+ Hold.PERMANENT,
+ )
+ }
+
+ revealAndHold(holdStatus) {
+ if (this.enabled && !this._holdStatus) {
+ this._revealPanel()
+ }
+
+ this._holdStatus |= holdStatus
+ }
+
+ release(holdStatus) {
+ this._holdStatus -= holdStatus
+
+ if (this.enabled && !this._holdStatus) {
+ this._queueUpdatePanelPosition()
+ }
+ }
+
+ reset() {
+ this.disable(true)
+ this.enable()
+ }
+
+ _changeEnabledStatus() {
+ let intellihide = SETTINGS.get_boolean('intellihide')
+ let onlySecondary = SETTINGS.get_boolean('intellihide-only-secondary')
+ let enabled = intellihide && !(this._dtpPanel.isPrimary && onlySecondary)
+
+ if (this.enabled !== enabled) {
+ this[enabled ? 'enable' : 'disable']()
+ }
+ }
+
+ _bindGeneralSignals() {
+ this._signalsHandler.add(
+ [
+ this._dtpPanel.taskbar,
+ ['menu-closed', 'end-drag'],
+ () => {
+ this._panelBox.sync_hover()
+ this._onHoverChanged()
+ },
+ ],
+ [
+ SETTINGS,
+ [
+ 'changed::intellihide-use-pressure',
+ 'changed::intellihide-hide-from-windows',
+ 'changed::intellihide-behaviour',
+ 'changed::intellihide-pressure-threshold',
+ 'changed::intellihide-pressure-time',
+ ],
+ () => this.reset(),
+ ],
+ [this._panelBox, 'notify::hover', () => this._onHoverChanged()],
+ [
+ this._dtpPanel.taskbar.previewMenu,
+ 'open-state-changed',
+ () => this._queueUpdatePanelPosition(),
+ ],
+ [
+ Main.overview,
+ ['showing', 'hiding'],
+ () => this._queueUpdatePanelPosition(),
+ ],
+ )
+
+ if (Meta.is_wayland_compositor()) {
+ this._signalsHandler.add([
+ this._panelBox,
+ 'notify::visible',
+ () => Utils.setDisplayUnredirect(!this._panelBox.visible),
+ ])
+ }
+ }
+
+ _onHoverChanged() {
+ this._hoveredOut = !this._panelBox.hover
+ this._queueUpdatePanelPosition()
+ }
+
+ _setTrackPanel(enable) {
+ let actorData = Utils.getTrackedActorData(this._panelBox)
+
+ actorData.affectsStruts = !enable
+ actorData.trackFullscreen = !enable
+
+ this._panelBox.track_hover = enable
+ this._panelBox.reactive = enable
+ this._panelBox.visible = enable ? enable : this._panelBox.visible
+
+ Main.layoutManager._queueUpdateRegions()
+ }
+
+ _setRevealMechanism() {
+ let barriers = Meta.BackendCapabilities.BARRIERS
+
+ if (
+ (global.backend.capabilities & barriers) === barriers &&
+ SETTINGS.get_boolean('intellihide-use-pressure')
+ ) {
+ this._edgeBarrier = this._createBarrier()
+ this._pressureBarrier = new Layout.PressureBarrier(
+ SETTINGS.get_int('intellihide-pressure-threshold'),
+ 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() {
+ if (this._pointerWatch) {
+ PointerWatcher.getPointerWatcher()._removeWatch(this._pointerWatch)
+ }
+
+ if (this._pressureBarrier) {
+ this._pressureBarrier.destroy()
+ this._edgeBarrier.destroy()
+
+ this._pressureBarrier = 0
+ }
+ }
+
+ _createBarrier() {
+ let position = this._dtpPanel.geom.position
+ let opts = { backend: global.backend }
+
+ if (this._dtpPanel.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(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(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() {
+ if (this._pendingUpdate) {
+ this._pendingUpdate = false
+ this._queueUpdatePanelPosition()
+ }
+ }
+
+ _checkIfShouldBeVisible(fromRevealMechanism) {
+ if (
+ Main.overview.visibleTarget ||
+ this._dtpPanel.taskbar.previewMenu.opened ||
+ this._dtpPanel.taskbar._dragMonitor ||
+ 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 SETTINGS.get_boolean('intellihide-show-in-fullscreen')
+ }
+
+ return !mouseBtnIsPressed
+ }
+
+ if (!SETTINGS.get_boolean('intellihide-hide-from-windows')) {
+ return this._panelBox.hover
+ }
+
+ return !this._windowOverlap
+ }
+
+ _checkIfGrab() {
+ let isGrab
+
+ if (GrabHelper._grabHelperStack)
+ // gnome-shell < 42
+ isGrab = GrabHelper._grabHelperStack.some(
+ (gh) => gh._owner == this._dtpPanel.panel,
+ )
+ else if (global.stage.get_grab_actor) {
+ // gnome-shell >= 42
+ let grabActor = global.stage.get_grab_actor()
+ let sourceActor = grabActor?._sourceActor || grabActor
+
+ isGrab =
+ sourceActor &&
+ (sourceActor == Main.layoutManager.dummyCursor ||
+ this._dtpPanel.statusArea.quickSettings?.menu.actor.contains(
+ sourceActor,
+ ) ||
+ this._dtpPanel.panel.contains(sourceActor))
+ }
+
+ if (isGrab)
+ //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 isGrab
+ }
+
+ _revealPanel(immediate) {
+ if (!this._panelBox.visible) {
+ this._panelBox.visible = true
+ this._dtpPanel.taskbar._shownInitially = false
+ }
+
+ this._animatePanel(0, immediate)
+ }
+
+ _hidePanel(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(destination, immediate) {
+ let animating = Utils.isAnimating(this._panelBox, this._translationProp)
+
+ 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) {
+ Utils.stopAnimations(this._panelBox)
+ }
+
+ this._animationDestination = destination
+
+ if (immediate) {
+ this._panelBox[this._translationProp] = destination
+ this._panelBox.visible = !destination
+ } 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
+ : 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
+ ? SETTINGS.get_int('intellihide-close-delay') * 0.001
+ : 0,
+ transition: 'easeOutQuad',
+ onComplete: () => {
+ this._panelBox.visible = !destination
+ Main.layoutManager._queueUpdateRegions()
+ this._timeoutsHandler.add([
+ T3,
+ POST_ANIMATE_MS,
+ () => this._queueUpdatePanelPosition(),
+ ])
+ },
}
- this._setRevealMechanism();
- this._queueUpdatePanelPosition();
+ tweenOpts[this._translationProp] = destination
+ Utils.animate(this._panelBox, tweenOpts)
+ }
}
- disable(reset) {
- if (this._proximityWatchId) {
- this._proximityManager.removeWatch(this._proximityWatchId);
- }
-
- this._setTrackPanel(false);
-
- this._signalsHandler.destroy();
- this._timeoutsHandler.destroy();
-
- this._removeRevealMechanism();
-
- this._revealPanel(!reset);
-
- this.enabled = false;
- }
-
- destroy() {
- SETTINGS.disconnect(this._intellihideChangedId);
- SETTINGS.disconnect(this._intellihideOnlySecondaryChangedId);
-
- if (this.enabled) {
- this.disable();
- }
- }
-
- toggle() {
- this[this._holdStatus & Hold.PERMANENT ? 'release' : 'revealAndHold'](Hold.PERMANENT);
- }
-
- revealAndHold(holdStatus) {
- if (this.enabled && !this._holdStatus) {
- this._revealPanel();
- }
-
- this._holdStatus |= holdStatus;
- }
-
- release(holdStatus) {
- this._holdStatus -= holdStatus;
-
- if (this.enabled && !this._holdStatus) {
- this._queueUpdatePanelPosition();
- }
- }
-
- reset() {
- this.disable(true);
- this.enable();
- }
-
- _changeEnabledStatus() {
- let intellihide = SETTINGS.get_boolean('intellihide');
- let onlySecondary = SETTINGS.get_boolean('intellihide-only-secondary');
- let enabled = intellihide && !(this._dtpPanel.isPrimary && onlySecondary);
-
- if (this.enabled !== enabled) {
- this[enabled ? 'enable' : 'disable']();
- }
- }
-
- _bindGeneralSignals() {
- this._signalsHandler.add(
- [
- this._dtpPanel.taskbar,
- ['menu-closed', 'end-drag'],
- () => {
- this._panelBox.sync_hover();
- this._onHoverChanged();
- }
- ],
- [
- SETTINGS,
- [
- 'changed::intellihide-use-pressure',
- 'changed::intellihide-hide-from-windows',
- 'changed::intellihide-behaviour',
- 'changed::intellihide-pressure-threshold',
- 'changed::intellihide-pressure-time'
- ],
- () => this.reset()
- ],
- [
- this._panelBox,
- 'notify::hover',
- () => this._onHoverChanged()
- ],
- [
- this._dtpPanel.taskbar.previewMenu,
- 'open-state-changed',
- () => this._queueUpdatePanelPosition()
- ],
- [
- Main.overview,
- [
- 'showing',
- 'hiding'
- ],
- () => this._queueUpdatePanelPosition()
- ]
- );
-
- if (Meta.is_wayland_compositor()) {
- this._signalsHandler.add([
- this._panelBox,
- 'notify::visible',
- () => Utils.setDisplayUnredirect(!this._panelBox.visible)
- ]);
- }
- }
-
- _onHoverChanged() {
- this._hoveredOut = !this._panelBox.hover;
- this._queueUpdatePanelPosition();
- }
-
- _setTrackPanel(enable) {
- let actorData = Utils.getTrackedActorData(this._panelBox)
-
- actorData.affectsStruts = !enable;
- actorData.trackFullscreen = !enable;
-
- this._panelBox.track_hover = enable;
- this._panelBox.reactive = enable;
- this._panelBox.visible = enable ? enable : this._panelBox.visible;
-
- Main.layoutManager._queueUpdateRegions();
- }
-
- _setRevealMechanism() {
- let barriers = Meta.BackendCapabilities.BARRIERS
-
- if ((global.backend.capabilities & barriers) === barriers && SETTINGS.get_boolean('intellihide-use-pressure')) {
- this._edgeBarrier = this._createBarrier();
- this._pressureBarrier = new Layout.PressureBarrier(
- SETTINGS.get_int('intellihide-pressure-threshold'),
- 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() {
- if (this._pointerWatch) {
- PointerWatcher.getPointerWatcher()._removeWatch(this._pointerWatch);
- }
-
- if (this._pressureBarrier) {
- this._pressureBarrier.destroy();
- this._edgeBarrier.destroy();
-
- this._pressureBarrier = 0;
- }
- }
-
- _createBarrier() {
- let position = this._dtpPanel.geom.position;
- let opts = { backend: global.backend };
-
- if (this._dtpPanel.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(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(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() {
- if (this._pendingUpdate) {
- this._pendingUpdate = false;
- this._queueUpdatePanelPosition();
- }
- }
-
- _checkIfShouldBeVisible(fromRevealMechanism) {
- if (Main.overview.visibleTarget || this._dtpPanel.taskbar.previewMenu.opened ||
- this._dtpPanel.taskbar._dragMonitor || 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 SETTINGS.get_boolean('intellihide-show-in-fullscreen');
- }
-
- return !mouseBtnIsPressed;
- }
-
- if (!SETTINGS.get_boolean('intellihide-hide-from-windows')) {
- return this._panelBox.hover;
- }
-
- return !this._windowOverlap;
- }
-
- _checkIfGrab() {
- let isGrab
-
- if (GrabHelper._grabHelperStack)
- // gnome-shell < 42
- isGrab = GrabHelper._grabHelperStack.some(gh => gh._owner == this._dtpPanel.panel)
- else if (global.stage.get_grab_actor) {
- // gnome-shell >= 42
- let grabActor = global.stage.get_grab_actor()
- let sourceActor = grabActor?._sourceActor || grabActor
-
- isGrab = sourceActor &&
- (sourceActor == Main.layoutManager.dummyCursor ||
- this._dtpPanel.statusArea.quickSettings?.menu.actor.contains(sourceActor) ||
- this._dtpPanel.panel.contains(sourceActor))
- }
-
- if (isGrab)
- //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 isGrab;
- }
-
- _revealPanel(immediate) {
- if (!this._panelBox.visible) {
- this._panelBox.visible = true;
- this._dtpPanel.taskbar._shownInitially = false;
- }
-
- this._animatePanel(0, immediate);
- }
-
- _hidePanel(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(destination, immediate) {
- let animating = Utils.isAnimating(this._panelBox, this._translationProp);
-
- 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) {
- Utils.stopAnimations(this._panelBox);
- }
-
- this._animationDestination = destination;
-
- if (immediate) {
- this._panelBox[this._translationProp] = destination;
- this._panelBox.visible = !destination;
- } 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 :
- 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 ? SETTINGS.get_int('intellihide-close-delay') * 0.001 : 0,
- transition: 'easeOutQuad',
- onComplete: () => {
- this._panelBox.visible = !destination;
- Main.layoutManager._queueUpdateRegions();
- this._timeoutsHandler.add([T3, POST_ANIMATE_MS, () => this._queueUpdatePanelPosition()]);
- }
- };
-
- tweenOpts[this._translationProp] = destination;
- Utils.animate(this._panelBox, tweenOpts);
- }
- }
-
- this._hoveredOut = false;
- }
+ this._hoveredOut = false
+ }
}
diff --git a/overview.js b/overview.js
index 79b7ba9..28a0ca3 100644
--- a/overview.js
+++ b/overview.js
@@ -16,503 +16,537 @@
*
* 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.
*/
-import * as Intellihide from './intellihide.js';
-import * as Utils from './utils.js';
+import * as Intellihide from './intellihide.js'
+import * as Utils from './utils.js'
-import Clutter from 'gi://Clutter';
-import Gio from 'gi://Gio';
-import Shell from 'gi://Shell';
-import St from 'gi://St';
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
-import * as WindowManager from 'resource:///org/gnome/shell/ui/windowManager.js';
-import {WindowPreview} from 'resource:///org/gnome/shell/ui/windowPreview.js';
-import {InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js';
-import {SETTINGS} from './extension.js';
+import Clutter from 'gi://Clutter'
+import Gio from 'gi://Gio'
+import Shell from 'gi://Shell'
+import St from 'gi://St'
+import * as Main from 'resource:///org/gnome/shell/ui/main.js'
+import * as WindowManager from 'resource:///org/gnome/shell/ui/windowManager.js'
+import { WindowPreview } from 'resource:///org/gnome/shell/ui/windowPreview.js'
+import { InjectionManager } from 'resource:///org/gnome/shell/extensions/extension.js'
+import { SETTINGS } from './extension.js'
-const GS_HOTKEYS_KEY = 'switch-to-application-';
+const GS_HOTKEYS_KEY = 'switch-to-application-'
// When the dash is shown, workspace window preview bottom labels go over it (default
// gnome-shell behavior), but when the extension hides the dash, leave some space
// so those labels don't go over a bottom panel
-const LABEL_MARGIN = 60;
+const LABEL_MARGIN = 60
//timeout names
-const T1 = 'swipeEndTimeout';
-const T2 = 'numberOverlayTimeout';
+const T1 = 'swipeEndTimeout'
+const T2 = 'numberOverlayTimeout'
export const Overview = class {
+ constructor() {
+ this._injectionManager = new InjectionManager()
+ this._numHotkeys = 10
+ }
- constructor() {
- this._injectionManager = new InjectionManager();
- this._numHotkeys = 10;
+ enable(primaryPanel) {
+ this._panel = primaryPanel
+ this.taskbar = primaryPanel.taskbar
+
+ this._injectionsHandler = new Utils.InjectionsHandler()
+ this._signalsHandler = new Utils.GlobalSignalsHandler()
+ this._timeoutsHandler = new Utils.TimeoutsHandler()
+
+ this._optionalWorkspaceIsolation()
+ this._optionalHotKeys()
+ this._optionalNumberOverlay()
+ this._optionalClickToExit()
+
+ this.toggleDash()
+ this._adaptAlloc()
+
+ this._signalsHandler.add([
+ SETTINGS,
+ ['changed::stockgs-keep-dash', 'changed::panel-sizes'],
+ () => this.toggleDash(),
+ ])
+ }
+
+ disable() {
+ this._signalsHandler.destroy()
+ this._injectionsHandler.destroy()
+ this._timeoutsHandler.destroy()
+ this._injectionManager.clear()
+
+ this.toggleDash(true)
+
+ // Remove key bindings
+ this._disableHotKeys()
+ this._disableExtraShortcut()
+ this._disableClickToExit()
+ }
+
+ toggleDash(visible) {
+ if (visible === undefined) {
+ visible = SETTINGS.get_boolean('stockgs-keep-dash')
}
- enable (primaryPanel) {
- this._panel = primaryPanel;
- this.taskbar = primaryPanel.taskbar;
+ let visibilityFunc = visible ? 'show' : 'hide'
+ let height = visible ? -1 : LABEL_MARGIN * Utils.getScaleFactor()
+ let overviewControls = Main.overview._overview._controls
- this._injectionsHandler = new Utils.InjectionsHandler();
- this._signalsHandler = new Utils.GlobalSignalsHandler();
- this._timeoutsHandler = new Utils.TimeoutsHandler();
+ overviewControls.dash[visibilityFunc]()
+ overviewControls.dash.set_height(height)
+ }
- this._optionalWorkspaceIsolation();
- this._optionalHotKeys();
- this._optionalNumberOverlay();
- this._optionalClickToExit();
+ _adaptAlloc() {
+ let overviewControls = Main.overview._overview._controls
- this.toggleDash();
- this._adaptAlloc();
+ this._injectionManager.overrideMethod(
+ Object.getPrototypeOf(overviewControls),
+ 'vfunc_allocate',
+ (originalAllocate) => (box) => {
+ let focusedPanel = this._panel.panelManager.focusedMonitorPanel
- this._signalsHandler.add([
- SETTINGS,
- [
- 'changed::stockgs-keep-dash',
- 'changed::panel-sizes'
- ],
- () => this.toggleDash()
- ]);
- }
+ if (focusedPanel) {
+ let position = focusedPanel.geom.position
+ let isBottom = position == St.Side.BOTTOM
- disable() {
- this._signalsHandler.destroy();
- this._injectionsHandler.destroy();
- this._timeoutsHandler.destroy();
- this._injectionManager.clear();
+ if (focusedPanel.intellihide?.enabled) {
+ // Panel intellihide is enabled (struts aren't taken into account on overview allocation),
+ // dynamically modify the overview box to follow the reveal/hide animation
+ let { transitioning, finalState, progress } =
+ overviewControls._stateAdjustment.getStateTransitionParams()
+ let size =
+ focusedPanel.geom[focusedPanel.checkIfVertical() ? 'w' : 'h'] *
+ (transitioning
+ ? Math.abs((finalState != 0 ? 0 : 1) - progress)
+ : 1)
- this.toggleDash(true);
-
- // Remove key bindings
- this._disableHotKeys();
- this._disableExtraShortcut();
- this._disableClickToExit();
- }
-
- toggleDash(visible) {
- if (visible === undefined) {
- visible = SETTINGS.get_boolean('stockgs-keep-dash');
+ if (isBottom || position == St.Side.RIGHT)
+ box[focusedPanel.fixedCoord.c2] -= size
+ else box[focusedPanel.fixedCoord.c1] += size
+ } else if (isBottom)
+ // The default overview allocation takes into account external
+ // struts, everywhere but the bottom where the dash is usually fixed anyway.
+ // If there is a bottom panel under the dash location, give it some space here
+ box.y2 -= focusedPanel.geom.h
}
- let visibilityFunc = visible ? 'show' : 'hide';
- let height = visible ? -1 : LABEL_MARGIN * Utils.getScaleFactor();
- let overviewControls = Main.overview._overview._controls;
+ originalAllocate.call(overviewControls, box)
+ },
+ )
+ }
- overviewControls.dash[visibilityFunc]();
- overviewControls.dash.set_height(height);
+ /**
+ * Isolate overview to open new windows for inactive apps
+ */
+ _optionalWorkspaceIsolation() {
+ let label = 'optionalWorkspaceIsolation'
+
+ let 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(),
+ ),
+ ])
}
- _adaptAlloc() {
- let overviewControls = Main.overview._overview._controls
+ let disable = () => {
+ this._signalsHandler.removeWithLabel(label)
+ this._injectionsHandler.removeWithLabel(label)
+ }
- this._injectionManager.overrideMethod(Object.getPrototypeOf(overviewControls), 'vfunc_allocate',
- (originalAllocate) =>
- (box) => {
- let focusedPanel = this._panel.panelManager.focusedMonitorPanel
-
- if (focusedPanel) {
- let position = focusedPanel.geom.position
- let isBottom = position == St.Side.BOTTOM
+ 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 (focusedPanel.intellihide?.enabled) {
- // Panel intellihide is enabled (struts aren't taken into account on overview allocation),
- // dynamically modify the overview box to follow the reveal/hide animation
- let { transitioning, finalState, progress } = overviewControls._stateAdjustment.getStateTransitionParams()
- let size = focusedPanel.geom[focusedPanel.checkIfVertical() ? 'w' : 'h'] *
- (transitioning ? Math.abs((finalState != 0 ? 0 : 1) - progress) : 1)
+ if (
+ windows.length > 0 &&
+ (!(windows.length == 1 && windows[0].skip_taskbar) ||
+ this.is_on_workspace(activeWorkspace))
+ )
+ return Main.activateWindow(windows[0])
- if (isBottom || position == St.Side.RIGHT)
- box[focusedPanel.fixedCoord.c2] -= size
- else
- box[focusedPanel.fixedCoord.c1] += size
- } else if (isBottom)
- // The default overview allocation takes into account external
- // struts, everywhere but the bottom where the dash is usually fixed anyway.
- // If there is a bottom panel under the dash location, give it some space here
- box.y2 -= focusedPanel.geom.h
- }
-
- originalAllocate.call(overviewControls, box)
+ return this.open_new_window(-1)
+ }
+
+ this._signalsHandler.add([
+ SETTINGS,
+ 'changed::isolate-workspaces',
+ () => {
+ this._panel.panelManager.allPanels.forEach((p) =>
+ p.taskbar.resetAppIcons(),
+ )
+
+ if (SETTINGS.get_boolean('isolate-workspaces')) enable()
+ else disable()
+ },
+ ])
+
+ if (SETTINGS.get_boolean('isolate-workspaces')) enable()
+ }
+
+ // Hotkeys
+ _activateApp(appIndex, modifiers) {
+ let seenApps = {}
+ let apps = []
+
+ this.taskbar._getAppIcons().forEach((appIcon) => {
+ if (!seenApps[appIcon.app] || this.taskbar.allowSplitApps) {
+ 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 (
+ SETTINGS.get_boolean('shortcut-previews') &&
+ windowCount > 1 &&
+ !(
+ modifiers &
+ ~(Clutter.ModifierType.MOD1_MASK | Clutter.ModifierType.SUPER_MASK)
+ )
+ ) {
+ //ignore the alt (MOD1_MASK) and super key (SUPER_MASK)
+ if (
+ this._hotkeyPreviewCycleInfo &&
+ this._hotkeyPreviewCycleInfo.appIcon != appIcon
+ ) {
+ this._endHotkeyPreviewCycle()
+ }
+
+ if (!this._hotkeyPreviewCycleInfo) {
+ this._hotkeyPreviewCycleInfo = {
+ appIcon: appIcon,
+ currentWindow: appIcon.window,
+ keyFocusOutId: appIcon.connect('key-focus-out', () =>
+ appIcon.grab_key_focus(),
+ ),
+ capturedEventId: global.stage.connect(
+ 'captured-event',
+ (actor, e) => {
+ if (
+ e.type() == Clutter.EventType.KEY_RELEASE &&
+ e.get_key_symbol() == (Clutter.KEY_Super_L || Clutter.Super_L)
+ ) {
+ this._endHotkeyPreviewCycle(true)
}
- );
- }
- /**
- * Isolate overview to open new windows for inactive apps
- */
- _optionalWorkspaceIsolation() {
- let label = 'optionalWorkspaceIsolation';
-
- let enable = () => {
- this._injectionsHandler.removeWithLabel(label);
+ return Clutter.EVENT_PROPAGATE
+ },
+ ),
+ }
- 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())
- ]);
+ appIcon._hotkeysCycle = appIcon.window
+ appIcon.window = null
+ appIcon._previewMenu.open(appIcon, true)
+ appIcon.grab_key_focus()
}
- let disable = () => {
- this._signalsHandler.removeWithLabel(label);
- this._injectionsHandler.removeWithLabel(label);
+ appIcon._previewMenu.focusNext()
+ } else {
+ // Activate with button = 1, i.e. same as left click
+ let button = 1
+ this._endHotkeyPreviewCycle()
+ appIcon.activate(button, modifiers, !this.taskbar.allowSplitApps)
+ }
+ }
+ }
+
+ _endHotkeyPreviewCycle(focusWindow) {
+ if (this._hotkeyPreviewCycleInfo) {
+ global.stage.disconnect(this._hotkeyPreviewCycleInfo.capturedEventId)
+ this._hotkeyPreviewCycleInfo.appIcon.disconnect(
+ this._hotkeyPreviewCycleInfo.keyFocusOutId,
+ )
+
+ if (focusWindow) {
+ this._hotkeyPreviewCycleInfo.appIcon._previewMenu.activateFocused()
+ } else this._hotkeyPreviewCycleInfo.appIcon._previewMenu.close()
+
+ this._hotkeyPreviewCycleInfo.appIcon.window =
+ this._hotkeyPreviewCycleInfo.currentWindow
+ delete this._hotkeyPreviewCycleInfo.appIcon._hotkeysCycle
+ this._hotkeyPreviewCycleInfo = 0
+ }
+ }
+
+ _optionalHotKeys() {
+ this._hotKeysEnabled = false
+ if (SETTINGS.get_boolean('hot-keys')) this._enableHotKeys()
+
+ this._signalsHandler.add([
+ SETTINGS,
+ 'changed::hot-keys',
+ () => {
+ if (SETTINGS.get_boolean('hot-keys')) this._enableHotKeys()
+ else this._disableHotKeys()
+ },
+ ])
+ }
+
+ _resetHotkeys() {
+ this._disableHotKeys()
+ this._enableHotKeys()
+ }
+
+ _enableHotKeys() {
+ 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 = SETTINGS.get_string('shortcut-num-keys')
+ let bothNumKeys = shortcutNumKeys == 'BOTH'
+ let keys = []
+ let prefixModifiers = Clutter.ModifierType.SUPER_MASK
+
+ if (SETTINGS.get_string('hotkey-prefix-text') == 'SuperAlt')
+ prefixModifiers |= Clutter.ModifierType.MOD1_MASK
+
+ 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) {
+ let modifiers = prefixModifiers
+
+ // for some reason, in gnome-shell >= 40 Clutter.get_current_event() is now empty
+ // for keyboard events. Create here the modifiers that are needed in appicon.activate
+ modifiers |=
+ key.indexOf('-shift-') >= 0 ? Clutter.ModifierType.SHIFT_MASK : 0
+ modifiers |=
+ key.indexOf('-ctrl-') >= 0 ? Clutter.ModifierType.CONTROL_MASK : 0
+
+ for (let i = 0; i < this._numHotkeys; i++) {
+ let appNum = i
+
+ Utils.addKeybinding(key + (i + 1), SETTINGS, () =>
+ this._activateApp(appNum, modifiers),
+ )
+ }
+ }, this)
+
+ this._hotKeysEnabled = true
+
+ if (SETTINGS.get_string('hotkeys-overlay-combo') === 'ALWAYS')
+ this.taskbar.toggleNumberOverlay(true)
+ }
+
+ _disableHotKeys() {
+ 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: 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() {
+ // Enable extra shortcut
+ if (SETTINGS.get_boolean('hot-keys')) this._enableExtraShortcut()
+
+ this._signalsHandler.add(
+ [SETTINGS, 'changed::hot-keys', this._checkHotkeysOptions.bind(this)],
+ [
+ SETTINGS,
+ 'changed::hotkeys-overlay-combo',
+ () => {
+ if (
+ SETTINGS.get_boolean('hot-keys') &&
+ SETTINGS.get_string('hotkeys-overlay-combo') === 'ALWAYS'
+ )
+ this.taskbar.toggleNumberOverlay(true)
+ else this.taskbar.toggleNumberOverlay(false)
+ },
+ ],
+ [SETTINGS, 'changed::shortcut-num-keys', () => this._resetHotkeys()],
+ )
+ }
+
+ _checkHotkeysOptions() {
+ if (SETTINGS.get_boolean('hot-keys')) this._enableExtraShortcut()
+ else this._disableExtraShortcut()
+ }
+
+ _enableExtraShortcut() {
+ Utils.addKeybinding('shortcut', SETTINGS, () => this._showOverlay(true))
+ }
+
+ _disableExtraShortcut() {
+ Utils.removeKeybinding('shortcut')
+ }
+
+ _showOverlay(overlayFromShortcut) {
+ //wait for intellihide timeout initialization
+ if (!this._panel.intellihide) {
+ return
+ }
+
+ // Restart the counting if the shortcut is pressed again
+ let hotkey_option = 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 = SETTINGS.get_int('overlay-timeout')
+
+ if (overlayFromShortcut) {
+ timeout = SETTINGS.get_int('shortcut-timeout')
+ }
+
+ // Hide the overlay/dock after the timeout
+ this._timeoutsHandler.add([
+ T2,
+ timeout,
+ () => {
+ if (hotkey_option != 'ALWAYS') {
+ this.taskbar.toggleNumberOverlay(false)
}
- 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());
+ this._panel.intellihide.release(Intellihide.Hold.TEMPORARY)
+ },
+ ])
+ }
- 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);
- }
+ _optionalClickToExit() {
+ this._clickToExitEnabled = false
+ if (SETTINGS.get_boolean('overview-click-to-exit'))
+ this._enableClickToExit()
- this._signalsHandler.add([
- SETTINGS,
- 'changed::isolate-workspaces',
- () => {
- this._panel.panelManager.allPanels.forEach(p => p.taskbar.resetAppIcons());
-
- if (SETTINGS.get_boolean('isolate-workspaces'))
- enable();
- else
- disable();
- }
- ]);
-
- if (SETTINGS.get_boolean('isolate-workspaces'))
- enable();
- }
-
- // Hotkeys
- _activateApp(appIndex, modifiers) {
- let seenApps = {};
- let apps = [];
-
- this.taskbar._getAppIcons().forEach(appIcon => {
- if (!seenApps[appIcon.app] || this.taskbar.allowSplitApps) {
- 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 (SETTINGS.get_boolean('shortcut-previews') && windowCount > 1 &&
- !(modifiers & ~(Clutter.ModifierType.MOD1_MASK | Clutter.ModifierType.SUPER_MASK))) { //ignore the alt (MOD1_MASK) and super key (SUPER_MASK)
- if (this._hotkeyPreviewCycleInfo && this._hotkeyPreviewCycleInfo.appIcon != appIcon) {
- this._endHotkeyPreviewCycle();
- }
-
- if (!this._hotkeyPreviewCycleInfo) {
- this._hotkeyPreviewCycleInfo = {
- appIcon: appIcon,
- currentWindow: appIcon.window,
- keyFocusOutId: appIcon.connect('key-focus-out', () => appIcon.grab_key_focus()),
- capturedEventId: global.stage.connect('captured-event', (actor, e) => {
- if (e.type() == Clutter.EventType.KEY_RELEASE && e.get_key_symbol() == (Clutter.KEY_Super_L || Clutter.Super_L)) {
- this._endHotkeyPreviewCycle(true);
- }
-
- return Clutter.EVENT_PROPAGATE;
- })
- };
-
- appIcon._hotkeysCycle = appIcon.window;
- appIcon.window = null;
- appIcon._previewMenu.open(appIcon, true);
- appIcon.grab_key_focus();
- }
-
- appIcon._previewMenu.focusNext();
- } else {
- // Activate with button = 1, i.e. same as left click
- let button = 1;
- this._endHotkeyPreviewCycle();
- appIcon.activate(button, modifiers, !this.taskbar.allowSplitApps);
- }
- }
- }
-
- _endHotkeyPreviewCycle(focusWindow) {
- if (this._hotkeyPreviewCycleInfo) {
- global.stage.disconnect(this._hotkeyPreviewCycleInfo.capturedEventId);
- this._hotkeyPreviewCycleInfo.appIcon.disconnect(this._hotkeyPreviewCycleInfo.keyFocusOutId);
-
- if (focusWindow) {
- this._hotkeyPreviewCycleInfo.appIcon._previewMenu.activateFocused();
- } else
- this._hotkeyPreviewCycleInfo.appIcon._previewMenu.close()
-
- this._hotkeyPreviewCycleInfo.appIcon.window = this._hotkeyPreviewCycleInfo.currentWindow;
- delete this._hotkeyPreviewCycleInfo.appIcon._hotkeysCycle;
- this._hotkeyPreviewCycleInfo = 0;
- }
- }
-
- _optionalHotKeys() {
- this._hotKeysEnabled = false;
- if (SETTINGS.get_boolean('hot-keys'))
- this._enableHotKeys();
-
- this._signalsHandler.add([
- SETTINGS,
- 'changed::hot-keys',
- () => {
- if (SETTINGS.get_boolean('hot-keys'))
- this._enableHotKeys();
- else
- this._disableHotKeys();
- }
- ]);
- }
-
- _resetHotkeys() {
- this._disableHotKeys();
- this._enableHotKeys();
- }
-
- _enableHotKeys() {
- 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 = SETTINGS.get_string('shortcut-num-keys');
- let bothNumKeys = shortcutNumKeys == 'BOTH';
- let keys = [];
- let prefixModifiers = Clutter.ModifierType.SUPER_MASK
-
- if (SETTINGS.get_string('hotkey-prefix-text') == 'SuperAlt')
- prefixModifiers |= Clutter.ModifierType.MOD1_MASK
-
- 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) {
- let modifiers = prefixModifiers
-
- // for some reason, in gnome-shell >= 40 Clutter.get_current_event() is now empty
- // for keyboard events. Create here the modifiers that are needed in appicon.activate
- modifiers |= (key.indexOf('-shift-') >= 0 ? Clutter.ModifierType.SHIFT_MASK : 0)
- modifiers |= (key.indexOf('-ctrl-') >= 0 ? Clutter.ModifierType.CONTROL_MASK : 0)
-
- for (let i = 0; i < this._numHotkeys; i++) {
- let appNum = i;
-
- Utils.addKeybinding(key + (i + 1), SETTINGS, () => this._activateApp(appNum, modifiers));
- }
- }, this);
-
- this._hotKeysEnabled = true;
-
- if (SETTINGS.get_string('hotkeys-overlay-combo') === 'ALWAYS')
- this.taskbar.toggleNumberOverlay(true);
- }
-
- _disableHotKeys() {
- 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: 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() {
- // Enable extra shortcut
- if (SETTINGS.get_boolean('hot-keys'))
- this._enableExtraShortcut();
-
- this._signalsHandler.add([
- SETTINGS,
- 'changed::hot-keys',
- this._checkHotkeysOptions.bind(this)
- ], [
- SETTINGS,
- 'changed::hotkeys-overlay-combo',
- () => {
- if (SETTINGS.get_boolean('hot-keys') && SETTINGS.get_string('hotkeys-overlay-combo') === 'ALWAYS')
- this.taskbar.toggleNumberOverlay(true);
- else
- this.taskbar.toggleNumberOverlay(false);
- }
- ], [
- SETTINGS,
- 'changed::shortcut-num-keys',
- () => this._resetHotkeys()
- ]);
- }
-
- _checkHotkeysOptions() {
- if (SETTINGS.get_boolean('hot-keys'))
- this._enableExtraShortcut();
- else
- this._disableExtraShortcut();
- }
-
- _enableExtraShortcut() {
- Utils.addKeybinding('shortcut', SETTINGS, () => this._showOverlay(true));
- }
-
- _disableExtraShortcut() {
- Utils.removeKeybinding('shortcut');
- }
-
- _showOverlay(overlayFromShortcut) {
- //wait for intellihide timeout initialization
- if (!this._panel.intellihide) {
- return;
- }
-
- // Restart the counting if the shortcut is pressed again
- let hotkey_option = 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 = SETTINGS.get_int('overlay-timeout');
-
- if (overlayFromShortcut) {
- timeout = SETTINGS.get_int('shortcut-timeout');
- }
-
- // Hide the overlay/dock after the timeout
- this._timeoutsHandler.add([T2, timeout, () => {
- if (hotkey_option != 'ALWAYS') {
- this.taskbar.toggleNumberOverlay(false);
- }
-
- this._panel.intellihide.release(Intellihide.Hold.TEMPORARY);
- }]);
- }
-
- _optionalClickToExit() {
- this._clickToExitEnabled = false;
+ this._signalsHandler.add([
+ SETTINGS,
+ 'changed::overview-click-to-exit',
+ () => {
if (SETTINGS.get_boolean('overview-click-to-exit'))
- this._enableClickToExit();
+ this._enableClickToExit()
+ else this._disableClickToExit()
+ },
+ ])
+ }
- this._signalsHandler.add([
- SETTINGS,
- 'changed::overview-click-to-exit',
- () => {
- if (SETTINGS.get_boolean('overview-click-to-exit'))
- this._enableClickToExit();
- else
- this._disableClickToExit();
- }
- ]);
- }
+ _enableClickToExit() {
+ if (this._clickToExitEnabled) return
- _enableClickToExit() {
- if (this._clickToExitEnabled)
- return;
+ this._signalsHandler.addWithLabel('click-to-exit', [
+ Main.layoutManager.overviewGroup,
+ 'button-release-event',
+ () => {
+ let [x, y] = global.get_pointer()
+ let pickedActor = global.stage.get_actor_at_pos(
+ Clutter.PickMode.REACTIVE,
+ x,
+ y,
+ )
- this._signalsHandler.addWithLabel('click-to-exit', [
- Main.layoutManager.overviewGroup,
- 'button-release-event',
- () => {
- let [x, y] = global.get_pointer();
- let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y);
-
- if (pickedActor) {
- let parent = pickedActor.get_parent();
+ if (pickedActor) {
+ let parent = pickedActor.get_parent()
- if (
- (
- pickedActor.has_style_class_name &&
- pickedActor.has_style_class_name('apps-scroll-view') &&
- !pickedActor.has_style_pseudo_class('first-child')
- ) || (
- parent?.has_style_class_name &&
- parent.has_style_class_name('window-picker')
- ) ||
- Main.overview._overview._controls._searchEntryBin.contains(pickedActor) ||
- pickedActor instanceof WindowPreview
- )
- return Clutter.EVENT_PROPAGATE
- }
+ if (
+ (pickedActor.has_style_class_name &&
+ pickedActor.has_style_class_name('apps-scroll-view') &&
+ !pickedActor.has_style_pseudo_class('first-child')) ||
+ (parent?.has_style_class_name &&
+ parent.has_style_class_name('window-picker')) ||
+ Main.overview._overview._controls._searchEntryBin.contains(
+ pickedActor,
+ ) ||
+ pickedActor instanceof WindowPreview
+ )
+ return Clutter.EVENT_PROPAGATE
+ }
- Main.overview.toggle()
- }
- ]);
+ Main.overview.toggle()
+ },
+ ])
- this._clickToExitEnabled = true;
- }
+ this._clickToExitEnabled = true
+ }
- _disableClickToExit() {
- if (!this._clickToExitEnabled)
- return;
-
- this._signalsHandler.removeWithLabel('click-to-exit')
+ _disableClickToExit() {
+ if (!this._clickToExitEnabled) return
- this._clickToExitEnabled = false;
- }
+ this._signalsHandler.removeWithLabel('click-to-exit')
- _onSwipeBegin() {
- this._swiping = true;
- return true;
- }
+ this._clickToExitEnabled = false
+ }
- _onSwipeEnd() {
- this._timeoutsHandler.add([
- T1,
- 0,
- () => this._swiping = false
- ]);
- return true;
- }
+ _onSwipeBegin() {
+ this._swiping = true
+ return true
+ }
+ _onSwipeEnd() {
+ this._timeoutsHandler.add([T1, 0, () => (this._swiping = false)])
+ return true
+ }
}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..4937228
--- /dev/null
+++ b/package.json
@@ -0,0 +1,13 @@
+{
+ "type": "module",
+ "scripts": {
+ "lint": "prettier 'src/**/*.js' --write && eslint 'src/**/*.js' --fix"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.19.0",
+ "eslint": "^9.19.0",
+ "eslint-config-prettier": "^10.0.1",
+ "globals": "^15.14.0",
+ "prettier": "^3.4.2"
+ }
+}
diff --git a/panel.js b/panel.js
index a0bfdac..f5745fb 100644
--- a/panel.js
+++ b/panel.js
@@ -27,1239 +27,1484 @@
* Some code was also adapted from the upstream Gnome Shell source code.
*/
-import Clutter from 'gi://Clutter';
-import GObject from 'gi://GObject';
-import * as AppIcons from './appIcons.js';
-import * as Utils from './utils.js';
-import * as Taskbar from './taskbar.js';
-import * as TaskbarItemContainer from './taskbar.js';
-import * as Pos from './panelPositions.js';
-import * as PanelSettings from './panelSettings.js';
-import * as PanelStyle from './panelStyle.js';
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
-import * as Dash from 'resource:///org/gnome/shell/ui/dash.js';
-import * as CtrlAltTab from 'resource:///org/gnome/shell/ui/ctrlAltTab.js';
-import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';
-import St from 'gi://St';
-import Meta from 'gi://Meta';
-import Pango from 'gi://Pango';
-import * as DND from 'resource:///org/gnome/shell/ui/dnd.js';
-import Shell from 'gi://Shell';
-import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
-import * as DateMenu from 'resource:///org/gnome/shell/ui/dateMenu.js';
-import * as Volume from 'resource:///org/gnome/shell/ui/status/volume.js';
-import * as Progress from './progress.js';
+import Clutter from 'gi://Clutter'
+import GObject from 'gi://GObject'
+import * as AppIcons from './appIcons.js'
+import * as Utils from './utils.js'
+import * as Taskbar from './taskbar.js'
+import * as TaskbarItemContainer from './taskbar.js'
+import * as Pos from './panelPositions.js'
+import * as PanelSettings from './panelSettings.js'
+import * as PanelStyle from './panelStyle.js'
+import * as Main from 'resource:///org/gnome/shell/ui/main.js'
+import * as Dash from 'resource:///org/gnome/shell/ui/dash.js'
+import * as CtrlAltTab from 'resource:///org/gnome/shell/ui/ctrlAltTab.js'
+import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'
+import St from 'gi://St'
+import Meta from 'gi://Meta'
+import Pango from 'gi://Pango'
+import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'
+import Shell from 'gi://Shell'
+import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'
+import * as DateMenu from 'resource:///org/gnome/shell/ui/dateMenu.js'
+import * as Volume from 'resource:///org/gnome/shell/ui/status/volume.js'
+import * as Progress from './progress.js'
-import * as Intellihide from './intellihide.js';
-import * as Transparency from './transparency.js';
-import {SETTINGS, DESKTOPSETTINGS, PERSISTENTSTORAGE} from './extension.js';
-import {gettext as _, InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js';
+import * as Intellihide from './intellihide.js'
+import * as Transparency from './transparency.js'
+import { SETTINGS, DESKTOPSETTINGS, PERSISTENTSTORAGE } from './extension.js'
+import {
+ gettext as _,
+ InjectionManager,
+} from 'resource:///org/gnome/shell/extensions/extension.js'
-let tracker = Shell.WindowTracker.get_default();
-export const panelBoxes = ['_leftBox', '_centerBox', '_rightBox'];
+let tracker = Shell.WindowTracker.get_default()
+export const panelBoxes = ['_leftBox', '_centerBox', '_rightBox']
//timeout names
-const T2 = 'startIntellihideTimeout';
-const T4 = 'showDesktopTimeout';
-const T5 = 'trackerFocusAppTimeout';
-const T6 = 'scrollPanelDelayTimeout';
-const T7 = 'waitPanelBoxAllocation';
-
-export const Panel = GObject.registerClass({
-}, class Panel extends St.Widget {
+const T2 = 'startIntellihideTimeout'
+const T4 = 'showDesktopTimeout'
+const T5 = 'trackerFocusAppTimeout'
+const T6 = 'scrollPanelDelayTimeout'
+const T7 = 'waitPanelBoxAllocation'
+export const Panel = GObject.registerClass(
+ {},
+ class Panel extends St.Widget {
_init(panelManager, monitor, panelBox, isStandalone) {
- super._init({ layout_manager: new Clutter.BinLayout() });
+ super._init({ layout_manager: new Clutter.BinLayout() })
- this._timeoutsHandler = new Utils.TimeoutsHandler();
- this._signalsHandler = new Utils.GlobalSignalsHandler();
- this._injectionManager = new InjectionManager();
+ this._timeoutsHandler = new Utils.TimeoutsHandler()
+ this._signalsHandler = new Utils.GlobalSignalsHandler()
+ this._injectionManager = new InjectionManager()
- this.panelManager = panelManager;
- this.panelStyle = new PanelStyle.PanelStyle();
+ this.panelManager = panelManager
+ this.panelStyle = new PanelStyle.PanelStyle()
- this.monitor = monitor;
- this.panelBox = panelBox;
+ this.monitor = monitor
+ this.panelBox = panelBox
- // when the original gnome-shell top panel is kept, all panels are "standalone",
- // so in this case use isPrimary to get the panel on the primary dtp monitor, which
- // might be different from the system's primary monitor.
- this.isStandalone = isStandalone;
- this.isPrimary = !isStandalone || (SETTINGS.get_boolean('stockgs-keep-top-panel') &&
- monitor == panelManager.dtpPrimaryMonitor);
+ // when the original gnome-shell top panel is kept, all panels are "standalone",
+ // so in this case use isPrimary to get the panel on the primary dtp monitor, which
+ // might be different from the system's primary monitor.
+ this.isStandalone = isStandalone
+ this.isPrimary =
+ !isStandalone ||
+ (SETTINGS.get_boolean('stockgs-keep-top-panel') &&
+ monitor == panelManager.dtpPrimaryMonitor)
- this._sessionStyle = null;
- this._unmappedButtons = [];
- this._elementGroups = [];
+ this._sessionStyle = null
+ this._unmappedButtons = []
+ this._elementGroups = []
- let systemMenuInfo = Utils.getSystemMenuInfo();
+ let systemMenuInfo = Utils.getSystemMenuInfo()
- if (isStandalone) {
- this.panel = new SecondaryPanel({ name: 'panel', reactive: true });
- this.statusArea = this.panel.statusArea = {};
+ if (isStandalone) {
+ this.panel = new SecondaryPanel({ name: 'panel', reactive: true })
+ this.statusArea = this.panel.statusArea = {}
- //next 3 functions are needed by other extensions to add elements to the secondary panel
- this.panel.addToStatusArea = function(role, indicator, position, box) {
- return Main.panel.addToStatusArea.call(this, role, indicator, position, box);
- };
-
- this.panel._addToPanelBox = function(role, indicator, position, box) {
- Main.panel._addToPanelBox.call(this, role, indicator, position, box);
- };
-
- this.panel._onMenuSet = function(indicator) {
- Main.panel._onMenuSet.call(this, indicator);
- };
-
- this._leftBox = this.panel._leftBox = new St.BoxLayout({ name: 'panelLeft' });
- this._centerBox = this.panel._centerBox = new St.BoxLayout({ name: 'panelCenter' });
- this._rightBox = this.panel._rightBox = new St.BoxLayout({ name: 'panelRight' });
-
- this.menuManager = this.panel.menuManager = new PopupMenu.PopupMenuManager(this.panel);
-
- this._setPanelMenu(systemMenuInfo.name, systemMenuInfo.constructor, this.panel);
- this._setPanelMenu('dateMenu', DateMenu.DateMenuButton, this.panel);
- this._setPanelMenu('activities', Main.panel.statusArea.activities.constructor, this.panel);
-
- this.panel.add_child(this._leftBox);
- this.panel.add_child(this._centerBox);
- this.panel.add_child(this._rightBox);
- } else {
- this.panel = Main.panel;
- this.statusArea = Main.panel.statusArea;
- this.menuManager = Main.panel.menuManager;
-
- panelBoxes.forEach(p => this[p] = Main.panel[p]);
-
- ['activities', systemMenuInfo.name, 'dateMenu'].forEach(b => {
- let container = this.statusArea[b].container;
- let parent = container.get_parent();
- let siblings = parent.get_children();
- let index = siblings.indexOf(container);
-
- container._dtpOriginalParent = parent;
- container._dtpOriginalIndex = index && index == siblings.length - 1 ? -1: index;
- parent ? parent.remove_child(container) : null;
- this.panel.add_child(container);
- });
+ //next 3 functions are needed by other extensions to add elements to the secondary panel
+ this.panel.addToStatusArea = function (role, indicator, position, box) {
+ return Main.panel.addToStatusArea.call(
+ this,
+ role,
+ indicator,
+ position,
+ box,
+ )
}
- // Create a wrapper around the real showAppsIcon in order to add a popupMenu. Most of
- // its behavior is handled by the taskbar, but its positioning is done at the panel level
- this.showAppsIconWrapper = new AppIcons.ShowAppsIconWrapper(this);
- this.panel.add_child(this.showAppsIconWrapper.realShowAppsIcon);
-
- this.panel._delegate = this;
-
- this.add_child(this.panel);
-
- if (Main.panel._onButtonPress || Main.panel._tryDragWindow) {
- this._signalsHandler.add([
- this.panel,
- [
- 'button-press-event',
- 'touch-event'
- ],
- this._onButtonPress.bind(this)
- ]);
+ this.panel._addToPanelBox = function (role, indicator, position, box) {
+ Main.panel._addToPanelBox.call(this, role, indicator, position, box)
}
- if (Main.panel._onKeyPress) {
- this._signalsHandler.add([this.panel, 'key-press-event', Main.panel._onKeyPress.bind(this)]);
+ this.panel._onMenuSet = function (indicator) {
+ Main.panel._onMenuSet.call(this, indicator)
}
- Main.ctrlAltTabManager.addGroup(this, _("Top Bar")+" "+ monitor.index, 'focus-top-bar-symbolic',
- { sortGroup: CtrlAltTab.SortGroup.TOP });
+ this._leftBox = this.panel._leftBox = new St.BoxLayout({
+ name: 'panelLeft',
+ })
+ this._centerBox = this.panel._centerBox = new St.BoxLayout({
+ name: 'panelCenter',
+ })
+ this._rightBox = this.panel._rightBox = new St.BoxLayout({
+ name: 'panelRight',
+ })
+
+ this.menuManager = this.panel.menuManager =
+ new PopupMenu.PopupMenuManager(this.panel)
+
+ this._setPanelMenu(
+ systemMenuInfo.name,
+ systemMenuInfo.constructor,
+ this.panel,
+ )
+ this._setPanelMenu('dateMenu', DateMenu.DateMenuButton, this.panel)
+ this._setPanelMenu(
+ 'activities',
+ Main.panel.statusArea.activities.constructor,
+ this.panel,
+ )
+
+ this.panel.add_child(this._leftBox)
+ this.panel.add_child(this._centerBox)
+ this.panel.add_child(this._rightBox)
+ } else {
+ this.panel = Main.panel
+ this.statusArea = Main.panel.statusArea
+ this.menuManager = Main.panel.menuManager
+
+ panelBoxes.forEach((p) => (this[p] = Main.panel[p]))
+ ;['activities', systemMenuInfo.name, 'dateMenu'].forEach((b) => {
+ let container = this.statusArea[b].container
+ let parent = container.get_parent()
+ let siblings = parent.get_children()
+ let index = siblings.indexOf(container)
+
+ container._dtpOriginalParent = parent
+ container._dtpOriginalIndex =
+ index && index == siblings.length - 1 ? -1 : index
+ parent ? parent.remove_child(container) : null
+ this.panel.add_child(container)
+ })
+ }
+
+ // Create a wrapper around the real showAppsIcon in order to add a popupMenu. Most of
+ // its behavior is handled by the taskbar, but its positioning is done at the panel level
+ this.showAppsIconWrapper = new AppIcons.ShowAppsIconWrapper(this)
+ this.panel.add_child(this.showAppsIconWrapper.realShowAppsIcon)
+
+ this.panel._delegate = this
+
+ this.add_child(this.panel)
+
+ if (Main.panel._onButtonPress || Main.panel._tryDragWindow) {
+ this._signalsHandler.add([
+ this.panel,
+ ['button-press-event', 'touch-event'],
+ this._onButtonPress.bind(this),
+ ])
+ }
+
+ if (Main.panel._onKeyPress) {
+ this._signalsHandler.add([
+ this.panel,
+ '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 () {
- let { name: systemMenuName } = Utils.getSystemMenuInfo();
+ enable() {
+ let { name: systemMenuName } = Utils.getSystemMenuInfo()
- if (this.statusArea[systemMenuName] && this.statusArea[systemMenuName]._volumeOutput) {
- Utils.getIndicators(this.statusArea[systemMenuName]._volumeOutput)._dtpIgnoreScroll = 1;
+ if (
+ this.statusArea[systemMenuName] &&
+ this.statusArea[systemMenuName]._volumeOutput
+ ) {
+ Utils.getIndicators(
+ this.statusArea[systemMenuName]._volumeOutput,
+ )._dtpIgnoreScroll = 1
+ }
+
+ this.geom = this.getGeometry()
+
+ this._setPanelPosition()
+
+ if (!this.isStandalone) {
+ this._injectionManager.overrideMethod(
+ Object.getPrototypeOf(this.panel),
+ 'vfunc_allocate',
+ () => (box) => this._mainPanelAllocate(box),
+ )
+
+ // remove the extra space before the clock when the message-indicator is displayed
+ if (DateMenu.IndicatorPad) {
+ this._injectionManager.overrideMethod(
+ DateMenu.IndicatorPad.prototype,
+ 'vfunc_get_preferred_width',
+ () => () => [0, 0],
+ )
+ this._injectionManager.overrideMethod(
+ DateMenu.IndicatorPad.prototype,
+ 'vfunc_get_preferred_height',
+ () => () => [0, 0],
+ )
}
+ }
- this.geom = this.getGeometry();
+ if (!DateMenu.IndicatorPad && this.statusArea.dateMenu) {
+ //3.36 switched to a size constraint applied on an anonymous child
+ let indicatorPad = this.statusArea.dateMenu
+ .get_first_child()
+ .get_first_child()
- this._setPanelPosition();
+ this._dateMenuIndicatorPadContraints = indicatorPad.get_constraints()
+ indicatorPad.clear_constraints()
+ }
- if (!this.isStandalone) {
- this._injectionManager.overrideMethod(Object.getPrototypeOf(this.panel), 'vfunc_allocate', () => (box) => this._mainPanelAllocate(box));
+ this.menuManager._oldChangeMenu = this.menuManager._changeMenu
+ this.menuManager._changeMenu = (menu) => {
+ if (!SETTINGS.get_boolean('stockgs-panelbtn-click-only')) {
+ this.menuManager._oldChangeMenu(menu)
+ }
+ }
- // remove the extra space before the clock when the message-indicator is displayed
- if (DateMenu.IndicatorPad) {
- this._injectionManager.overrideMethod(DateMenu.IndicatorPad.prototype, 'vfunc_get_preferred_width', () => () => [0,0]);
- this._injectionManager.overrideMethod(DateMenu.IndicatorPad.prototype, 'vfunc_get_preferred_height', () => () => [0,0]);
+ this.dynamicTransparency = new Transparency.DynamicTransparency(this)
+
+ this.taskbar = new Taskbar.Taskbar(this)
+
+ this.panel.add_child(this.taskbar.actor)
+
+ this._setShowDesktopButton(true)
+
+ this._setAllocationMap()
+
+ this.panel.add_style_class_name(
+ 'dashtopanelMainPanel ' + this.getOrientation(),
+ )
+
+ this._timeoutsHandler.add([
+ T2,
+ SETTINGS.get_int('intellihide-enable-start-delay'),
+ () => (this.intellihide = new Intellihide.Intellihide(this)),
+ ])
+
+ this._signalsHandler.add(
+ // this is to catch changes to the theme or window scale factor
+ [
+ Utils.getStageTheme(),
+ 'changed',
+ () => (this._resetGeometry(), this._setShowDesktopButtonStyle()),
+ ],
+ [
+ // sync hover after a popupmenu is closed
+ this.taskbar,
+ 'menu-closed',
+ () => this.panel.sync_hover(),
+ ],
+ [Main.overview, ['showing', 'hiding'], () => this._adjustForOverview()],
+ [
+ Main.overview,
+ 'hidden',
+ () => {
+ if (this.isPrimary) {
+ //reset the primary monitor when exiting the overview
+ this.panelManager.setFocusedMonitor(this.monitor)
}
- }
-
- if (!DateMenu.IndicatorPad && this.statusArea.dateMenu) {
- //3.36 switched to a size constraint applied on an anonymous child
- let indicatorPad = this.statusArea.dateMenu.get_first_child().get_first_child();
-
- this._dateMenuIndicatorPadContraints = indicatorPad.get_constraints();
- indicatorPad.clear_constraints();
- }
-
- this.menuManager._oldChangeMenu = this.menuManager._changeMenu;
- this.menuManager._changeMenu = (menu) => {
- if (!SETTINGS.get_boolean('stockgs-panelbtn-click-only')) {
- this.menuManager._oldChangeMenu(menu);
+ },
+ ],
+ [
+ this.statusArea.activities,
+ 'captured-event',
+ (actor, e) => {
+ if (
+ e.type() == Clutter.EventType.BUTTON_PRESS ||
+ e.type() == Clutter.EventType.TOUCH_BEGIN
+ ) {
+ //temporarily use as primary the monitor on which the activities btn was clicked
+ this.panelManager.setFocusedMonitor(this.monitor)
}
- };
+ },
+ ],
+ [
+ this._centerBox,
+ 'child-added',
+ () => this._onBoxActorAdded(this._centerBox),
+ ],
+ [
+ this._rightBox,
+ 'child-added',
+ () => this._onBoxActorAdded(this._rightBox),
+ ],
+ [this.panel, 'scroll-event', this._onPanelMouseScroll.bind(this)],
+ [Main.layoutManager, 'startup-complete', () => this._resetGeometry()],
+ )
- this.dynamicTransparency = new Transparency.DynamicTransparency(this);
+ this._bindSettingsChanges()
- this.taskbar = new Taskbar.Taskbar(this);
+ this.panelStyle.enable(this)
- this.panel.add_child(this.taskbar.actor);
-
- this._setShowDesktopButton(true);
-
- this._setAllocationMap();
-
- this.panel.add_style_class_name('dashtopanelMainPanel ' + this.getOrientation());
-
- this._timeoutsHandler.add([T2, SETTINGS.get_int('intellihide-enable-start-delay'), () => this.intellihide = new Intellihide.Intellihide(this)]);
-
- this._signalsHandler.add(
- // this is to catch changes to the theme or window scale factor
- [
- Utils.getStageTheme(),
- 'changed',
- () => (this._resetGeometry(), this._setShowDesktopButtonStyle()),
- ],
- [
- // sync hover after a popupmenu is closed
- this.taskbar,
- 'menu-closed',
- () => this.panel.sync_hover()
- ],
- [
- Main.overview,
- [
- 'showing',
- 'hiding'
- ],
- () => this._adjustForOverview()
- ],
- [
- Main.overview,
- 'hidden',
- () => {
- if (this.isPrimary) {
- //reset the primary monitor when exiting the overview
- this.panelManager.setFocusedMonitor(this.monitor);
- }
- }
- ],
- [
- this.statusArea.activities,
- 'captured-event',
- (actor, e) => {
- if (e.type() == Clutter.EventType.BUTTON_PRESS || e.type() == Clutter.EventType.TOUCH_BEGIN) {
- //temporarily use as primary the monitor on which the activities btn was clicked
- this.panelManager.setFocusedMonitor(this.monitor);
- }
- }
- ],
- [
- this._centerBox,
- 'child-added',
- () => this._onBoxActorAdded(this._centerBox)
- ],
- [
- this._rightBox,
- 'child-added',
- () => this._onBoxActorAdded(this._rightBox)
- ],
- [
- this.panel,
- 'scroll-event',
- this._onPanelMouseScroll.bind(this)
- ],
- [
- Main.layoutManager,
- 'startup-complete',
- () => this._resetGeometry()
- ]
- );
-
- this._bindSettingsChanges();
-
- this.panelStyle.enable(this);
-
- if (this.checkIfVertical()) {
- this._signalsHandler.add([
- this.panelBox,
- 'notify::visible',
- () => {
- if (this.panelBox.visible) {
- this._refreshVerticalAlloc();
- }
- }
- ]);
-
- if (this.statusArea.dateMenu) {
- this._formatVerticalClock();
-
- this._signalsHandler.add([
- this.statusArea.dateMenu._clock,
- 'notify::clock',
- () => this._formatVerticalClock()
- ]);
+ if (this.checkIfVertical()) {
+ this._signalsHandler.add([
+ this.panelBox,
+ 'notify::visible',
+ () => {
+ if (this.panelBox.visible) {
+ this._refreshVerticalAlloc()
}
+ },
+ ])
+
+ if (this.statusArea.dateMenu) {
+ this._formatVerticalClock()
+
+ this._signalsHandler.add([
+ this.statusArea.dateMenu._clock,
+ 'notify::clock',
+ () => this._formatVerticalClock(),
+ ])
}
+ }
- // Since we are usually visible but not usually changing, make sure
- // most repaint requests don't actually require us to repaint anything.
- // This saves significant CPU when repainting the screen.
- this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
+ // Since we are usually visible but not usually changing, make sure
+ // most repaint requests don't actually require us to repaint anything.
+ // This saves significant CPU when repainting the screen.
+ this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS)
- this._initProgressManager();
+ this._initProgressManager()
}
disable() {
- this.panelStyle.disable();
+ this.panelStyle.disable()
- this._timeoutsHandler.destroy();
- this._signalsHandler.destroy();
+ this._timeoutsHandler.destroy()
+ this._signalsHandler.destroy()
- this.panel.remove_child(this.taskbar.actor);
+ this.panel.remove_child(this.taskbar.actor)
- if (this.intellihide) {
- this.intellihide.destroy();
+ if (this.intellihide) {
+ this.intellihide.destroy()
+ }
+
+ this.dynamicTransparency.destroy()
+
+ this.progressManager.destroy()
+
+ this.taskbar.destroy()
+ this.showAppsIconWrapper.destroy()
+
+ this.menuManager._changeMenu = this.menuManager._oldChangeMenu
+
+ this._unmappedButtons.forEach((a) => this._disconnectVisibleId(a))
+
+ if (this.statusArea.dateMenu) {
+ this.statusArea.dateMenu._clockDisplay.text =
+ this.statusArea.dateMenu._clock.clock
+ this.statusArea.dateMenu._clockDisplay.clutter_text.set_width(-1)
+
+ if (this._dateMenuIndicatorPadContraints) {
+ let indicatorPad = this.statusArea.dateMenu
+ .get_first_child()
+ .get_first_child()
+
+ this._dateMenuIndicatorPadContraints.forEach((c) =>
+ indicatorPad.add_constraint(c),
+ )
+ }
+ }
+
+ this._setVertical(this.panel, false)
+ this._setVertical(this._centerBox, false)
+ this._setVertical(this._rightBox, false)
+
+ let { name: systemMenuName } = Utils.getSystemMenuInfo()
+
+ if (!this.isStandalone) {
+ ;['vertical', 'horizontal', 'dashtopanelMainPanel'].forEach((c) =>
+ this.panel.remove_style_class_name(c),
+ )
+
+ if (!Main.sessionMode.isLocked) {
+ ;['activities', systemMenuName, 'dateMenu'].forEach((b) => {
+ let container = this.statusArea[b].container
+ let originalParent = container._dtpOriginalParent
+
+ this.panel.remove_child(container)
+
+ originalParent &&
+ originalParent.insert_child_at_index(
+ container,
+ Math.min(
+ container._dtpOriginalIndex,
+ originalParent.get_children().length - 1,
+ ),
+ )
+
+ delete container._dtpOriginalParent
+ delete container._dtpOriginalIndex
+ })
}
- this.dynamicTransparency.destroy();
+ this._setShowDesktopButton(false)
- this.progressManager.destroy();
+ delete Utils.getIndicators(
+ this.statusArea[systemMenuName]._volumeOutput,
+ )._dtpIgnoreScroll
- this.taskbar.destroy();
- this.showAppsIconWrapper.destroy();
+ this._injectionManager.clear()
- this.menuManager._changeMenu = this.menuManager._oldChangeMenu;
+ this.panel._delegate = this.panel
+ } else {
+ this._removePanelMenu('dateMenu')
+ this._removePanelMenu(systemMenuName)
+ this._removePanelMenu('activities')
+ }
- this._unmappedButtons.forEach(a => this._disconnectVisibleId(a));
-
- if (this.statusArea.dateMenu) {
- this.statusArea.dateMenu._clockDisplay.text = this.statusArea.dateMenu._clock.clock;
- this.statusArea.dateMenu._clockDisplay.clutter_text.set_width(-1);
-
- if (this._dateMenuIndicatorPadContraints) {
- let indicatorPad = this.statusArea.dateMenu.get_first_child().get_first_child();
-
- this._dateMenuIndicatorPadContraints.forEach(c => indicatorPad.add_constraint(c));
- }
- }
-
- this._setVertical(this.panel, false);
- this._setVertical(this._centerBox, false);
- this._setVertical(this._rightBox, false);
-
- let { name: systemMenuName } = Utils.getSystemMenuInfo();
-
- if (!this.isStandalone) {
- ['vertical', 'horizontal', 'dashtopanelMainPanel'].forEach(c => this.panel.remove_style_class_name(c));
-
- if (!Main.sessionMode.isLocked) {
- ['activities', systemMenuName, 'dateMenu'].forEach(b => {
- let container = this.statusArea[b].container;
- let originalParent = container._dtpOriginalParent;
-
- this.panel.remove_child(container);
-
- originalParent && originalParent.insert_child_at_index(
- container,
- Math.min(container._dtpOriginalIndex, originalParent.get_children().length - 1)
- );
-
- delete container._dtpOriginalParent;
- delete container._dtpOriginalIndex;
- });
- }
-
- this._setShowDesktopButton(false);
-
- delete Utils.getIndicators(this.statusArea[systemMenuName]._volumeOutput)._dtpIgnoreScroll;
-
- this._injectionManager.clear();
-
- this.panel._delegate = this.panel;
- } else {
- this._removePanelMenu('dateMenu');
- this._removePanelMenu(systemMenuName);
- this._removePanelMenu('activities');
- }
-
- Main.ctrlAltTabManager.removeGroup(this);
+ Main.ctrlAltTabManager.removeGroup(this)
}
getPosition() {
- let position = PanelSettings.getPanelPosition(SETTINGS, this.monitor.index);
+ let position = PanelSettings.getPanelPosition(
+ SETTINGS,
+ this.monitor.index,
+ )
- if (position == Pos.TOP) {
- return St.Side.TOP;
- } else if (position == Pos.RIGHT) {
- return St.Side.RIGHT;
- } else if (position == Pos.BOTTOM) {
- return St.Side.BOTTOM;
- }
+ if (position == Pos.TOP) {
+ return St.Side.TOP
+ } else if (position == Pos.RIGHT) {
+ return St.Side.RIGHT
+ } else if (position == Pos.BOTTOM) {
+ return St.Side.BOTTOM
+ }
- return St.Side.LEFT;
+ return St.Side.LEFT
}
checkIfVertical() {
- let position = this.getPosition();
+ let position = this.getPosition()
- return (position == St.Side.LEFT || position == St.Side.RIGHT);
+ return position == St.Side.LEFT || position == St.Side.RIGHT
}
getOrientation() {
- return (this.checkIfVertical() ? 'vertical' : 'horizontal');
+ return this.checkIfVertical() ? 'vertical' : 'horizontal'
}
updateElementPositions() {
- let panelPositions = this.panelManager.panelsElementPositions[this.monitor.index] || Pos.defaults;
+ let panelPositions =
+ this.panelManager.panelsElementPositions[this.monitor.index] ||
+ Pos.defaults
- this._updateGroupedElements(panelPositions);
+ this._updateGroupedElements(panelPositions)
- this.panel.hide();
- this.panel.show();
+ this.panel.hide()
+ this.panel.show()
}
_updateGroupedElements(panelPositions) {
- let previousPosition = 0;
- let previousCenteredPosition = 0;
- let currentGroup = -1;
+ let previousPosition = 0
+ let previousCenteredPosition = 0
+ let currentGroup = -1
- this._elementGroups = [];
+ this._elementGroups = []
- panelPositions.forEach(pos => {
- let allocationMap = this.allocationMap[pos.element];
+ panelPositions.forEach((pos) => {
+ let allocationMap = this.allocationMap[pos.element]
- if (allocationMap.actor) {
- allocationMap.actor.visible = pos.visible;
+ if (allocationMap.actor) {
+ allocationMap.actor.visible = pos.visible
- if (!pos.visible) {
- return;
- }
+ if (!pos.visible) {
+ return
+ }
- let currentPosition = pos.position;
- let isCentered = Pos.checkIfCentered(currentPosition);
+ let currentPosition = pos.position
+ let isCentered = Pos.checkIfCentered(currentPosition)
- if (currentPosition == Pos.STACKED_TL && previousPosition == Pos.STACKED_BR) {
- currentPosition = Pos.STACKED_BR;
- }
+ if (
+ currentPosition == Pos.STACKED_TL &&
+ previousPosition == Pos.STACKED_BR
+ ) {
+ currentPosition = Pos.STACKED_BR
+ }
- if (!previousPosition ||
- (previousPosition == Pos.STACKED_TL && currentPosition != Pos.STACKED_TL) ||
- (previousPosition != Pos.STACKED_BR && currentPosition == Pos.STACKED_BR) ||
- (isCentered && previousPosition != currentPosition && previousPosition != Pos.STACKED_BR)) {
- this._elementGroups[++currentGroup] = { elements: [], index: this._elementGroups.length, expandableIndex: -1 };
- previousCenteredPosition = 0;
- }
-
- if (pos.element == Pos.TASKBAR) {
- this._elementGroups[currentGroup].expandableIndex = this._elementGroups[currentGroup].elements.length;
- }
-
- if (isCentered && !this._elementGroups[currentGroup].isCentered) {
- this._elementGroups[currentGroup].isCentered = 1;
- previousCenteredPosition = currentPosition;
- }
-
- this._elementGroups[currentGroup].position = previousCenteredPosition || currentPosition;
- this._elementGroups[currentGroup].elements.push(allocationMap);
-
- allocationMap.position = currentPosition;
- previousPosition = currentPosition;
+ if (
+ !previousPosition ||
+ (previousPosition == Pos.STACKED_TL &&
+ currentPosition != Pos.STACKED_TL) ||
+ (previousPosition != Pos.STACKED_BR &&
+ currentPosition == Pos.STACKED_BR) ||
+ (isCentered &&
+ previousPosition != currentPosition &&
+ previousPosition != Pos.STACKED_BR)
+ ) {
+ this._elementGroups[++currentGroup] = {
+ elements: [],
+ index: this._elementGroups.length,
+ expandableIndex: -1,
}
- });
+ previousCenteredPosition = 0
+ }
+
+ if (pos.element == Pos.TASKBAR) {
+ this._elementGroups[currentGroup].expandableIndex =
+ this._elementGroups[currentGroup].elements.length
+ }
+
+ if (isCentered && !this._elementGroups[currentGroup].isCentered) {
+ this._elementGroups[currentGroup].isCentered = 1
+ previousCenteredPosition = currentPosition
+ }
+
+ this._elementGroups[currentGroup].position =
+ previousCenteredPosition || currentPosition
+ this._elementGroups[currentGroup].elements.push(allocationMap)
+
+ allocationMap.position = currentPosition
+ previousPosition = currentPosition
+ }
+ })
}
_bindSettingsChanges() {
- let isVertical = this.checkIfVertical();
+ let isVertical = this.checkIfVertical()
- this._signalsHandler.add(
- [
- SETTINGS,
- [
- 'changed::panel-sizes',
- 'changed::appicon-margin-todesktop',
- 'changed::appicon-margin-toscreenborder',
- 'changed::group-apps'
- ],
- () => this._resetGeometry()
- ],
- [
- SETTINGS,
- [
- 'changed::appicon-margin',
- 'changed::appicon-padding'
- ],
- () => this.taskbar.resetAppIcons()
- ],
- [
- SETTINGS,
- [
- 'changed::showdesktop-button-width',
- 'changed::trans-use-custom-bg',
- 'changed::desktop-line-use-custom-color',
- 'changed::desktop-line-custom-color',
- 'changed::trans-bg-color'
- ],
- () => this._setShowDesktopButtonStyle()
- ],
- [
- DESKTOPSETTINGS,
- 'changed::clock-format',
- () => {
- this._clockFormat = null;
+ this._signalsHandler.add(
+ [
+ SETTINGS,
+ [
+ 'changed::panel-sizes',
+ 'changed::appicon-margin-todesktop',
+ 'changed::appicon-margin-toscreenborder',
+ 'changed::group-apps',
+ ],
+ () => this._resetGeometry(),
+ ],
+ [
+ SETTINGS,
+ ['changed::appicon-margin', 'changed::appicon-padding'],
+ () => this.taskbar.resetAppIcons(),
+ ],
+ [
+ SETTINGS,
+ [
+ 'changed::showdesktop-button-width',
+ 'changed::trans-use-custom-bg',
+ 'changed::desktop-line-use-custom-color',
+ 'changed::desktop-line-custom-color',
+ 'changed::trans-bg-color',
+ ],
+ () => this._setShowDesktopButtonStyle(),
+ ],
+ [
+ DESKTOPSETTINGS,
+ 'changed::clock-format',
+ () => {
+ this._clockFormat = null
- if (isVertical) {
- this._formatVerticalClock();
- }
- }
- ],
- [
- SETTINGS,
- 'changed::progress-show-bar',
- () => this._initProgressManager()
- ],
- [
- SETTINGS,
- 'changed::progress-show-count',
- () => this._initProgressManager()
- ]
- );
+ if (isVertical) {
+ this._formatVerticalClock()
+ }
+ },
+ ],
+ [
+ SETTINGS,
+ 'changed::progress-show-bar',
+ () => this._initProgressManager(),
+ ],
+ [
+ SETTINGS,
+ 'changed::progress-show-count',
+ () => this._initProgressManager(),
+ ],
+ )
- if (isVertical) {
- this._signalsHandler.add([SETTINGS, 'changed::group-apps-label-max-width', () => this._resetGeometry()]);
- }
+ if (isVertical) {
+ this._signalsHandler.add([
+ SETTINGS,
+ 'changed::group-apps-label-max-width',
+ () => this._resetGeometry(),
+ ])
+ }
}
_setPanelMenu(propName, constr, container) {
- if (!this.statusArea[propName]) {
- this.statusArea[propName] = this._getPanelMenu(propName, constr);
- this.menuManager.addMenu(this.statusArea[propName].menu);
- container.insert_child_at_index(this.statusArea[propName].container, 0);
- }
+ if (!this.statusArea[propName]) {
+ this.statusArea[propName] = this._getPanelMenu(propName, constr)
+ this.menuManager.addMenu(this.statusArea[propName].menu)
+ container.insert_child_at_index(this.statusArea[propName].container, 0)
+ }
}
_removePanelMenu(propName) {
- if (this.statusArea[propName]) {
- let parent = this.statusArea[propName].container.get_parent();
+ if (this.statusArea[propName]) {
+ let parent = this.statusArea[propName].container.get_parent()
- if (parent) {
- parent.remove_child(this.statusArea[propName].container);
- }
-
- //calling this.statusArea[propName].destroy(); is buggy for now, gnome-shell never
- //destroys those panel menus...
- //since we can't destroy the menu (hence properly disconnect its signals), let's
- //store it so the next time a panel needs one of its kind, we can reuse it instead
- //of creating a new one
- let panelMenu = this.statusArea[propName];
-
- this.menuManager.removeMenu(panelMenu.menu);
- PERSISTENTSTORAGE[propName].push(panelMenu);
- this.statusArea[propName] = null;
+ if (parent) {
+ parent.remove_child(this.statusArea[propName].container)
}
+
+ //calling this.statusArea[propName].destroy(); is buggy for now, gnome-shell never
+ //destroys those panel menus...
+ //since we can't destroy the menu (hence properly disconnect its signals), let's
+ //store it so the next time a panel needs one of its kind, we can reuse it instead
+ //of creating a new one
+ let panelMenu = this.statusArea[propName]
+
+ this.menuManager.removeMenu(panelMenu.menu)
+ PERSISTENTSTORAGE[propName].push(panelMenu)
+ this.statusArea[propName] = null
+ }
}
_getPanelMenu(propName, constr) {
- PERSISTENTSTORAGE[propName] = PERSISTENTSTORAGE[propName] || [];
+ PERSISTENTSTORAGE[propName] = PERSISTENTSTORAGE[propName] || []
- if (!PERSISTENTSTORAGE[propName].length) {
- PERSISTENTSTORAGE[propName].push(new constr());
- }
+ if (!PERSISTENTSTORAGE[propName].length) {
+ PERSISTENTSTORAGE[propName].push(new constr())
+ }
- return PERSISTENTSTORAGE[propName].pop();
+ return PERSISTENTSTORAGE[propName].pop()
}
_adjustForOverview() {
- let isFocusedMonitor = this.panelManager.checkIfFocusedMonitor(this.monitor);
- let isOverview = !!Main.overview.visibleTarget;
- let isOverviewFocusedMonitor = isOverview && isFocusedMonitor;
- let isShown = !isOverview || isOverviewFocusedMonitor;
- let actorData = Utils.getTrackedActorData(this.panelBox)
+ let isFocusedMonitor = this.panelManager.checkIfFocusedMonitor(
+ this.monitor,
+ )
+ let isOverview = !!Main.overview.visibleTarget
+ let isOverviewFocusedMonitor = isOverview && isFocusedMonitor
+ let isShown = !isOverview || isOverviewFocusedMonitor
+ let actorData = Utils.getTrackedActorData(this.panelBox)
- // prevent the "chrome" to update the panelbox visibility while in overview
- actorData.trackFullscreen = !isOverview
+ // prevent the "chrome" to update the panelbox visibility while in overview
+ actorData.trackFullscreen = !isOverview
- this.panelBox[isShown ? 'show' : 'hide']();
+ this.panelBox[isShown ? 'show' : 'hide']()
}
_resetGeometry() {
- this.geom = this.getGeometry();
- this._setPanelPosition();
- this.taskbar.resetAppIcons(true);
- this.dynamicTransparency.updateExternalStyle();
+ this.geom = this.getGeometry()
+ this._setPanelPosition()
+ this.taskbar.resetAppIcons(true)
+ this.dynamicTransparency.updateExternalStyle()
- if (this.intellihide && this.intellihide.enabled) {
- this.intellihide.reset();
- }
+ if (this.intellihide && this.intellihide.enabled) {
+ this.intellihide.reset()
+ }
- if (this.checkIfVertical()) {
- this.showAppsIconWrapper.realShowAppsIcon.toggleButton.set_width(this.geom.w);
- this._refreshVerticalAlloc();
- }
+ if (this.checkIfVertical()) {
+ this.showAppsIconWrapper.realShowAppsIcon.toggleButton.set_width(
+ this.geom.w,
+ )
+ this._refreshVerticalAlloc()
+ }
}
getGeometry() {
- let scaleFactor = Utils.getScaleFactor();
- let panelBoxTheme = this.panelBox.get_theme_node();
- let lrPadding = panelBoxTheme.get_padding(St.Side.RIGHT) + panelBoxTheme.get_padding(St.Side.LEFT);
- let topPadding = panelBoxTheme.get_padding(St.Side.TOP);
- let tbPadding = topPadding + panelBoxTheme.get_padding(St.Side.BOTTOM);
- let position = this.getPosition();
- let length = PanelSettings.getPanelLength(SETTINGS, this.monitor.index) / 100;
- let anchor = PanelSettings.getPanelAnchor(SETTINGS, this.monitor.index);
- let anchorPlaceOnMonitor = 0;
- let gsTopPanelOffset = 0;
- let x = 0, y = 0;
- let w = 0, h = 0;
+ let scaleFactor = Utils.getScaleFactor()
+ let panelBoxTheme = this.panelBox.get_theme_node()
+ let lrPadding =
+ panelBoxTheme.get_padding(St.Side.RIGHT) +
+ panelBoxTheme.get_padding(St.Side.LEFT)
+ let topPadding = panelBoxTheme.get_padding(St.Side.TOP)
+ let tbPadding = topPadding + panelBoxTheme.get_padding(St.Side.BOTTOM)
+ let position = this.getPosition()
+ let length =
+ PanelSettings.getPanelLength(SETTINGS, this.monitor.index) / 100
+ let anchor = PanelSettings.getPanelAnchor(SETTINGS, this.monitor.index)
+ let anchorPlaceOnMonitor = 0
+ let gsTopPanelOffset = 0
+ let x = 0,
+ y = 0
+ let w = 0,
+ h = 0
- const panelSize = PanelSettings.getPanelSize(SETTINGS, this.monitor.index) + SETTINGS.get_int('appicon-margin-todesktop') + SETTINGS.get_int('appicon-margin-toscreenborder');
- this.dtpSize = panelSize * scaleFactor;
+ const panelSize =
+ PanelSettings.getPanelSize(SETTINGS, this.monitor.index) +
+ SETTINGS.get_int('appicon-margin-todesktop') +
+ SETTINGS.get_int('appicon-margin-toscreenborder')
+ this.dtpSize = panelSize * scaleFactor
- if (SETTINGS.get_boolean('stockgs-keep-top-panel') && Main.layoutManager.primaryMonitor == this.monitor) {
- gsTopPanelOffset = Main.layoutManager.panelBox.height - topPadding;
+ if (
+ SETTINGS.get_boolean('stockgs-keep-top-panel') &&
+ Main.layoutManager.primaryMonitor == this.monitor
+ ) {
+ gsTopPanelOffset = Main.layoutManager.panelBox.height - topPadding
+ }
+
+ if (this.checkIfVertical()) {
+ if (!SETTINGS.get_boolean('group-apps')) {
+ // add window title width and side padding of _dtpIconContainer when vertical
+ this.dtpSize +=
+ SETTINGS.get_int('group-apps-label-max-width') +
+ (AppIcons.DEFAULT_PADDING_SIZE * 2) / scaleFactor
}
- if (this.checkIfVertical()) {
- if (!SETTINGS.get_boolean('group-apps')) {
- // add window title width and side padding of _dtpIconContainer when vertical
- this.dtpSize += SETTINGS.get_int('group-apps-label-max-width') + AppIcons.DEFAULT_PADDING_SIZE * 2 / scaleFactor;
- }
+ ;(this.sizeFunc = 'get_preferred_height'),
+ (this.fixedCoord = { c1: 'x1', c2: 'x2' })
+ this.varCoord = { c1: 'y1', c2: 'y2' }
- this.sizeFunc = 'get_preferred_height',
- this.fixedCoord = { c1: 'x1', c2: 'x2' }
- this.varCoord = { c1: 'y1', c2: 'y2' };
+ w = this.dtpSize
+ h = this.monitor.height * length - tbPadding - gsTopPanelOffset
+ } else {
+ this.sizeFunc = 'get_preferred_width'
+ this.fixedCoord = { c1: 'y1', c2: 'y2' }
+ this.varCoord = { c1: 'x1', c2: 'x2' }
- w = this.dtpSize;
- h = this.monitor.height * length - tbPadding - gsTopPanelOffset;
+ w = this.monitor.width * length - lrPadding
+ h = this.dtpSize
+ }
+
+ if (position == St.Side.TOP || position == St.Side.LEFT) {
+ x = this.monitor.x
+ y = this.monitor.y + gsTopPanelOffset
+ } else if (position == St.Side.RIGHT) {
+ x = this.monitor.x + this.monitor.width - this.dtpSize - lrPadding
+ y = this.monitor.y + gsTopPanelOffset
+ } else {
+ //BOTTOM
+ x = this.monitor.x
+ y = this.monitor.y + this.monitor.height - this.dtpSize - tbPadding
+ }
+
+ if (this.checkIfVertical()) {
+ let viewHeight = this.monitor.height - gsTopPanelOffset
+
+ if (anchor === Pos.MIDDLE) {
+ anchorPlaceOnMonitor = (viewHeight - h) / 2
+ } else if (anchor === Pos.END) {
+ anchorPlaceOnMonitor = viewHeight - h
} else {
- this.sizeFunc = 'get_preferred_width';
- this.fixedCoord = { c1: 'y1', c2: 'y2' };
- this.varCoord = { c1: 'x1', c2: 'x2' };
-
- w = this.monitor.width * length - lrPadding;
- h = this.dtpSize;
+ // Pos.START
+ anchorPlaceOnMonitor = 0
}
-
- if (position == St.Side.TOP || position == St.Side.LEFT) {
- x = this.monitor.x;
- y = this.monitor.y + gsTopPanelOffset;
- } else if (position == St.Side.RIGHT) {
- x = this.monitor.x + this.monitor.width - this.dtpSize - lrPadding;
- y = this.monitor.y + gsTopPanelOffset;
- } else { //BOTTOM
- x = this.monitor.x;
- y = this.monitor.y + this.monitor.height - this.dtpSize - tbPadding;
- }
-
- if (this.checkIfVertical()) {
- let viewHeight = this.monitor.height - gsTopPanelOffset;
-
- if (anchor === Pos.MIDDLE) {
- anchorPlaceOnMonitor = (viewHeight - h) / 2;
- } else if (anchor === Pos.END) {
- anchorPlaceOnMonitor = viewHeight - h;
- } else { // Pos.START
- anchorPlaceOnMonitor = 0;
- }
- y = y + anchorPlaceOnMonitor;
+ y = y + anchorPlaceOnMonitor
+ } else {
+ if (anchor === Pos.MIDDLE) {
+ anchorPlaceOnMonitor = (this.monitor.width - w) / 2
+ } else if (anchor === Pos.END) {
+ anchorPlaceOnMonitor = this.monitor.width - w
} else {
- if (anchor === Pos.MIDDLE) {
- anchorPlaceOnMonitor = (this.monitor.width - w) / 2;
- } else if (anchor === Pos.END) {
- anchorPlaceOnMonitor = this.monitor.width - w;
- } else { // Pos.START
- anchorPlaceOnMonitor = 0;
- }
- x = x + anchorPlaceOnMonitor;
+ // Pos.START
+ anchorPlaceOnMonitor = 0
}
+ x = x + anchorPlaceOnMonitor
+ }
- return {
- x, y,
- w, h,
- lrPadding,
- tbPadding,
- position
- };
+ return {
+ x,
+ y,
+ w,
+ h,
+ lrPadding,
+ tbPadding,
+ position,
+ }
}
_setAllocationMap() {
- this.allocationMap = {};
- let setMap = (name, actor) => this.allocationMap[name] = {
- actor: actor,
- box: new Clutter.ActorBox()
- };
+ this.allocationMap = {}
+ let setMap = (name, actor) =>
+ (this.allocationMap[name] = {
+ actor: actor,
+ box: new Clutter.ActorBox(),
+ })
- setMap(Pos.SHOW_APPS_BTN, this.showAppsIconWrapper.realShowAppsIcon);
- setMap(Pos.ACTIVITIES_BTN, this.statusArea.activities ? this.statusArea.activities.container : 0);
- setMap(Pos.LEFT_BOX, this._leftBox);
- setMap(Pos.TASKBAR, this.taskbar.actor);
- setMap(Pos.CENTER_BOX, this._centerBox);
- setMap(Pos.DATE_MENU, this.statusArea.dateMenu.container);
- setMap(Pos.SYSTEM_MENU, this.statusArea[Utils.getSystemMenuInfo().name].container);
- setMap(Pos.RIGHT_BOX, this._rightBox);
- setMap(Pos.DESKTOP_BTN, this._showDesktopButton);
+ setMap(Pos.SHOW_APPS_BTN, this.showAppsIconWrapper.realShowAppsIcon)
+ setMap(
+ Pos.ACTIVITIES_BTN,
+ this.statusArea.activities ? this.statusArea.activities.container : 0,
+ )
+ setMap(Pos.LEFT_BOX, this._leftBox)
+ setMap(Pos.TASKBAR, this.taskbar.actor)
+ setMap(Pos.CENTER_BOX, this._centerBox)
+ setMap(Pos.DATE_MENU, this.statusArea.dateMenu.container)
+ setMap(
+ Pos.SYSTEM_MENU,
+ this.statusArea[Utils.getSystemMenuInfo().name].container,
+ )
+ setMap(Pos.RIGHT_BOX, this._rightBox)
+ setMap(Pos.DESKTOP_BTN, this._showDesktopButton)
}
_mainPanelAllocate(box) {
- this.panel.set_allocation(box);
+ this.panel.set_allocation(box)
}
vfunc_allocate(box) {
- this.set_allocation(box);
+ this.set_allocation(box)
- let fixed = 0;
- let centeredMonitorGroup;
- let panelAlloc = new Clutter.ActorBox({ x1: 0, y1: 0, x2: this.geom.w, y2: this.geom.h });
- let assignGroupSize = (group, update) => {
- group.size = 0;
- group.tlOffset = 0;
- group.brOffset = 0;
+ let fixed = 0
+ let centeredMonitorGroup
+ let panelAlloc = new Clutter.ActorBox({
+ x1: 0,
+ y1: 0,
+ x2: this.geom.w,
+ y2: this.geom.h,
+ })
+ let assignGroupSize = (group, update) => {
+ group.size = 0
+ group.tlOffset = 0
+ group.brOffset = 0
- group.elements.forEach(element => {
- if (!update) {
- element.box[this.fixedCoord.c1] = panelAlloc[this.fixedCoord.c1];
- element.box[this.fixedCoord.c2] = panelAlloc[this.fixedCoord.c2];
- element.natSize = element.actor[this.sizeFunc](-1)[1];
- }
+ group.elements.forEach((element) => {
+ if (!update) {
+ element.box[this.fixedCoord.c1] = panelAlloc[this.fixedCoord.c1]
+ element.box[this.fixedCoord.c2] = panelAlloc[this.fixedCoord.c2]
+ element.natSize = element.actor[this.sizeFunc](-1)[1]
+ }
- if (!group.isCentered || Pos.checkIfCentered(element.position)) {
- group.size += element.natSize;
- } else if (element.position == Pos.STACKED_TL) {
- group.tlOffset += element.natSize;
- } else { // Pos.STACKED_BR
- group.brOffset += element.natSize;
- }
- });
+ if (!group.isCentered || Pos.checkIfCentered(element.position)) {
+ group.size += element.natSize
+ } else if (element.position == Pos.STACKED_TL) {
+ group.tlOffset += element.natSize
+ } else {
+ // Pos.STACKED_BR
+ group.brOffset += element.natSize
+ }
+ })
- if (group.isCentered) {
- group.size += Math.max(group.tlOffset, group.brOffset) * 2;
- group.tlOffset = Math.max(group.tlOffset - group.brOffset, 0);
+ if (group.isCentered) {
+ group.size += Math.max(group.tlOffset, group.brOffset) * 2
+ group.tlOffset = Math.max(group.tlOffset - group.brOffset, 0)
+ }
+ }
+ let allocateGroup = (group, tlLimit, brLimit) => {
+ let startPosition = tlLimit
+ let currentPosition = 0
+
+ if (group.expandableIndex >= 0) {
+ let availableSize = brLimit - tlLimit
+ let expandable = group.elements[group.expandableIndex]
+ let i = 0
+ let l = this._elementGroups.length
+ let tlSize = 0
+ let brSize = 0
+
+ if (
+ centeredMonitorGroup &&
+ (centeredMonitorGroup != group ||
+ expandable.position != Pos.CENTERED_MONITOR)
+ ) {
+ if (
+ centeredMonitorGroup.index < group.index ||
+ (centeredMonitorGroup == group &&
+ expandable.position == Pos.STACKED_TL)
+ ) {
+ i = centeredMonitorGroup.index
+ } else {
+ l = centeredMonitorGroup.index
}
- };
- let allocateGroup = (group, tlLimit, brLimit) => {
- let startPosition = tlLimit;
- let currentPosition = 0;
+ }
- if (group.expandableIndex >= 0) {
- let availableSize = brLimit - tlLimit;
- let expandable = group.elements[group.expandableIndex];
- let i = 0;
- let l = this._elementGroups.length;
- let tlSize = 0;
- let brSize = 0;
+ for (; i < l; ++i) {
+ let refGroup = this._elementGroups[i]
- if (centeredMonitorGroup && (centeredMonitorGroup != group || expandable.position != Pos.CENTERED_MONITOR)) {
- if (centeredMonitorGroup.index < group.index || (centeredMonitorGroup == group && expandable.position == Pos.STACKED_TL)) {
- i = centeredMonitorGroup.index;
- } else {
- l = centeredMonitorGroup.index;
- }
- }
-
- for (; i < l; ++i) {
- let refGroup = this._elementGroups[i];
-
- if (i < group.index && (!refGroup.fixed || refGroup[this.varCoord.c2] > tlLimit)) {
- tlSize += refGroup.size;
- } else if (i > group.index && (!refGroup.fixed || refGroup[this.varCoord.c1] < brLimit)) {
- brSize += refGroup.size;
- }
- }
-
- if (group.isCentered) {
- availableSize -= Math.max(tlSize, brSize) * 2;
- } else {
- availableSize -= tlSize + brSize;
- }
-
- if (availableSize < group.size) {
- expandable.natSize -= (group.size - availableSize) * (group.isCentered && !Pos.checkIfCentered(expandable.position) ? .5 : 1);
- assignGroupSize(group, true);
- }
+ if (
+ i < group.index &&
+ (!refGroup.fixed || refGroup[this.varCoord.c2] > tlLimit)
+ ) {
+ tlSize += refGroup.size
+ } else if (
+ i > group.index &&
+ (!refGroup.fixed || refGroup[this.varCoord.c1] < brLimit)
+ ) {
+ brSize += refGroup.size
}
+ }
- if (group.isCentered) {
- startPosition = tlLimit + (brLimit - tlLimit - group.size) * .5;
- } else if (group.position == Pos.STACKED_BR) {
- startPosition = brLimit - group.size;
- }
+ if (group.isCentered) {
+ availableSize -= Math.max(tlSize, brSize) * 2
+ } else {
+ availableSize -= tlSize + brSize
+ }
- currentPosition = group.tlOffset + startPosition;
-
- group.elements.forEach(element => {
- element.box[this.varCoord.c1] = Math.round(currentPosition);
- element.box[this.varCoord.c2] = Math.round((currentPosition += element.natSize));
-
- element.actor.allocate(element.box);
- });
-
- group[this.varCoord.c1] = startPosition;
- group[this.varCoord.c2] = currentPosition;
- group.fixed = 1;
- ++fixed;
- };
-
- this.panel.allocate(panelAlloc);
-
- this._elementGroups.forEach(group => {
- group.fixed = 0;
-
- assignGroupSize(group);
-
- if (group.position == Pos.CENTERED_MONITOR) {
- centeredMonitorGroup = group;
- }
- });
-
- if (centeredMonitorGroup) {
- allocateGroup(centeredMonitorGroup, panelAlloc[this.varCoord.c1], panelAlloc[this.varCoord.c2]);
+ if (availableSize < group.size) {
+ expandable.natSize -=
+ (group.size - availableSize) *
+ (group.isCentered && !Pos.checkIfCentered(expandable.position)
+ ? 0.5
+ : 1)
+ assignGroupSize(group, true)
+ }
}
- let iterations = 0; //failsafe
- while (fixed < this._elementGroups.length && ++iterations < 10) {
- for (let i = 0, l = this._elementGroups.length; i < l; ++i) {
- let group = this._elementGroups[i];
-
- if (group.fixed) {
- continue;
- }
-
- let prevGroup = this._elementGroups[i - 1];
- let nextGroup = this._elementGroups[i + 1];
- let prevLimit = prevGroup && prevGroup.fixed ? prevGroup[this.varCoord.c2] :
- centeredMonitorGroup && group.index > centeredMonitorGroup.index ? centeredMonitorGroup[this.varCoord.c2] : panelAlloc[this.varCoord.c1];
- let nextLimit = nextGroup && nextGroup.fixed ? nextGroup[this.varCoord.c1] :
- centeredMonitorGroup && group.index < centeredMonitorGroup.index ? centeredMonitorGroup[this.varCoord.c1] : panelAlloc[this.varCoord.c2];
-
- if (group.position == Pos.STACKED_TL) {
- allocateGroup(group, panelAlloc[this.varCoord.c1], nextLimit);
- } else if (group.position == Pos.STACKED_BR) {
- allocateGroup(group, prevLimit, panelAlloc[this.varCoord.c2]);
- } else if ((!prevGroup || prevGroup.fixed) && (!nextGroup || nextGroup.fixed)) { // CENTERED
- allocateGroup(group, prevLimit, nextLimit);
- }
- }
+ if (group.isCentered) {
+ startPosition = tlLimit + (brLimit - tlLimit - group.size) * 0.5
+ } else if (group.position == Pos.STACKED_BR) {
+ startPosition = brLimit - group.size
}
+
+ currentPosition = group.tlOffset + startPosition
+
+ group.elements.forEach((element) => {
+ element.box[this.varCoord.c1] = Math.round(currentPosition)
+ element.box[this.varCoord.c2] = Math.round(
+ (currentPosition += element.natSize),
+ )
+
+ element.actor.allocate(element.box)
+ })
+
+ group[this.varCoord.c1] = startPosition
+ group[this.varCoord.c2] = currentPosition
+ group.fixed = 1
+ ++fixed
+ }
+
+ this.panel.allocate(panelAlloc)
+
+ this._elementGroups.forEach((group) => {
+ group.fixed = 0
+
+ assignGroupSize(group)
+
+ if (group.position == Pos.CENTERED_MONITOR) {
+ centeredMonitorGroup = group
+ }
+ })
+
+ if (centeredMonitorGroup) {
+ allocateGroup(
+ centeredMonitorGroup,
+ panelAlloc[this.varCoord.c1],
+ panelAlloc[this.varCoord.c2],
+ )
+ }
+
+ let iterations = 0 //failsafe
+ while (fixed < this._elementGroups.length && ++iterations < 10) {
+ for (let i = 0, l = this._elementGroups.length; i < l; ++i) {
+ let group = this._elementGroups[i]
+
+ if (group.fixed) {
+ continue
+ }
+
+ let prevGroup = this._elementGroups[i - 1]
+ let nextGroup = this._elementGroups[i + 1]
+ let prevLimit =
+ prevGroup && prevGroup.fixed
+ ? prevGroup[this.varCoord.c2]
+ : centeredMonitorGroup && group.index > centeredMonitorGroup.index
+ ? centeredMonitorGroup[this.varCoord.c2]
+ : panelAlloc[this.varCoord.c1]
+ let nextLimit =
+ nextGroup && nextGroup.fixed
+ ? nextGroup[this.varCoord.c1]
+ : centeredMonitorGroup && group.index < centeredMonitorGroup.index
+ ? centeredMonitorGroup[this.varCoord.c1]
+ : panelAlloc[this.varCoord.c2]
+
+ if (group.position == Pos.STACKED_TL) {
+ allocateGroup(group, panelAlloc[this.varCoord.c1], nextLimit)
+ } else if (group.position == Pos.STACKED_BR) {
+ allocateGroup(group, prevLimit, panelAlloc[this.varCoord.c2])
+ } else if (
+ (!prevGroup || prevGroup.fixed) &&
+ (!nextGroup || nextGroup.fixed)
+ ) {
+ // CENTERED
+ allocateGroup(group, prevLimit, nextLimit)
+ }
+ }
+ }
}
_setPanelPosition() {
- let clipContainer = this.panelBox.get_parent();
+ let clipContainer = this.panelBox.get_parent()
- this.set_size(this.geom.w, this.geom.h);
- clipContainer.set_position(this.geom.x, this.geom.y);
+ this.set_size(this.geom.w, this.geom.h)
+ clipContainer.set_position(this.geom.x, this.geom.y)
- this._setVertical(this.panel, this.checkIfVertical());
+ this._setVertical(this.panel, this.checkIfVertical())
- // styles for theming
- Object.keys(St.Side).forEach(p => {
- let cssName = 'dashtopanel' + p.charAt(0) + p.slice(1).toLowerCase();
+ // styles for theming
+ Object.keys(St.Side).forEach((p) => {
+ let cssName = 'dashtopanel' + p.charAt(0) + p.slice(1).toLowerCase()
- this.panel[(St.Side[p] == this.geom.position ? 'add' : 'remove') + '_style_class_name'](cssName);
- });
+ this.panel[
+ (St.Side[p] == this.geom.position ? 'add' : 'remove') +
+ '_style_class_name'
+ ](cssName)
+ })
- this._setPanelClip(clipContainer);
+ this._setPanelClip(clipContainer)
- Main.layoutManager._updateHotCorners();
- Main.layoutManager._updatePanelBarrier(this);
+ Main.layoutManager._updateHotCorners()
+ Main.layoutManager._updatePanelBarrier(this)
}
_setPanelClip(clipContainer) {
- clipContainer = clipContainer || this.panelBox.get_parent();
- this._timeoutsHandler.add([T7, 0, () => Utils.setClip(clipContainer, clipContainer.x, clipContainer.y, this.panelBox.width, this.panelBox.height)]);
+ clipContainer = clipContainer || this.panelBox.get_parent()
+ this._timeoutsHandler.add([
+ T7,
+ 0,
+ () =>
+ Utils.setClip(
+ clipContainer,
+ clipContainer.x,
+ clipContainer.y,
+ this.panelBox.width,
+ this.panelBox.height,
+ ),
+ ])
}
_onButtonPress(actor, event) {
- let type = event.type();
- let isPress = type == Clutter.EventType.BUTTON_PRESS;
- let button = isPress ? event.get_button() : -1;
- let [stageX, stageY] = event.get_coords();
+ let type = event.type()
+ let isPress = type == Clutter.EventType.BUTTON_PRESS
+ let button = isPress ? event.get_button() : -1
+ let [stageX, stageY] = event.get_coords()
- if (button == 3 && global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, stageX, stageY) == this.panel) {
- //right click on an empty part of the panel, temporarily borrow and display the showapps context menu
- Main.layoutManager.setDummyCursorGeometry(stageX, stageY, 0, 0);
+ if (
+ button == 3 &&
+ global.stage.get_actor_at_pos(
+ Clutter.PickMode.REACTIVE,
+ stageX,
+ stageY,
+ ) == this.panel
+ ) {
+ //right click on an empty part of the panel, temporarily borrow and display the showapps context menu
+ Main.layoutManager.setDummyCursorGeometry(stageX, stageY, 0, 0)
- this.showAppsIconWrapper.createMenu();
- this.showAppsIconWrapper.popupMenu(Main.layoutManager.dummyCursor);
+ this.showAppsIconWrapper.createMenu()
+ this.showAppsIconWrapper.popupMenu(Main.layoutManager.dummyCursor)
- return Clutter.EVENT_STOP;
- } else {
- const targetActor = global.stage.get_event_actor(event);
+ return Clutter.EVENT_STOP
+ } else {
+ const targetActor = global.stage.get_event_actor(event)
- if (Main.modalCount > 0 || targetActor != actor ||
- (!isPress && type != Clutter.EventType.TOUCH_BEGIN) ||
- (isPress && button != 1)) {
- return Clutter.EVENT_PROPAGATE;
- }
+ if (
+ Main.modalCount > 0 ||
+ targetActor != actor ||
+ (!isPress && type != Clutter.EventType.TOUCH_BEGIN) ||
+ (isPress && button != 1)
+ ) {
+ return Clutter.EVENT_PROPAGATE
}
+ }
- let params = this.checkIfVertical() ? [stageY, 'y', 'height'] : [stageX, 'x', 'width'];
- let dragWindow = this._getDraggableWindowForPosition.apply(this, params.concat(['maximized_' + this.getOrientation() + 'ly']));
+ let params = this.checkIfVertical()
+ ? [stageY, 'y', 'height']
+ : [stageX, 'x', 'width']
+ let dragWindow = this._getDraggableWindowForPosition.apply(
+ this,
+ params.concat(['maximized_' + this.getOrientation() + 'ly']),
+ )
- if (!dragWindow)
- return Clutter.EVENT_PROPAGATE;
+ 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);
+ 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;
+ return Clutter.EVENT_STOP
}
- _getDraggableWindowForPosition(stageCoord, coord, dimension, maximizedProp) {
- let workspace = Utils.getCurrentWorkspace();
- let allWindowsByStacking = global.display.sort_windows_by_stacking(
- workspace.list_windows()
- ).reverse();
+ _getDraggableWindowForPosition(
+ stageCoord,
+ coord,
+ dimension,
+ maximizedProp,
+ ) {
+ let workspace = Utils.getCurrentWorkspace()
+ let allWindowsByStacking = global.display
+ .sort_windows_by_stacking(workspace.list_windows())
+ .reverse()
- return Utils.find(allWindowsByStacking, metaWindow => {
- let rect = metaWindow.get_frame_rect();
+ return Utils.find(allWindowsByStacking, (metaWindow) => {
+ let rect = metaWindow.get_frame_rect()
- return metaWindow.get_monitor() == this.monitor.index &&
- metaWindow.showing_on_its_workspace() &&
- metaWindow.get_window_type() != Meta.WindowType.DESKTOP &&
- metaWindow[maximizedProp] &&
- stageCoord > rect[coord] && stageCoord < rect[coord] + rect[dimension];
- });
+ 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(box) {
- if (this.checkIfVertical()) {
- this._setVertical(box, true);
- }
+ if (this.checkIfVertical()) {
+ this._setVertical(box, true)
+ }
}
_refreshVerticalAlloc() {
- this._setVertical(this._centerBox, true);
- this._setVertical(this._rightBox, true);
- this._formatVerticalClock();
+ this._setVertical(this._centerBox, true)
+ this._setVertical(this._rightBox, true)
+ this._formatVerticalClock()
}
_setVertical(actor, isVertical) {
- let _set = (actor, isVertical) => {
- if (!actor || actor instanceof Dash.DashItemContainer || actor instanceof TaskbarItemContainer.TaskbarItemContainer) {
- return;
- }
+ let _set = (actor, isVertical) => {
+ if (
+ !actor ||
+ actor instanceof Dash.DashItemContainer ||
+ actor instanceof TaskbarItemContainer.TaskbarItemContainer
+ ) {
+ return
+ }
- if (actor instanceof St.BoxLayout) {
- actor.vertical = isVertical;
- } else if (
- actor != this.statusArea.appMenu &&
- ((actor._delegate || actor) instanceof PanelMenu.ButtonBox || actor == this.statusArea.quickSettings)
- ) {
- let child = actor.get_first_child();
+ if (actor instanceof St.BoxLayout) {
+ actor.vertical = isVertical
+ } else if (
+ actor != this.statusArea.appMenu &&
+ ((actor._delegate || actor) instanceof PanelMenu.ButtonBox ||
+ actor == this.statusArea.quickSettings)
+ ) {
+ let child = actor.get_first_child()
- if (isVertical && !actor.visible && !actor._dtpVisibleId) {
- this._unmappedButtons.push(actor);
- actor._dtpVisibleId = actor.connect('notify::visible', () => {
- this._disconnectVisibleId(actor);
- this._refreshVerticalAlloc();
- });
- actor._dtpDestroyId = actor.connect('destroy', () => this._disconnectVisibleId(actor));
- }
+ if (isVertical && !actor.visible && !actor._dtpVisibleId) {
+ this._unmappedButtons.push(actor)
+ actor._dtpVisibleId = actor.connect('notify::visible', () => {
+ this._disconnectVisibleId(actor)
+ this._refreshVerticalAlloc()
+ })
+ actor._dtpDestroyId = actor.connect('destroy', () =>
+ this._disconnectVisibleId(actor),
+ )
+ }
- if (child) {
- let [, natWidth] = actor.get_preferred_width(-1);
+ if (child) {
+ let [, natWidth] = actor.get_preferred_width(-1)
- child.x_align = Clutter.ActorAlign[isVertical ? 'CENTER' : 'START'];
- actor.set_width(isVertical ? this.dtpSize : -1);
- isVertical = isVertical && (natWidth > this.dtpSize);
- actor[(isVertical ? 'add' : 'remove') + '_style_class_name']('vertical');
- }
- }
+ child.x_align = Clutter.ActorAlign[isVertical ? 'CENTER' : 'START']
+ actor.set_width(isVertical ? this.dtpSize : -1)
+ isVertical = isVertical && natWidth > this.dtpSize
+ actor[(isVertical ? 'add' : 'remove') + '_style_class_name'](
+ 'vertical',
+ )
+ }
+ }
- actor.get_children().forEach(c => _set(c, isVertical));
- };
+ actor.get_children().forEach((c) => _set(c, isVertical))
+ }
- _set(actor, false);
+ _set(actor, false)
- if (isVertical)
- _set(actor, isVertical);
+ if (isVertical) _set(actor, isVertical)
}
_disconnectVisibleId(actor) {
- actor.disconnect(actor._dtpVisibleId);
- actor.disconnect(actor._dtpDestroyId);
+ actor.disconnect(actor._dtpVisibleId)
+ actor.disconnect(actor._dtpDestroyId)
- delete actor._dtpVisibleId;
- delete actor._dtpDestroyId;
+ delete actor._dtpVisibleId
+ delete actor._dtpDestroyId
- this._unmappedButtons.splice(this._unmappedButtons.indexOf(actor), 1);
+ this._unmappedButtons.splice(this._unmappedButtons.indexOf(actor), 1)
}
_formatVerticalClock() {
- // https://github.com/GNOME/gnome-desktop/blob/master/libgnome-desktop/gnome-wall-clock.c#L310
- if (this.statusArea.dateMenu) {
- let datetime = this.statusArea.dateMenu._clock.clock;
- let datetimeParts = datetime.split(' ');
- let time = datetimeParts[1];
- let clockText = this.statusArea.dateMenu._clockDisplay.clutter_text;
- let setClockText = (text, useTimeSeparator) => {
- let stacks = text instanceof Array;
- let separator = `\n ${useTimeSeparator ? '‧‧' : '—' } \n`;
+ // https://github.com/GNOME/gnome-desktop/blob/master/libgnome-desktop/gnome-wall-clock.c#L310
+ if (this.statusArea.dateMenu) {
+ let datetime = this.statusArea.dateMenu._clock.clock
+ let datetimeParts = datetime.split(' ')
+ let time = datetimeParts[1]
+ let clockText = this.statusArea.dateMenu._clockDisplay.clutter_text
+ let setClockText = (text, useTimeSeparator) => {
+ let stacks = text instanceof Array
+ let separator = `\n ${useTimeSeparator ? '‧‧' : '—'} \n`
- clockText.set_text((stacks ? text.join(separator) : text).trim());
- clockText.set_use_markup(stacks);
- clockText.get_allocation_box();
+ clockText.set_text((stacks ? text.join(separator) : text).trim())
+ clockText.set_use_markup(stacks)
+ clockText.get_allocation_box()
- return !clockText.get_layout().is_ellipsized();
- };
-
- if (clockText.ellipsize == Pango.EllipsizeMode.NONE) {
- //on gnome-shell 3.36.4, the clockdisplay isn't ellipsize anymore, so set it back
- clockText.ellipsize = Pango.EllipsizeMode.END;
- }
-
- clockText.natural_width = this.dtpSize;
-
- if (!time) {
- datetimeParts = datetime.split(' ');
- time = datetimeParts.pop();
- datetimeParts = [datetimeParts.join(' '), time];
- }
-
- if (!setClockText(datetime) &&
- !setClockText(datetimeParts) &&
- !setClockText(time)) {
- let timeParts = time.split('∶');
-
- if (!this._clockFormat) {
- this._clockFormat = DESKTOPSETTINGS.get_string('clock-format');
- }
-
- if (this._clockFormat == '12h') {
- timeParts.push.apply(timeParts, timeParts.pop().split(' '));
- }
-
- setClockText(timeParts, true);
- }
+ return !clockText.get_layout().is_ellipsized()
}
+
+ if (clockText.ellipsize == Pango.EllipsizeMode.NONE) {
+ //on gnome-shell 3.36.4, the clockdisplay isn't ellipsize anymore, so set it back
+ clockText.ellipsize = Pango.EllipsizeMode.END
+ }
+
+ clockText.natural_width = this.dtpSize
+
+ if (!time) {
+ datetimeParts = datetime.split(' ')
+ time = datetimeParts.pop()
+ datetimeParts = [datetimeParts.join(' '), time]
+ }
+
+ if (
+ !setClockText(datetime) &&
+ !setClockText(datetimeParts) &&
+ !setClockText(time)
+ ) {
+ let timeParts = time.split('∶')
+
+ if (!this._clockFormat) {
+ this._clockFormat = DESKTOPSETTINGS.get_string('clock-format')
+ }
+
+ if (this._clockFormat == '12h') {
+ timeParts.push.apply(timeParts, timeParts.pop().split(' '))
+ }
+
+ setClockText(timeParts, true)
+ }
+ }
}
_setShowDesktopButton(add) {
- if (add) {
- if(this._showDesktopButton)
- return;
+ if (add) {
+ if (this._showDesktopButton) return
- this._showDesktopButton = new St.Bin({ style_class: 'showdesktop-button',
- reactive: true,
- can_focus: true,
- // x_fill: true,
- // y_fill: true,
- track_hover: true });
+ this._showDesktopButton = new St.Bin({
+ style_class: 'showdesktop-button',
+ reactive: true,
+ can_focus: true,
+ // x_fill: true,
+ // y_fill: true,
+ track_hover: true,
+ })
- this._setShowDesktopButtonStyle();
+ this._setShowDesktopButtonStyle()
- this._showDesktopButton.connect('touch-event', (actor, event) => {
- if (event.type() == Clutter.EventType.TOUCH_BEGIN) {
- this._onShowDesktopButtonPress();
- }
- });
- this._showDesktopButton.connect('button-press-event', () => this._onShowDesktopButtonPress());
- this._showDesktopButton.connect('enter-event', () => {
- this._showDesktopButton.add_style_class_name(this._getBackgroundBrightness() ?
- 'showdesktop-button-light-hovered' : 'showdesktop-button-dark-hovered');
+ this._showDesktopButton.connect('touch-event', (actor, event) => {
+ if (event.type() == Clutter.EventType.TOUCH_BEGIN) {
+ this._onShowDesktopButtonPress()
+ }
+ })
+ this._showDesktopButton.connect('button-press-event', () =>
+ this._onShowDesktopButtonPress(),
+ )
+ this._showDesktopButton.connect('enter-event', () => {
+ this._showDesktopButton.add_style_class_name(
+ this._getBackgroundBrightness()
+ ? 'showdesktop-button-light-hovered'
+ : 'showdesktop-button-dark-hovered',
+ )
- if (SETTINGS.get_boolean('show-showdesktop-hover')) {
- this._timeoutsHandler.add([T4, SETTINGS.get_int('show-showdesktop-delay'), () => {
- this._hiddenDesktopWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace();
- this._toggleWorkspaceWindows(true, this._hiddenDesktopWorkspace);
- }]);
- }
- });
+ if (SETTINGS.get_boolean('show-showdesktop-hover')) {
+ this._timeoutsHandler.add([
+ T4,
+ SETTINGS.get_int('show-showdesktop-delay'),
+ () => {
+ this._hiddenDesktopWorkspace =
+ Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace()
+ this._toggleWorkspaceWindows(true, this._hiddenDesktopWorkspace)
+ },
+ ])
+ }
+ })
- this._showDesktopButton.connect('leave-event', () => {
- this._showDesktopButton.remove_style_class_name(this._getBackgroundBrightness() ?
- 'showdesktop-button-light-hovered' : 'showdesktop-button-dark-hovered');
+ this._showDesktopButton.connect('leave-event', () => {
+ this._showDesktopButton.remove_style_class_name(
+ this._getBackgroundBrightness()
+ ? 'showdesktop-button-light-hovered'
+ : 'showdesktop-button-dark-hovered',
+ )
- if (SETTINGS.get_boolean('show-showdesktop-hover')) {
- if (this._timeoutsHandler.getId(T4)) {
- this._timeoutsHandler.remove(T4);
- } else if (this._hiddenDesktopWorkspace) {
- this._toggleWorkspaceWindows(false, this._hiddenDesktopWorkspace);
- }
- }
- });
+ if (SETTINGS.get_boolean('show-showdesktop-hover')) {
+ if (this._timeoutsHandler.getId(T4)) {
+ this._timeoutsHandler.remove(T4)
+ } else if (this._hiddenDesktopWorkspace) {
+ this._toggleWorkspaceWindows(false, this._hiddenDesktopWorkspace)
+ }
+ }
+ })
- this.panel.add_child(this._showDesktopButton);
- } else {
- if(!this._showDesktopButton)
- return;
+ this.panel.add_child(this._showDesktopButton)
+ } else {
+ if (!this._showDesktopButton) return
- this.panel.remove_child(this._showDesktopButton);
- this._showDesktopButton.destroy();
- this._showDesktopButton = null;
- }
+ this.panel.remove_child(this._showDesktopButton)
+ this._showDesktopButton.destroy()
+ this._showDesktopButton = null
+ }
}
_setShowDesktopButtonStyle() {
- let rgb = this._getBackgroundBrightness() ? "rgba(55, 55, 55, .2)" : "rgba(200, 200, 200, .2)";
+ let rgb = this._getBackgroundBrightness()
+ ? 'rgba(55, 55, 55, .2)'
+ : 'rgba(200, 200, 200, .2)'
- let isLineCustom = SETTINGS.get_boolean('desktop-line-use-custom-color');
- rgb = isLineCustom ? SETTINGS.get_string('desktop-line-custom-color') : rgb;
+ let isLineCustom = SETTINGS.get_boolean('desktop-line-use-custom-color')
+ rgb = isLineCustom
+ ? SETTINGS.get_string('desktop-line-custom-color')
+ : rgb
- if (this._showDesktopButton) {
- let buttonSize = SETTINGS.get_int('showdesktop-button-width') + 'px;';
- let isVertical = this.checkIfVertical();
+ if (this._showDesktopButton) {
+ let buttonSize = SETTINGS.get_int('showdesktop-button-width') + 'px;'
+ let isVertical = this.checkIfVertical()
- let sytle = "border: 0 solid " + rgb + ";";
- sytle += isVertical ? 'border-top-width:1px;height:' + buttonSize : 'border-left-width:1px;width:' + buttonSize;
+ let sytle = 'border: 0 solid ' + rgb + ';'
+ sytle += isVertical
+ ? 'border-top-width:1px;height:' + buttonSize
+ : 'border-left-width:1px;width:' + buttonSize
- this._showDesktopButton.set_style(sytle);
- this._showDesktopButton[(isVertical ? 'x' : 'y') + '_expand'] = true;
- }
+ this._showDesktopButton.set_style(sytle)
+ this._showDesktopButton[(isVertical ? 'x' : 'y') + '_expand'] = true
+ }
}
// _getBackgroundBrightness: return true if panel has a bright background color
_getBackgroundBrightness() {
- return Utils.checkIfColorIsBright(this.dynamicTransparency.backgroundColorRgb);
+ return Utils.checkIfColorIsBright(
+ this.dynamicTransparency.backgroundColorRgb,
+ )
}
_toggleWorkspaceWindows(hide, workspace) {
- let time = SETTINGS.get_int('show-showdesktop-time') * .001;
+ let time = SETTINGS.get_int('show-showdesktop-time') * 0.001
- workspace.list_windows().forEach(w => {
- if (!w.minimized && !w.customJS_ding) {
- let tweenOpts = {
- opacity: hide ? 0 : 255,
- time: time,
- transition: 'easeOutQuad'
- };
+ workspace.list_windows().forEach((w) => {
+ if (!w.minimized && !w.customJS_ding) {
+ let tweenOpts = {
+ opacity: hide ? 0 : 255,
+ time: time,
+ transition: 'easeOutQuad',
+ }
- Utils.animateWindowOpacity(w.get_compositor_private(), tweenOpts);
- }
- });
+ Utils.animateWindowOpacity(w.get_compositor_private(), tweenOpts)
+ }
+ })
}
_onShowDesktopButtonPress() {
- let label = 'trackerFocusApp';
+ let label = 'trackerFocusApp'
- this._signalsHandler.removeWithLabel(label);
- this._timeoutsHandler.remove(T5);
+ this._signalsHandler.removeWithLabel(label)
+ this._timeoutsHandler.remove(T5)
- if(this._restoreWindowList && this._restoreWindowList.length) {
- this._timeoutsHandler.remove(T4);
+ 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);
+ 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();
- });
+ windows.forEach(function (w) {
+ w.minimize()
+ })
- this._restoreWindowList = windows;
+ this._restoreWindowList = windows
- this._timeoutsHandler.add([T5, 20, () => this._signalsHandler.addWithLabel(
- label,
- [
- tracker,
- 'notify::focus-app',
- () => this._restoreWindowList = null
- ]
- )]);
- }
+ this._timeoutsHandler.add([
+ T5,
+ 20,
+ () =>
+ this._signalsHandler.addWithLabel(label, [
+ tracker,
+ 'notify::focus-app',
+ () => (this._restoreWindowList = null),
+ ]),
+ ])
+ }
- Main.overview.hide();
+ Main.overview.hide()
}
_onPanelMouseScroll(actor, event) {
- let scrollAction = SETTINGS.get_string('scroll-panel-action');
- let direction = Utils.getMouseScrollDirection(event);
+ let scrollAction = SETTINGS.get_string('scroll-panel-action')
+ let direction = Utils.getMouseScrollDirection(event)
- const targetActor = global.stage.get_event_actor(event);
+ const targetActor = global.stage.get_event_actor(event)
- if (!this._checkIfIgnoredScrollSource(targetActor) && !this._timeoutsHandler.getId(T6)) {
- if (direction && scrollAction === 'SWITCH_WORKSPACE') {
- let args = [global.display];
+ if (
+ !this._checkIfIgnoredScrollSource(targetActor) &&
+ !this._timeoutsHandler.getId(T6)
+ ) {
+ if (direction && scrollAction === 'SWITCH_WORKSPACE') {
+ let args = [global.display]
- //adjust for horizontal workspaces
- if (Utils.DisplayWrapper.getWorkspaceManager().layout_rows === 1) {
- direction = direction == 'up' ? 'left' : 'right';
- }
+ //adjust for horizontal workspaces
+ if (Utils.DisplayWrapper.getWorkspaceManager().layout_rows === 1) {
+ direction = direction == 'up' ? 'left' : 'right'
+ }
- //gnome-shell < 3.30 needs an additional "screen" param
- global.screen ? args.push(global.screen) : 0;
+ //gnome-shell < 3.30 needs an additional "screen" param
+ global.screen ? args.push(global.screen) : 0
- let showWsPopup = SETTINGS.get_boolean('scroll-panel-show-ws-popup');
- showWsPopup ? 0 : Main.wm._workspaceSwitcherPopup = { display: () => {} };
- Main.wm._showWorkspaceSwitcher.apply(Main.wm, args.concat([0, { get_name: () => 'switch---' + direction }]));
- showWsPopup ? 0 : Main.wm._workspaceSwitcherPopup = null;
- } else if (direction && scrollAction === 'CYCLE_WINDOWS') {
- let windows = this.taskbar.getAppInfos().reduce((ws, appInfo) => ws.concat(appInfo.windows), []);
+ let showWsPopup = SETTINGS.get_boolean('scroll-panel-show-ws-popup')
+ showWsPopup
+ ? 0
+ : (Main.wm._workspaceSwitcherPopup = { display: () => {} })
+ Main.wm._showWorkspaceSwitcher.apply(
+ Main.wm,
+ args.concat([0, { get_name: () => 'switch---' + direction }]),
+ )
+ showWsPopup ? 0 : (Main.wm._workspaceSwitcherPopup = null)
+ } else if (direction && scrollAction === 'CYCLE_WINDOWS') {
+ let windows = this.taskbar
+ .getAppInfos()
+ .reduce((ws, appInfo) => ws.concat(appInfo.windows), [])
- Utils.activateSiblingWindow(windows, direction);
- } else if (scrollAction === 'CHANGE_VOLUME' && !event.is_pointer_emulated()) {
- let proto = Volume.OutputIndicator.prototype;
- let func = proto._handleScrollEvent || proto.vfunc_scroll_event || proto._onScrollEvent;
- let indicator = Main.panel.statusArea[Utils.getSystemMenuInfo().name]._volumeOutput;
+ Utils.activateSiblingWindow(windows, direction)
+ } else if (
+ scrollAction === 'CHANGE_VOLUME' &&
+ !event.is_pointer_emulated()
+ ) {
+ let proto = Volume.OutputIndicator.prototype
+ let func =
+ proto._handleScrollEvent ||
+ proto.vfunc_scroll_event ||
+ proto._onScrollEvent
+ let indicator =
+ Main.panel.statusArea[Utils.getSystemMenuInfo().name]._volumeOutput
- if (indicator.quickSettingsItems)
- // new quick settings menu in gnome-shell > 42
- func(indicator.quickSettingsItems[0], event);
- else
- func.call(indicator, 0, event);
- } else {
- return;
- }
-
- const scrollDelay = SETTINGS.get_int('scroll-panel-delay');
-
- if (scrollDelay) {
- this._timeoutsHandler.add([T6, scrollDelay, () => {}]);
- }
+ if (indicator.quickSettingsItems)
+ // new quick settings menu in gnome-shell > 42
+ func(indicator.quickSettingsItems[0], event)
+ else func.call(indicator, 0, event)
+ } else {
+ return
}
+
+ const scrollDelay = SETTINGS.get_int('scroll-panel-delay')
+
+ if (scrollDelay) {
+ this._timeoutsHandler.add([T6, scrollDelay, () => {}])
+ }
+ }
}
_checkIfIgnoredScrollSource(source) {
- let ignoredConstr = ['WorkspaceIndicator'];
+ let ignoredConstr = ['WorkspaceIndicator']
- return source.get_parent()._dtpIgnoreScroll || ignoredConstr.indexOf(source.constructor.name) >= 0;
+ return (
+ source.get_parent()._dtpIgnoreScroll ||
+ ignoredConstr.indexOf(source.constructor.name) >= 0
+ )
}
_initProgressManager() {
- const progressVisible = SETTINGS.get_boolean('progress-show-bar');
- const countVisible = SETTINGS.get_boolean('progress-show-count');
- const pm = this.progressManager;
+ const progressVisible = SETTINGS.get_boolean('progress-show-bar')
+ const countVisible = SETTINGS.get_boolean('progress-show-count')
+ const pm = this.progressManager
- if(!pm && (progressVisible || countVisible))
- this.progressManager = new Progress.ProgressManager();
- else if (pm)
- Object.keys(pm._entriesByDBusName).forEach((k) => pm._entriesByDBusName[k].setCountVisible(countVisible));
+ if (!pm && (progressVisible || countVisible))
+ this.progressManager = new Progress.ProgressManager()
+ else if (pm)
+ Object.keys(pm._entriesByDBusName).forEach((k) =>
+ pm._entriesByDBusName[k].setCountVisible(countVisible),
+ )
}
-});
-
-export const SecondaryPanel = GObject.registerClass({
-}, class SecondaryPanel extends St.Widget {
+ },
+)
+export const SecondaryPanel = GObject.registerClass(
+ {},
+ class SecondaryPanel extends St.Widget {
_init(params) {
- super._init(params);
+ super._init(params)
}
vfunc_allocate(box) {
- this.set_allocation(box);
+ this.set_allocation(box)
}
-});
+ },
+)
diff --git a/panelManager.js b/panelManager.js
index 9073739..897eea0 100755
--- a/panelManager.js
+++ b/panelManager.js
@@ -17,765 +17,938 @@
* 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 * 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';
+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()
- constructor() {
- this.overview = new Overview.Overview();
- this.panelsElementPositions = {};
- this._injectionManager = new InjectionManager();
+ this._saveMonitors()
+ }
- 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)
}
- enable(reset) {
- let dtpPrimaryIndex = SETTINGS.get_int('primary-monitor');
+ if (SETTINGS.get_boolean('multi-monitors')) {
+ Main.layoutManager.monitors
+ .filter((m) => m != this.dtpPrimaryMonitor)
+ .forEach((m) => {
+ this.allPanels.push(this._createPanel(m, true))
+ })
+ }
- this.allPanels = [];
- this.dtpPrimaryMonitor = Main.layoutManager.monitors[dtpPrimaryIndex] || Main.layoutManager.primaryMonitor;
- this.proximityManager = new Proximity.ProximityManager();
+ global.dashToPanel.panels = this.allPanels
+ global.dashToPanel.emit('panels-created')
- 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.allPanels.forEach((p) => {
+ let panelPosition = p.getPosition()
+ let leftOrRight =
+ panelPosition == St.Side.LEFT || panelPosition == St.Side.RIGHT
- this.setFocusedMonitor(this.dtpPrimaryMonitor);
+ 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],
+ 'child-added',
+ (parent, child) => {
+ this.primaryPanel &&
+ child instanceof St.Bin &&
+ this._adjustPanelMenuButton(
+ this._getPanelMenuButton(child.get_first_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,
+ )
}
- if (SETTINGS.get_boolean('multi-monitors')) {
- Main.layoutManager.monitors.filter(m => m != this.dtpPrimaryMonitor).forEach(m => {
- this.allPanels.push(this._createPanel(m, true));
- });
+ 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_child(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
+
+ // https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2395
+ // The overview allocation used to calculate its workarea based on the monitor where the overview
+ // was displayed, but it got changed back to always use the primary monitor. So now, temporarily assign
+ // the primary monitor to dtp focused monitor while recalculating the overview workarea
+ Main.layoutManager.primaryMonitor = monitor
+ Main.overview._overview._controls.layout_manager._updateWorkAreaBox()
+ Main.layoutManager.primaryMonitor =
+ Main.layoutManager.monitors[Main.layoutManager.primaryIndex]
+ }
+ }
+
+ _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_child(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_child(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)
}
- global.dashToPanel.panels = this.allPanels;
- global.dashToPanel.emit('panels-created');
+ find(c)
+ })
- 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
- );
+ find(container)
- this._findPanelMenuButtons(p.panelBox).forEach(pmb => this._adjustPanelMenuButton(pmb, p.monitor, panelPosition));
-
- p.taskbar.iconAnimator.start();
- });
+ return panelMenuButtons
+ }
- 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],
- 'child-added',
- (parent, child) => {
- this.primaryPanel &&
- child instanceof St.Bin &&
- this._adjustPanelMenuButton(this._getPanelMenuButton(child.get_first_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) {}});
+ _removePanelBarriers(panel) {
+ if (panel.isStandalone && panel._rightPanelBarrier) {
+ panel._rightPanelBarrier.destroy()
}
- disable(reset) {
- this.primaryPanel && this.overview.disable();
- this.proximityManager.destroy();
+ if (panel._leftPanelBarrier) {
+ panel._leftPanelBarrier.destroy()
+ delete panel._leftPanelBarrier
+ }
+ }
- this.allPanels.forEach(p => {
- p.taskbar.iconAnimator.pause();
+ _getPanelMenuButton(obj) {
+ return obj instanceof PanelMenu.Button && obj.menu?._boxPointer ? obj : 0
+ }
- 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_child(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;
+ _setKeyBindings(enable) {
+ let keys = {
+ 'intellihide-key-toggle': () =>
+ this.allPanels.forEach((p) => p.intellihide.toggle()),
}
- _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;
- }
- });
- }
+ Object.keys(keys).forEach((k) => {
+ Utils.removeKeybinding(k)
- 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;
-
- // https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2395
- // The overview allocation used to calculate its workarea based on the monitor where the overview
- // was displayed, but it got changed back to always use the primary monitor. So now, temporarily assign
- // the primary monitor to dtp focused monitor while recalculating the overview workarea
- Main.layoutManager.primaryMonitor = monitor
- Main.overview._overview._controls.layout_manager._updateWorkAreaBox()
- Main.layoutManager.primaryMonitor = Main.layoutManager.monitors[Main.layoutManager.primaryIndex]
- }
- }
-
- _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_child(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_child(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);
- }
- });
- }
-
-};
+ 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;
- }
- });
+ constructor(actor) {
+ this._count = 0
+ this._started = false
+ this._animations = {
+ dance: [],
}
+ this._timeline = new Clutter.Timeline({
+ duration: 3000,
+ repeat_count: -1,
+ })
- 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;
+ /* 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;
+ 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;
+ 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 });
+ 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.start();
+ this._timeline.stop()
}
- this._count++;
+ return
+ }
}
-
- 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 = [];
+ // 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;
+ //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
+ }
+ }
}
- // 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;
+ if (haveTopLeftCorner) {
+ let corner = new Layout.HotCorner(this, monitor, cornerX, cornerY)
- 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);
- }
+ 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');
+ this.emit('hot-corners-changed')
}
function newUpdatePanelBarrier(panel) {
- let barriers = {
- _rightPanelBarrier: [(panel.isStandalone ? panel : this)],
- _leftPanelBarrier: [panel]
- };
+ let barriers = {
+ _rightPanelBarrier: [panel.isStandalone ? panel : this],
+ _leftPanelBarrier: [panel],
+ }
- Object.keys(barriers).forEach(k => {
- let obj = barriers[k][0];
+ Object.keys(barriers).forEach((k) => {
+ let obj = barriers[k][0]
- if (obj[k]) {
- obj[k].destroy();
- obj[k] = null;
- }
- });
+ if (obj[k]) {
+ obj[k].destroy()
+ obj[k] = null
+ }
+ })
- if (!this.primaryMonitor || !panel.panelBox.height) {
- return;
+ 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 = {
+ backend: global.backend,
+ directions: barriers[k][2],
}
- 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);
- }
+ barrierOptions[panel.varCoord.c1] = barrierOptions[panel.varCoord.c2] =
+ barriers[k][1]
+ barrierOptions[panel.fixedCoord.c1] = fixed1
+ barrierOptions[panel.fixedCoord.c2] = fixed2
- 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 = {
- backend: global.backend,
- 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);
- });
+ 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;
+ 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._oldResize()
- this._hiddenY = Main.layoutManager.primaryMonitor.y + topOffset - this.height;
- this._targetY = this._hiddenY + this.height;
- this.y = this._hiddenY;
+ 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));
+ 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;
+ if (this._open) return
- this._resize();
- this._oldOpen();
+ this._resize()
+ this._oldOpen()
}
diff --git a/panelPositions.js b/panelPositions.js
index a970bdd..bf39133 100644
--- a/panelPositions.js
+++ b/panelPositions.js
@@ -15,47 +15,47 @@
* along with this program. If not, see .
*/
-export const SHOW_APPS_BTN = 'showAppsButton';
-export const ACTIVITIES_BTN = 'activitiesButton';
-export const TASKBAR = 'taskbar';
-export const DATE_MENU = 'dateMenu';
-export const SYSTEM_MENU = 'systemMenu';
-export const LEFT_BOX = 'leftBox';
-export const CENTER_BOX = 'centerBox';
-export const RIGHT_BOX = 'rightBox';
-export const DESKTOP_BTN = 'desktopButton';
+export const SHOW_APPS_BTN = 'showAppsButton'
+export const ACTIVITIES_BTN = 'activitiesButton'
+export const TASKBAR = 'taskbar'
+export const DATE_MENU = 'dateMenu'
+export const SYSTEM_MENU = 'systemMenu'
+export const LEFT_BOX = 'leftBox'
+export const CENTER_BOX = 'centerBox'
+export const RIGHT_BOX = 'rightBox'
+export const DESKTOP_BTN = 'desktopButton'
-export const STACKED_TL = 'stackedTL';
-export const STACKED_BR = 'stackedBR';
-export const CENTERED = 'centered';
-export const CENTERED_MONITOR = 'centerMonitor';
+export const STACKED_TL = 'stackedTL'
+export const STACKED_BR = 'stackedBR'
+export const CENTERED = 'centered'
+export const CENTERED_MONITOR = 'centerMonitor'
-export const TOP = 'TOP';
-export const BOTTOM = 'BOTTOM';
-export const LEFT = 'LEFT';
-export const RIGHT = 'RIGHT';
+export const TOP = 'TOP'
+export const BOTTOM = 'BOTTOM'
+export const LEFT = 'LEFT'
+export const RIGHT = 'RIGHT'
-export const START = 'START';
-export const MIDDLE = 'MIDDLE';
-export const END = 'END';
+export const START = 'START'
+export const MIDDLE = 'MIDDLE'
+export const END = 'END'
export const defaults = [
- { element: SHOW_APPS_BTN, visible: true, position: STACKED_TL },
- { element: ACTIVITIES_BTN, visible: false, position: STACKED_TL },
- { element: LEFT_BOX, visible: true, position: STACKED_TL },
- { element: TASKBAR, visible: true, position: STACKED_TL },
- { element: CENTER_BOX, visible: true, position: STACKED_BR },
- { element: RIGHT_BOX, visible: true, position: STACKED_BR },
- { element: DATE_MENU, visible: true, position: STACKED_BR },
- { element: SYSTEM_MENU, visible: true, position: STACKED_BR },
- { element: DESKTOP_BTN, visible: true, position: STACKED_BR },
-];
+ { element: SHOW_APPS_BTN, visible: true, position: STACKED_TL },
+ { element: ACTIVITIES_BTN, visible: false, position: STACKED_TL },
+ { element: LEFT_BOX, visible: true, position: STACKED_TL },
+ { element: TASKBAR, visible: true, position: STACKED_TL },
+ { element: CENTER_BOX, visible: true, position: STACKED_BR },
+ { element: RIGHT_BOX, visible: true, position: STACKED_BR },
+ { element: DATE_MENU, visible: true, position: STACKED_BR },
+ { element: SYSTEM_MENU, visible: true, position: STACKED_BR },
+ { element: DESKTOP_BTN, visible: true, position: STACKED_BR },
+]
-export const optionDialogFunctions = {};
+export const optionDialogFunctions = {}
-optionDialogFunctions[SHOW_APPS_BTN] = '_showShowAppsButtonOptions';
-optionDialogFunctions[DESKTOP_BTN] = '_showDesktopButtonOptions';
+optionDialogFunctions[SHOW_APPS_BTN] = '_showShowAppsButtonOptions'
+optionDialogFunctions[DESKTOP_BTN] = '_showDesktopButtonOptions'
export function checkIfCentered(position) {
- return position == CENTERED || position == CENTERED_MONITOR;
+ return position == CENTERED || position == CENTERED_MONITOR
}
diff --git a/panelSettings.js b/panelSettings.js
index fc2d60c..bfb73e6 100644
--- a/panelSettings.js
+++ b/panelSettings.js
@@ -15,43 +15,43 @@
* along with this program. If not, see .
*/
-import * as Pos from './panelPositions.js';
+import * as Pos from './panelPositions.js'
/** Return object representing a settings value that is stored as JSON. */
export function getSettingsJson(settings, setting) {
- try {
- return JSON.parse(settings.get_string(setting));
- } catch(e) {
- log('Error parsing positions: ' + e.message);
- }
+ try {
+ return JSON.parse(settings.get_string(setting))
+ } catch (e) {
+ log('Error parsing positions: ' + e.message)
+ }
}
/** Write value object as JSON to setting in settings. */
export function setSettingsJson(settings, setting, value) {
- try {
- const json = JSON.stringify(value);
- settings.set_string(setting, json);
- } catch(e) {
- log('Error serializing setting: ' + e.message);
- }
+ try {
+ const json = JSON.stringify(value)
+ settings.set_string(setting, json)
+ } catch (e) {
+ log('Error serializing setting: ' + e.message)
+ }
}
/** Returns size of panel on a specific monitor, in pixels. */
export function getPanelSize(settings, monitorIndex) {
- const sizes = getSettingsJson(settings, 'panel-sizes');
- // Pull in deprecated setting if panel-sizes does not have setting for monitor.
- const fallbackSize = settings.get_int('panel-size');
- const theDefault = 48;
- return sizes[monitorIndex] || fallbackSize || theDefault;
+ const sizes = getSettingsJson(settings, 'panel-sizes')
+ // Pull in deprecated setting if panel-sizes does not have setting for monitor.
+ const fallbackSize = settings.get_int('panel-size')
+ const theDefault = 48
+ return sizes[monitorIndex] || fallbackSize || theDefault
}
export function setPanelSize(settings, monitorIndex, value) {
- if (!(Number.isInteger(value) && value <= 128 && value >= 16)) {
- log('Not setting invalid panel size: ' + value);
- return;
- }
- let sizes = getSettingsJson(settings, 'panel-sizes');
- sizes[monitorIndex] = value;
- setSettingsJson(settings, 'panel-sizes', sizes);
+ if (!(Number.isInteger(value) && value <= 128 && value >= 16)) {
+ log('Not setting invalid panel size: ' + value)
+ return
+ }
+ let sizes = getSettingsJson(settings, 'panel-sizes')
+ sizes[monitorIndex] = value
+ setSettingsJson(settings, 'panel-sizes', sizes)
}
/**
@@ -59,53 +59,59 @@ export function setPanelSize(settings, monitorIndex, value) {
* from settings. e.g. 100
*/
export function getPanelLength(settings, monitorIndex) {
- const lengths = getSettingsJson(settings, 'panel-lengths');
- const theDefault = 100;
- return lengths[monitorIndex] || theDefault;
+ const lengths = getSettingsJson(settings, 'panel-lengths')
+ const theDefault = 100
+ return lengths[monitorIndex] || theDefault
}
export function setPanelLength(settings, monitorIndex, value) {
- if (!(Number.isInteger(value) && value <= 100 && value >= 0)) {
- log('Not setting invalid panel length: ' + value);
- return;
- }
- let lengths = getSettingsJson(settings, 'panel-lengths');
- lengths[monitorIndex] = value;
- setSettingsJson(settings, 'panel-lengths', lengths);
+ if (!(Number.isInteger(value) && value <= 100 && value >= 0)) {
+ log('Not setting invalid panel length: ' + value)
+ return
+ }
+ let lengths = getSettingsJson(settings, 'panel-lengths')
+ lengths[monitorIndex] = value
+ setSettingsJson(settings, 'panel-lengths', lengths)
}
/** Returns position of panel on a specific monitor. */
export function getPanelPosition(settings, monitorIndex) {
- const positions = getSettingsJson(settings, 'panel-positions');
- const fallbackPosition = settings.get_string('panel-position');
- const theDefault = Pos.BOTTOM;
- return positions[monitorIndex] || fallbackPosition || theDefault;
+ const positions = getSettingsJson(settings, 'panel-positions')
+ const fallbackPosition = settings.get_string('panel-position')
+ const theDefault = Pos.BOTTOM
+ return positions[monitorIndex] || fallbackPosition || theDefault
}
export function setPanelPosition(settings, monitorIndex, value) {
- if (!(value === Pos.TOP || value === Pos.BOTTOM || value === Pos.LEFT
- || value === Pos.RIGHT)) {
- log('Not setting invalid panel position: ' + value);
- return;
- }
- const positions = getSettingsJson(settings, 'panel-positions');
- positions[monitorIndex] = value;
- setSettingsJson(settings, 'panel-positions', positions);
+ if (
+ !(
+ value === Pos.TOP ||
+ value === Pos.BOTTOM ||
+ value === Pos.LEFT ||
+ value === Pos.RIGHT
+ )
+ ) {
+ log('Not setting invalid panel position: ' + value)
+ return
+ }
+ const positions = getSettingsJson(settings, 'panel-positions')
+ positions[monitorIndex] = value
+ setSettingsJson(settings, 'panel-positions', positions)
}
/** Returns anchor location of panel on a specific monitor. */
export function getPanelAnchor(settings, monitorIndex) {
- const anchors = getSettingsJson(settings, 'panel-anchors');
- const theDefault = Pos.MIDDLE;
- return anchors[monitorIndex] || theDefault;
+ const anchors = getSettingsJson(settings, 'panel-anchors')
+ const theDefault = Pos.MIDDLE
+ return anchors[monitorIndex] || theDefault
}
export function setPanelAnchor(settings, monitorIndex, value) {
- if (!(value === Pos.START || value === Pos.MIDDLE || value === Pos.END)) {
- log('Not setting invalid panel anchor: ' + value);
- return;
- }
- const anchors = getSettingsJson(settings, 'panel-anchors');
- anchors[monitorIndex] = value;
- setSettingsJson(settings, 'panel-anchors', anchors);
+ if (!(value === Pos.START || value === Pos.MIDDLE || value === Pos.END)) {
+ log('Not setting invalid panel anchor: ' + value)
+ return
+ }
+ const anchors = getSettingsJson(settings, 'panel-anchors')
+ anchors[monitorIndex] = value
+ setSettingsJson(settings, 'panel-anchors', anchors)
}
diff --git a/panelStyle.js b/panelStyle.js
index 353e3ef..0ffb875 100644
--- a/panelStyle.js
+++ b/panelStyle.js
@@ -21,294 +21,323 @@
* mathematical.coffee@gmail.com
*/
-import * as Utils from './utils.js';
-import {SETTINGS} from './extension.js';
-
+import * as Utils from './utils.js'
+import { SETTINGS } from './extension.js'
export const PanelStyle = class {
+ enable(panel) {
+ this.panel = panel
- enable(panel) {
- this.panel = panel;
+ this._applyStyles()
- this._applyStyles();
+ this._bindSettingsChanges()
+ }
- this._bindSettingsChanges();
+ disable() {
+ for (let i = 0; i < this._dtpSettingsSignalIds.length; ++i) {
+ SETTINGS.disconnect(this._dtpSettingsSignalIds[i])
}
- disable() {
- for (let i = 0; i < this._dtpSettingsSignalIds.length; ++i) {
- SETTINGS.disconnect(this._dtpSettingsSignalIds[i]);
+ this._removeStyles()
+ }
+
+ _bindSettingsChanges() {
+ let configKeys = [
+ 'tray-size',
+ 'leftbox-size',
+ 'tray-padding',
+ 'leftbox-padding',
+ 'status-icon-padding',
+ ]
+
+ this._dtpSettingsSignalIds = []
+
+ for (let i in configKeys) {
+ this._dtpSettingsSignalIds.push(
+ SETTINGS.connect('changed::' + configKeys[i], () => {
+ this._removeStyles()
+ this._applyStyles()
+ }),
+ )
+ }
+ }
+
+ _applyStyles() {
+ this._rightBoxOperations = []
+
+ let trayPadding = SETTINGS.get_int('tray-padding')
+ let isVertical = this.panel.checkIfVertical()
+ let paddingStyle = 'padding: ' + (isVertical ? '%dpx 0' : '0 %dpx')
+
+ if (trayPadding >= 0) {
+ let operation = {}
+ let trayPaddingStyleLine
+
+ if (isVertical) {
+ trayPaddingStyleLine = paddingStyle.format(trayPadding)
+ operation.compareFn = function (actor) {
+ let parent = actor.get_parent()
+ return (
+ (parent &&
+ parent.has_style_class_name &&
+ parent.has_style_class_name('panel-button') &&
+ !parent.has_style_class_name('clock-display')) ||
+ (actor.has_style_class_name && actor.has_style_class_name('clock'))
+ )
+ }
+ } else {
+ trayPaddingStyleLine = '-natural-hpadding: %dpx'.format(trayPadding)
+ if (trayPadding < 6) {
+ trayPaddingStyleLine += '; -minimum-hpadding: %dpx'.format(
+ trayPadding,
+ )
}
- this._removeStyles();
+ operation.compareFn = function (actor) {
+ return (
+ actor.has_style_class_name &&
+ actor.has_style_class_name('panel-button')
+ )
+ }
+ }
+
+ operation.applyFn = (actor, operationIdx) => {
+ this._overrideStyle(actor, trayPaddingStyleLine, operationIdx)
+ this._refreshPanelButton(actor)
+ }
+ this._rightBoxOperations.push(operation)
}
- _bindSettingsChanges() {
- let configKeys = [
- "tray-size",
- "leftbox-size",
- "tray-padding",
- "leftbox-padding",
- "status-icon-padding",
- ];
-
- this._dtpSettingsSignalIds = [];
-
- for(let i in configKeys) {
- this._dtpSettingsSignalIds.push(SETTINGS.connect('changed::' + configKeys[i], () => {
- this._removeStyles();
- this._applyStyles();
- }));
- }
+ let statusIconPadding = SETTINGS.get_int('status-icon-padding')
+ if (statusIconPadding >= 0) {
+ let statusIconPaddingStyleLine = paddingStyle.format(statusIconPadding)
+ let operation = {}
+ operation.compareFn = function (actor) {
+ return (
+ actor.has_style_class_name &&
+ actor.has_style_class_name('system-status-icon')
+ )
+ }
+ operation.applyFn = (actor, operationIdx) => {
+ this._overrideStyle(actor, statusIconPaddingStyleLine, operationIdx)
+ }
+ this._rightBoxOperations.push(operation)
}
- _applyStyles() {
- this._rightBoxOperations = [];
-
- let trayPadding = SETTINGS.get_int('tray-padding');
- let isVertical = this.panel.checkIfVertical();
- let paddingStyle = 'padding: ' + (isVertical ? '%dpx 0' : '0 %dpx');
+ let trayContentSize = SETTINGS.get_int('tray-size')
+ if (trayContentSize > 0) {
+ let trayIconSizeStyleLine = 'icon-size: %dpx'.format(trayContentSize)
+ let operation = {}
+ operation.compareFn = function (actor) {
+ return actor.constructor && actor.constructor.name == 'St_Icon'
+ }
+ operation.applyFn = (actor, operationIdx) => {
+ this._overrideStyle(actor, trayIconSizeStyleLine, operationIdx)
+ }
+ this._rightBoxOperations.push(operation)
- if(trayPadding >= 0) {
- let operation = {};
- let trayPaddingStyleLine;
+ let trayContentSizeStyleLine = 'font-size: %dpx'.format(trayContentSize)
+ operation = {}
+ operation.compareFn = function (actor) {
+ return actor.constructor && actor.constructor.name == 'St_Label'
+ }
+ operation.applyFn = (actor, operationIdx) => {
+ this._overrideStyle(actor, trayContentSizeStyleLine, operationIdx)
+ }
+ this._rightBoxOperations.push(operation)
- if (isVertical) {
- trayPaddingStyleLine = paddingStyle.format(trayPadding);
- operation.compareFn = function (actor) {
- let parent = actor.get_parent();
- return ((parent && parent.has_style_class_name && (parent.has_style_class_name('panel-button') && !parent.has_style_class_name('clock-display'))) ||
- (actor.has_style_class_name && actor.has_style_class_name('clock')));
- };
- } else {
- trayPaddingStyleLine = '-natural-hpadding: %dpx'.format(trayPadding);
- if (trayPadding < 6) {
- trayPaddingStyleLine += '; -minimum-hpadding: %dpx'.format(trayPadding);
- }
-
- operation.compareFn = function (actor) {
- return (actor.has_style_class_name && actor.has_style_class_name('panel-button'));
- };
- }
-
- operation.applyFn = (actor, operationIdx) => {
- this._overrideStyle(actor, trayPaddingStyleLine, operationIdx);
- this._refreshPanelButton(actor);
- };
- this._rightBoxOperations.push(operation);
- }
-
- let statusIconPadding = SETTINGS.get_int('status-icon-padding');
- if(statusIconPadding >= 0) {
- let statusIconPaddingStyleLine = paddingStyle.format(statusIconPadding)
- let operation = {};
- operation.compareFn = function (actor) {
- return (actor.has_style_class_name && actor.has_style_class_name('system-status-icon'));
- };
- operation.applyFn = (actor, operationIdx) => {
- this._overrideStyle(actor, statusIconPaddingStyleLine, operationIdx);
- };
- this._rightBoxOperations.push(operation);
- }
-
- let trayContentSize = SETTINGS.get_int('tray-size');
- if(trayContentSize > 0) {
- let trayIconSizeStyleLine = 'icon-size: %dpx'.format(trayContentSize)
- let operation = {};
- operation.compareFn = function (actor) {
- return (actor.constructor && actor.constructor.name == 'St_Icon');
- };
- operation.applyFn = (actor, operationIdx) => {
- this._overrideStyle(actor, trayIconSizeStyleLine, operationIdx);
- };
- this._rightBoxOperations.push(operation);
-
- let trayContentSizeStyleLine = 'font-size: %dpx'.format(trayContentSize)
- operation = {};
- operation.compareFn = function (actor) {
- return (actor.constructor && actor.constructor.name == 'St_Label');
- };
- operation.applyFn = (actor, operationIdx) => {
- this._overrideStyle(actor, trayContentSizeStyleLine, operationIdx);
- };
- this._rightBoxOperations.push(operation);
-
- this._overrideStyle(this.panel._rightBox, trayContentSizeStyleLine, 0);
- this._overrideStyle(this.panel._centerBox, trayContentSizeStyleLine, 0);
- }
-
- // center box has been moved next to the right box and will be treated the same
- this._centerBoxOperations = this._rightBoxOperations;
-
- this._leftBoxOperations = [];
-
- let leftboxPadding = SETTINGS.get_int('leftbox-padding');
- if(leftboxPadding >= 0) {
- let leftboxPaddingStyleLine = paddingStyle.format(leftboxPadding);
- let operation = {};
- operation.compareFn = function (actor) {
- let parent = actor.get_parent();
- return (parent && parent.has_style_class_name && parent.has_style_class_name('panel-button'));
- };
- operation.applyFn = (actor, operationIdx) => {
- this._overrideStyle(actor, leftboxPaddingStyleLine, operationIdx);
- };
- this._leftBoxOperations.push(operation);
- }
-
- let leftboxContentSize = SETTINGS.get_int('leftbox-size');
- if(leftboxContentSize > 0) {
- let leftboxIconSizeStyleLine = 'icon-size: %dpx'.format(leftboxContentSize)
- let operation = {};
- operation.compareFn = function (actor) {
- return (actor.constructor && actor.constructor.name == 'St_Icon');
- };
- operation.applyFn = (actor, operationIdx) => {
- this._overrideStyle(actor, leftboxIconSizeStyleLine, operationIdx);
- };
- this._leftBoxOperations.push(operation);
-
- let leftboxContentSizeStyleLine = 'font-size: %dpx'.format(leftboxContentSize)
- operation = {};
- operation.compareFn = function (actor) {
- return (actor.constructor && actor.constructor.name == 'St_Label');
- };
- operation.applyFn = (actor, operationIdx) => {
- this._overrideStyle(actor, leftboxContentSizeStyleLine, operationIdx);
- };
- this._leftBoxOperations.push(operation);
-
- this._overrideStyle(this.panel._leftBox, leftboxContentSizeStyleLine, 0);
- }
-
- this._applyStylesRecursively();
-
- /* connect signal */
- this._rightBoxActorAddedID = this.panel._rightBox.connect('child-added',
- (container, actor) => {
- if(this._rightBoxOperations.length && !this._ignoreAddedChild)
- this._recursiveApply(actor, this._rightBoxOperations);
-
- this._ignoreAddedChild = 0;
- }
- );
- this._centerBoxActorAddedID = this.panel._centerBox.connect('child-added',
- (container, actor) => {
- if(this._centerBoxOperations.length && !this._ignoreAddedChild)
- this._recursiveApply(actor, this._centerBoxOperations);
-
- this._ignoreAddedChild = 0;
- }
- );
- this._leftBoxActorAddedID = this.panel._leftBox.connect('child-added',
- (container, actor) => {
- if(this._leftBoxOperations.length)
- this._recursiveApply(actor, this._leftBoxOperations);
- }
- );
+ this._overrideStyle(this.panel._rightBox, trayContentSizeStyleLine, 0)
+ this._overrideStyle(this.panel._centerBox, trayContentSizeStyleLine, 0)
}
- _removeStyles() {
- /* disconnect signal */
- if (this._rightBoxActorAddedID)
- this.panel._rightBox.disconnect(this._rightBoxActorAddedID);
- if (this._centerBoxActorAddedID)
- this.panel._centerBox.disconnect(this._centerBoxActorAddedID);
- if (this._leftBoxActorAddedID)
- this.panel._leftBox.disconnect(this._leftBoxActorAddedID);
+ // center box has been moved next to the right box and will be treated the same
+ this._centerBoxOperations = this._rightBoxOperations
- this._restoreOriginalStyle(this.panel._rightBox);
- this._restoreOriginalStyle(this.panel._centerBox);
- this._restoreOriginalStyle(this.panel._leftBox);
+ this._leftBoxOperations = []
- this._applyStylesRecursively(true);
+ let leftboxPadding = SETTINGS.get_int('leftbox-padding')
+ if (leftboxPadding >= 0) {
+ let leftboxPaddingStyleLine = paddingStyle.format(leftboxPadding)
+ let operation = {}
+ operation.compareFn = function (actor) {
+ let parent = actor.get_parent()
+ return (
+ parent &&
+ parent.has_style_class_name &&
+ parent.has_style_class_name('panel-button')
+ )
+ }
+ operation.applyFn = (actor, operationIdx) => {
+ this._overrideStyle(actor, leftboxPaddingStyleLine, operationIdx)
+ }
+ this._leftBoxOperations.push(operation)
}
- _applyStylesRecursively(restore) {
- /*recurse actors */
- if(this._rightBoxOperations.length) {
- // add the system menu as we move it from the rightbox to the panel to position it independently
- let children = this.panel._rightBox.get_children().concat([this.panel.statusArea[Utils.getSystemMenuInfo().name].container]);
- for(let i in children)
- this._recursiveApply(children[i], this._rightBoxOperations, restore);
- }
+ let leftboxContentSize = SETTINGS.get_int('leftbox-size')
+ if (leftboxContentSize > 0) {
+ let leftboxIconSizeStyleLine = 'icon-size: %dpx'.format(
+ leftboxContentSize,
+ )
+ let operation = {}
+ operation.compareFn = function (actor) {
+ return actor.constructor && actor.constructor.name == 'St_Icon'
+ }
+ operation.applyFn = (actor, operationIdx) => {
+ this._overrideStyle(actor, leftboxIconSizeStyleLine, operationIdx)
+ }
+ this._leftBoxOperations.push(operation)
- if(this._centerBoxOperations.length) {
- // add the date menu as we move it from the centerbox to the panel to position it independently
- let children = this.panel._centerBox.get_children().concat([this.panel.statusArea.dateMenu.container]);
- for(let i in children)
- this._recursiveApply(children[i], this._centerBoxOperations, restore);
- }
+ let leftboxContentSizeStyleLine = 'font-size: %dpx'.format(
+ leftboxContentSize,
+ )
+ operation = {}
+ operation.compareFn = function (actor) {
+ return actor.constructor && actor.constructor.name == 'St_Label'
+ }
+ operation.applyFn = (actor, operationIdx) => {
+ this._overrideStyle(actor, leftboxContentSizeStyleLine, operationIdx)
+ }
+ this._leftBoxOperations.push(operation)
- if(this._leftBoxOperations.length) {
- let children = this.panel._leftBox.get_children();
- for(let i in children)
- this._recursiveApply(children[i], this._leftBoxOperations, restore);
- }
+ this._overrideStyle(this.panel._leftBox, leftboxContentSizeStyleLine, 0)
}
- _recursiveApply(actor, operations, restore) {
- for(let i in operations) {
- let o = operations[i];
- if(o.compareFn(actor))
- if(restore)
- o.restoreFn ? o.restoreFn(actor) : this._restoreOriginalStyle(actor);
- else
- o.applyFn(actor, i);
- }
+ this._applyStylesRecursively()
- if(actor.get_children) {
- let children = actor.get_children();
- for(let i in children) {
- this._recursiveApply(children[i], operations, restore);
- }
- }
- }
-
- _overrideStyle(actor, styleLine, operationIdx) {
- if (actor._dtp_original_inline_style === undefined) {
- actor._dtp_original_inline_style = actor.get_style();
- }
+ /* connect signal */
+ this._rightBoxActorAddedID = this.panel._rightBox.connect(
+ 'child-added',
+ (container, actor) => {
+ if (this._rightBoxOperations.length && !this._ignoreAddedChild)
+ this._recursiveApply(actor, this._rightBoxOperations)
- if(actor._dtp_style_overrides === undefined) {
- actor._dtp_style_overrides = {};
- }
+ this._ignoreAddedChild = 0
+ },
+ )
+ this._centerBoxActorAddedID = this.panel._centerBox.connect(
+ 'child-added',
+ (container, actor) => {
+ if (this._centerBoxOperations.length && !this._ignoreAddedChild)
+ this._recursiveApply(actor, this._centerBoxOperations)
- actor._dtp_style_overrides[operationIdx] = styleLine;
- let newStyleLine = '';
- for(let i in actor._dtp_style_overrides)
- newStyleLine += actor._dtp_style_overrides[i] + '; ';
- actor.set_style(newStyleLine + (actor._dtp_original_inline_style || ''));
- }
+ this._ignoreAddedChild = 0
+ },
+ )
+ this._leftBoxActorAddedID = this.panel._leftBox.connect(
+ 'child-added',
+ (container, actor) => {
+ if (this._leftBoxOperations.length)
+ this._recursiveApply(actor, this._leftBoxOperations)
+ },
+ )
+ }
- _restoreOriginalStyle(actor) {
- if (actor._dtp_original_inline_style !== undefined) {
- actor.set_style(actor._dtp_original_inline_style);
- delete actor._dtp_original_inline_style;
- delete actor._dtp_style_overrides;
- }
+ _removeStyles() {
+ /* disconnect signal */
+ if (this._rightBoxActorAddedID)
+ this.panel._rightBox.disconnect(this._rightBoxActorAddedID)
+ if (this._centerBoxActorAddedID)
+ this.panel._centerBox.disconnect(this._centerBoxActorAddedID)
+ if (this._leftBoxActorAddedID)
+ this.panel._leftBox.disconnect(this._leftBoxActorAddedID)
- if (actor.has_style_class_name('panel-button')) {
- this._refreshPanelButton(actor);
- }
+ this._restoreOriginalStyle(this.panel._rightBox)
+ this._restoreOriginalStyle(this.panel._centerBox)
+ this._restoreOriginalStyle(this.panel._leftBox)
+
+ this._applyStylesRecursively(true)
+ }
+
+ _applyStylesRecursively(restore) {
+ /*recurse actors */
+ if (this._rightBoxOperations.length) {
+ // add the system menu as we move it from the rightbox to the panel to position it independently
+ let children = this.panel._rightBox
+ .get_children()
+ .concat([
+ this.panel.statusArea[Utils.getSystemMenuInfo().name].container,
+ ])
+ for (let i in children)
+ this._recursiveApply(children[i], this._rightBoxOperations, restore)
}
- _refreshPanelButton(actor) {
- if (actor.visible) {
- //force gnome 3.34+ to refresh (having problem with the -natural-hpadding)
- let parent = actor.get_parent();
- let children = parent.get_children();
- let actorIndex = 0;
-
- if (children.length > 1) {
- actorIndex = children.indexOf(actor);
- }
-
- this._ignoreAddedChild = [this.panel._centerBox, this.panel._rightBox].indexOf(parent) >= 0;
-
- parent.remove_child(actor);
- parent.insert_child_at_index(actor, actorIndex);
- }
+ if (this._centerBoxOperations.length) {
+ // add the date menu as we move it from the centerbox to the panel to position it independently
+ let children = this.panel._centerBox
+ .get_children()
+ .concat([this.panel.statusArea.dateMenu.container])
+ for (let i in children)
+ this._recursiveApply(children[i], this._centerBoxOperations, restore)
}
-
+
+ if (this._leftBoxOperations.length) {
+ let children = this.panel._leftBox.get_children()
+ for (let i in children)
+ this._recursiveApply(children[i], this._leftBoxOperations, restore)
+ }
+ }
+
+ _recursiveApply(actor, operations, restore) {
+ for (let i in operations) {
+ let o = operations[i]
+ if (o.compareFn(actor))
+ if (restore)
+ o.restoreFn ? o.restoreFn(actor) : this._restoreOriginalStyle(actor)
+ else o.applyFn(actor, i)
+ }
+
+ if (actor.get_children) {
+ let children = actor.get_children()
+ for (let i in children) {
+ this._recursiveApply(children[i], operations, restore)
+ }
+ }
+ }
+
+ _overrideStyle(actor, styleLine, operationIdx) {
+ if (actor._dtp_original_inline_style === undefined) {
+ actor._dtp_original_inline_style = actor.get_style()
+ }
+
+ if (actor._dtp_style_overrides === undefined) {
+ actor._dtp_style_overrides = {}
+ }
+
+ actor._dtp_style_overrides[operationIdx] = styleLine
+ let newStyleLine = ''
+ for (let i in actor._dtp_style_overrides)
+ newStyleLine += actor._dtp_style_overrides[i] + '; '
+ actor.set_style(newStyleLine + (actor._dtp_original_inline_style || ''))
+ }
+
+ _restoreOriginalStyle(actor) {
+ if (actor._dtp_original_inline_style !== undefined) {
+ actor.set_style(actor._dtp_original_inline_style)
+ delete actor._dtp_original_inline_style
+ delete actor._dtp_style_overrides
+ }
+
+ if (actor.has_style_class_name('panel-button')) {
+ this._refreshPanelButton(actor)
+ }
+ }
+
+ _refreshPanelButton(actor) {
+ if (actor.visible) {
+ //force gnome 3.34+ to refresh (having problem with the -natural-hpadding)
+ let parent = actor.get_parent()
+ let children = parent.get_children()
+ let actorIndex = 0
+
+ if (children.length > 1) {
+ actorIndex = children.indexOf(actor)
+ }
+
+ this._ignoreAddedChild =
+ [this.panel._centerBox, this.panel._rightBox].indexOf(parent) >= 0
+
+ parent.remove_child(actor)
+ parent.insert_child_at_index(actor, actorIndex)
+ }
+ }
}
diff --git a/prefs.js b/prefs.js
index db51cdb..f670cce 100644
--- a/prefs.js
+++ b/prefs.js
@@ -20,28 +20,32 @@
* Some code was also adapted from the upstream Gnome Shell source code.
*/
-import GdkPixbuf from 'gi://GdkPixbuf';
-import Gio from 'gi://Gio';
-import GLib from 'gi://GLib';
-import GObject from 'gi://GObject';
-import Gtk from 'gi://Gtk';
-import Gdk from 'gi://Gdk';
+import GdkPixbuf from 'gi://GdkPixbuf'
+import Gio from 'gi://Gio'
+import GLib from 'gi://GLib'
+import GObject from 'gi://GObject'
+import Gtk from 'gi://Gtk'
+import Gdk from 'gi://Gdk'
-import * as PanelSettings from './panelSettings.js';
-import * as Pos from './panelPositions.js';
+import * as PanelSettings from './panelSettings.js'
+import * as Pos from './panelPositions.js'
-import {ExtensionPreferences, gettext as _, ngettext} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
+import {
+ ExtensionPreferences,
+ gettext as _,
+ ngettext,
+} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'
-const SCALE_UPDATE_TIMEOUT = 500;
-const DEFAULT_PANEL_SIZES = [ 128, 96, 64, 48, 32, 24, 16 ];
-const DEFAULT_FONT_SIZES = [ 96, 64, 48, 32, 24, 16, 0 ];
-const DEFAULT_MARGIN_SIZES = [ 32, 24, 16, 12, 8, 4, 0 ];
-const DEFAULT_PADDING_SIZES = [ 32, 24, 16, 12, 8, 4, 0, -1 ];
+const SCALE_UPDATE_TIMEOUT = 500
+const DEFAULT_PANEL_SIZES = [128, 96, 64, 48, 32, 24, 16]
+const DEFAULT_FONT_SIZES = [96, 64, 48, 32, 24, 16, 0]
+const DEFAULT_MARGIN_SIZES = [32, 24, 16, 12, 8, 4, 0]
+const DEFAULT_PADDING_SIZES = [32, 24, 16, 12, 8, 4, 0, -1]
// Minimum length could be 0, but a higher value may help prevent confusion about where the panel went.
-const LENGTH_MARKS = [ 100, 90, 80, 70, 60, 50, 40, 30, 20, 10 ];
-const MAX_WINDOW_INDICATOR = 4;
+const LENGTH_MARKS = [100, 90, 80, 70, 60, 50, 40, 30, 20, 10]
+const MAX_WINDOW_INDICATOR = 4
-const SCHEMA_PATH = '/org/gnome/shell/extensions/dash-to-panel/';
+const SCHEMA_PATH = '/org/gnome/shell/extensions/dash-to-panel/'
/**
* This function was copied from the activities-config extension
@@ -49,2446 +53,3807 @@ const SCHEMA_PATH = '/org/gnome/shell/extensions/dash-to-panel/';
* by Norman L. Smith.
*/
function cssHexString(css) {
- let rrggbb = '#';
- let start;
- for (let loop = 0; loop < 3; loop++) {
- let end = 0;
- let xx = '';
- for (let loop = 0; loop < 2; loop++) {
- while (true) {
- let x = css.slice(end, end + 1);
- if ((x == '(') || (x == ',') || (x == ')'))
- break;
- end++;
- }
- if (loop == 0) {
- end++;
- start = end;
- }
- }
- xx = parseInt(css.slice(start, end)).toString(16);
- if (xx.length == 1)
- xx = '0' + xx;
- rrggbb += xx;
- css = css.slice(end);
+ let rrggbb = '#'
+ let start
+ for (let loop = 0; loop < 3; loop++) {
+ let end = 0
+ let xx = ''
+ for (let loop = 0; loop < 2; loop++) {
+ while (true) {
+ let x = css.slice(end, end + 1)
+ if (x == '(' || x == ',' || x == ')') break
+ end++
+ }
+ if (loop == 0) {
+ end++
+ start = end
+ }
}
- return rrggbb;
+ xx = parseInt(css.slice(start, end)).toString(16)
+ if (xx.length == 1) xx = '0' + xx
+ rrggbb += xx
+ css = css.slice(end)
+ }
+ return rrggbb
}
function setShortcut(settings, shortcutName) {
- let shortcut_text = settings.get_string(shortcutName + '-text');
- let [success, key, mods] = Gtk.accelerator_parse(shortcut_text);
+ let shortcut_text = settings.get_string(shortcutName + '-text')
+ let [success, key, mods] = Gtk.accelerator_parse(shortcut_text)
- if (success && Gtk.accelerator_valid(key, mods)) {
- let shortcut = Gtk.accelerator_name(key, mods);
- settings.set_strv(shortcutName, [shortcut]);
- }
- else {
- settings.set_strv(shortcutName, []);
- }
+ if (success && Gtk.accelerator_valid(key, mods)) {
+ let shortcut = Gtk.accelerator_name(key, mods)
+ settings.set_strv(shortcutName, [shortcut])
+ } else {
+ settings.set_strv(shortcutName, [])
+ }
}
function checkHotkeyPrefix(settings) {
- settings.delay();
+ settings.delay()
- let hotkeyPrefix = settings.get_string('hotkey-prefix-text');
- if (hotkeyPrefix == 'Super')
- hotkeyPrefix = '';
- else if (hotkeyPrefix == 'SuperAlt')
- hotkeyPrefix = '';
- let [ , , mods] = Gtk.accelerator_parse(hotkeyPrefix);
- let [ , , shift_mods] = Gtk.accelerator_parse('' + hotkeyPrefix);
- let [ , , ctrl_mods] = Gtk.accelerator_parse('' + hotkeyPrefix);
+ let hotkeyPrefix = settings.get_string('hotkey-prefix-text')
+ if (hotkeyPrefix == 'Super') hotkeyPrefix = ''
+ else if (hotkeyPrefix == 'SuperAlt') hotkeyPrefix = ''
+ let [, , mods] = Gtk.accelerator_parse(hotkeyPrefix)
+ let [, , shift_mods] = Gtk.accelerator_parse('' + hotkeyPrefix)
+ let [, , ctrl_mods] = Gtk.accelerator_parse('' + hotkeyPrefix)
- let numHotkeys = 10;
- for (let i = 1; i <= numHotkeys; i++) {
- let number = i;
- if (number == 10)
- number = 0;
- let key = Gdk.keyval_from_name(number.toString());
- let key_kp = Gdk.keyval_from_name('KP_' + number.toString());
- if (Gtk.accelerator_valid(key, mods)) {
- let shortcut = Gtk.accelerator_name(key, mods);
- let shortcut_kp = Gtk.accelerator_name(key_kp, mods);
+ let numHotkeys = 10
+ for (let i = 1; i <= numHotkeys; i++) {
+ let number = i
+ if (number == 10) number = 0
+ let key = Gdk.keyval_from_name(number.toString())
+ let key_kp = Gdk.keyval_from_name('KP_' + number.toString())
+ if (Gtk.accelerator_valid(key, mods)) {
+ let shortcut = Gtk.accelerator_name(key, mods)
+ let shortcut_kp = Gtk.accelerator_name(key_kp, mods)
- // Setup shortcut strings
- settings.set_strv('app-hotkey-' + i, [shortcut]);
- settings.set_strv('app-hotkey-kp-' + i, [shortcut_kp]);
+ // Setup shortcut strings
+ settings.set_strv('app-hotkey-' + i, [shortcut])
+ settings.set_strv('app-hotkey-kp-' + i, [shortcut_kp])
- // With
- shortcut = Gtk.accelerator_name(key, shift_mods);
- shortcut_kp = Gtk.accelerator_name(key_kp, shift_mods);
- settings.set_strv('app-shift-hotkey-' + i, [shortcut]);
- settings.set_strv('app-shift-hotkey-kp-' + i, [shortcut_kp]);
+ // With
+ shortcut = Gtk.accelerator_name(key, shift_mods)
+ shortcut_kp = Gtk.accelerator_name(key_kp, shift_mods)
+ settings.set_strv('app-shift-hotkey-' + i, [shortcut])
+ settings.set_strv('app-shift-hotkey-kp-' + i, [shortcut_kp])
- // With
- shortcut = Gtk.accelerator_name(key, ctrl_mods);
- shortcut_kp = Gtk.accelerator_name(key_kp, ctrl_mods);
- settings.set_strv('app-ctrl-hotkey-' + i, [shortcut]);
- settings.set_strv('app-ctrl-hotkey-kp-' + i, [shortcut_kp]);
- }
- else {
- // Reset default settings for the relevant keys if the
- // accelerators are invalid
- let keys = ['app-hotkey-' + i, 'app-shift-hotkey-' + i, 'app-ctrl-hotkey-' + i, // Regular numbers
- 'app-hotkey-kp-' + i, 'app-shift-hotkey-kp-' + i, 'app-ctrl-hotkey-kp-' + i]; // Key-pad numbers
- keys.forEach(function(val) {
- settings.set_value(val, settings.get_default_value(val));
- }, this);
- }
+ // With
+ shortcut = Gtk.accelerator_name(key, ctrl_mods)
+ shortcut_kp = Gtk.accelerator_name(key_kp, ctrl_mods)
+ settings.set_strv('app-ctrl-hotkey-' + i, [shortcut])
+ settings.set_strv('app-ctrl-hotkey-kp-' + i, [shortcut_kp])
+ } else {
+ // Reset default settings for the relevant keys if the
+ // accelerators are invalid
+ let keys = [
+ 'app-hotkey-' + i,
+ 'app-shift-hotkey-' + i,
+ 'app-ctrl-hotkey-' + i, // Regular numbers
+ 'app-hotkey-kp-' + i,
+ 'app-shift-hotkey-kp-' + i,
+ 'app-ctrl-hotkey-kp-' + i,
+ ] // Key-pad numbers
+ keys.forEach(function (val) {
+ settings.set_value(val, settings.get_default_value(val))
+ }, this)
}
+ }
- settings.apply();
+ settings.apply()
}
function mergeObjects(main, bck) {
- for (const prop in bck) {
- if (!main.hasOwnProperty(prop) && bck.hasOwnProperty(prop)) {
- main[prop] = bck[prop];
- }
+ for (const prop in bck) {
+ if (!main.hasOwnProperty(prop) && bck.hasOwnProperty(prop)) {
+ main[prop] = bck[prop]
}
+ }
- return main;
+ return main
}
const Preferences = class {
+ constructor(window, settings, path) {
+ // this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.dash-to-panel');
+ this._rtl = Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL
+ this._builder = new Gtk.Builder()
+ this._builder.set_scope(new BuilderScope(this))
+ this._settings = settings
+ this._path = path
- constructor(window, settings, path) {
- // this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.dash-to-panel');
- this._rtl = (Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL);
- this._builder = new Gtk.Builder();
- this._builder.set_scope(new BuilderScope(this));
- this._settings = settings;
- this._path = path;
+ this._metadata = ExtensionPreferences.lookupByURL(import.meta.url).metadata
+ this._builder.set_translation_domain(this._metadata['gettext-domain'])
- this._metadata = ExtensionPreferences.lookupByURL(import.meta.url).metadata;
- this._builder.set_translation_domain(this._metadata['gettext-domain']);
+ window.set_search_enabled(true)
- window.set_search_enabled(true);
+ // dialogs
+ this._builder.add_from_file(
+ this._path + '/ui/BoxAnimateAppIconHoverOptions.ui',
+ )
+ this._builder.add_from_file(
+ this._path + '/ui/BoxHighlightAppIconHoverOptions.ui',
+ )
+ this._builder.add_from_file(this._path + '/ui/BoxDotOptions.ui')
+ this._builder.add_from_file(this._path + '/ui/BoxShowDesktopOptions.ui')
+ this._builder.add_from_file(this._path + '/ui/BoxDynamicOpacityOptions.ui')
+ this._builder.add_from_file(this._path + '/ui/BoxIntellihideOptions.ui')
+ this._builder.add_from_file(
+ this._path + '/ui/BoxShowApplicationsOptions.ui',
+ )
+ this._builder.add_from_file(this._path + '/ui/BoxWindowPreviewOptions.ui')
+ this._builder.add_from_file(this._path + '/ui/BoxGroupAppsOptions.ui')
+ this._builder.add_from_file(this._path + '/ui/BoxMiddleClickOptions.ui')
+ this._builder.add_from_file(this._path + '/ui/BoxOverlayShortcut.ui')
+ this._builder.add_from_file(this._path + '/ui/BoxSecondaryMenuOptions.ui')
+ this._builder.add_from_file(this._path + '/ui/BoxScrollPanelOptions.ui')
+ this._builder.add_from_file(this._path + '/ui/BoxScrollIconOptions.ui')
+ this._builder.add_from_file(this._path + '/ui/BoxAdvancedOptions.ui')
- // dialogs
- this._builder.add_from_file(this._path + '/ui/BoxAnimateAppIconHoverOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxHighlightAppIconHoverOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxDotOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxShowDesktopOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxDynamicOpacityOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxIntellihideOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxShowApplicationsOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxWindowPreviewOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxGroupAppsOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxMiddleClickOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxOverlayShortcut.ui');
- this._builder.add_from_file(this._path + '/ui/BoxSecondaryMenuOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxScrollPanelOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxScrollIconOptions.ui');
- this._builder.add_from_file(this._path + '/ui/BoxAdvancedOptions.ui');
+ // pages
+ this._builder.add_from_file(this._path + '/ui/SettingsPosition.ui')
+ let pagePosition = this._builder.get_object('position')
+ window.add(pagePosition)
- // pages
- this._builder.add_from_file(this._path + '/ui/SettingsPosition.ui');
- let pagePosition = this._builder.get_object('position');
- window.add(pagePosition);
+ this._builder.add_from_file(this._path + '/ui/SettingsStyle.ui')
+ let pageStyle = this._builder.get_object('style')
+ window.add(pageStyle)
- this._builder.add_from_file(this._path + '/ui/SettingsStyle.ui');
- let pageStyle = this._builder.get_object('style');
- window.add(pageStyle);
+ this._builder.add_from_file(this._path + '/ui/SettingsBehavior.ui')
+ let pageBehavior = this._builder.get_object('behavior')
+ window.add(pageBehavior)
- this._builder.add_from_file(this._path + '/ui/SettingsBehavior.ui');
- let pageBehavior = this._builder.get_object('behavior');
- window.add(pageBehavior);
+ this._builder.add_from_file(this._path + '/ui/SettingsAction.ui')
+ let pageAction = this._builder.get_object('action')
+ window.add(pageAction)
- this._builder.add_from_file(this._path + '/ui/SettingsAction.ui');
- let pageAction = this._builder.get_object('action');
- window.add(pageAction);
+ this._builder.add_from_file(this._path + '/ui/SettingsFineTune.ui')
+ let pageFineTune = this._builder.get_object('finetune')
+ window.add(pageFineTune)
- this._builder.add_from_file(this._path + '/ui/SettingsFineTune.ui');
- let pageFineTune = this._builder.get_object('finetune');
- window.add(pageFineTune);
+ this._builder.add_from_file(this._path + '/ui/SettingsDonation.ui')
+ let pageDonation = this._builder.get_object('donation')
+ window.add(pageDonation)
- this._builder.add_from_file(this._path + '/ui/SettingsDonation.ui');
- let pageDonation = this._builder.get_object('donation');
- window.add(pageDonation);
+ this._builder.add_from_file(this._path + '/ui/SettingsAbout.ui')
+ let pageAbout = this._builder.get_object('about')
+ window.add(pageAbout)
- this._builder.add_from_file(this._path + '/ui/SettingsAbout.ui');
- let pageAbout = this._builder.get_object('about');
- window.add(pageAbout);
+ let listbox = this._builder.get_object('taskbar_display_listbox')
+ let provider = new Gtk.CssProvider()
+ provider.load_from_data('list { background-color: transparent; }', -1)
+ let context = listbox.get_style_context()
+ context.add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
- let listbox = this._builder.get_object('taskbar_display_listbox');
- let provider = new Gtk.CssProvider();
- provider.load_from_data('list { background-color: transparent; }', -1);
- let context = listbox.get_style_context();
- context.add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+ // set the window as notebook, it is being used as parent for dialogs
+ this.notebook = window
- // set the window as notebook, it is being used as parent for dialogs
- this.notebook = window;
+ // Timeout to delay the update of the settings
+ this._panel_size_timeout = 0
+ this._dot_height_timeout = 0
+ this._tray_size_timeout = 0
+ this._leftbox_size_timeout = 0
+ this._appicon_margin_timeout = 0
+ this._appicon_margin_todesktop_timeout = 0
+ this._appicon_margin_toscreenborder_timeout = 0
+ this._appicon_padding_timeout = 0
+ this._opacity_timeout = 0
+ this._tray_padding_timeout = 0
+ this._statusicon_padding_timeout = 0
+ this._leftbox_padding_timeout = 0
+ this._addFormatValueCallbacks()
+ this._bindSettings()
- // Timeout to delay the update of the settings
- this._panel_size_timeout = 0;
- this._dot_height_timeout = 0;
- this._tray_size_timeout = 0;
- this._leftbox_size_timeout = 0;
- this._appicon_margin_timeout = 0;
- this._appicon_margin_todesktop_timeout = 0;
- this._appicon_margin_toscreenborder_timeout = 0;
- this._appicon_padding_timeout = 0;
- this._opacity_timeout = 0;
- this._tray_padding_timeout = 0;
- this._statusicon_padding_timeout = 0;
- this._leftbox_padding_timeout = 0;
- this._addFormatValueCallbacks();
- this._bindSettings();
+ let maybeGoToPage = () => {
+ let targetPageName = settings.get_string('target-prefs-page')
- let maybeGoToPage = () => {
- let targetPageName = settings.get_string('target-prefs-page')
-
- if (targetPageName) {
- window.set_visible_page_name(targetPageName)
- settings.set_string('target-prefs-page', '')
- }
- }
-
- settings.connect('changed::target-prefs-page', maybeGoToPage);
-
- maybeGoToPage();
+ if (targetPageName) {
+ window.set_visible_page_name(targetPageName)
+ settings.set_string('target-prefs-page', '')
+ }
}
- /**
- * Connect signals
- */
- _connector(builder, object, signal, handler) {
- object.connect(signal, this._SignalHandler[handler].bind(this));
+ settings.connect('changed::target-prefs-page', maybeGoToPage)
+
+ maybeGoToPage()
+ }
+
+ /**
+ * Connect signals
+ */
+ _connector(builder, object, signal, handler) {
+ object.connect(signal, this._SignalHandler[handler].bind(this))
+ }
+
+ _updateVerticalRelatedOptions() {
+ let position = this._getPanelPosition(this._currentMonitorIndex)
+ let isVertical = position == Pos.LEFT || position == Pos.RIGHT
+ let showDesktopWidthLabel = this._builder.get_object(
+ 'show_showdesktop_width_label',
+ )
+
+ showDesktopWidthLabel.set_title(
+ isVertical
+ ? _('Show Desktop button height (px)')
+ : _('Show Desktop button width (px)'),
+ )
+
+ this._displayPanelPositionsForMonitor(this._currentMonitorIndex)
+ }
+
+ _maybeDisableTopPosition() {
+ let keepTopPanel = this._settings.get_boolean('stockgs-keep-top-panel')
+ let monitorSync = this._settings.get_boolean(
+ 'panel-element-positions-monitors-sync',
+ )
+ let topAvailable =
+ !keepTopPanel ||
+ (!monitorSync && this._currentMonitorIndex != this.monitors[0])
+ let topRadio = this._builder.get_object('position_top_button')
+
+ topRadio.set_sensitive(topAvailable)
+ topRadio.set_tooltip_text(
+ !topAvailable
+ ? _('Unavailable when gnome-shell top panel is present')
+ : '',
+ )
+ }
+
+ _getPanelPosition(monitorIndex) {
+ return PanelSettings.getPanelPosition(this._settings, monitorIndex)
+ }
+
+ _setPanelPosition(position) {
+ const monitorSync = this._settings.get_boolean(
+ 'panel-element-positions-monitors-sync',
+ )
+ const monitorsToSetFor = monitorSync
+ ? this.monitors
+ : [this._currentMonitorIndex]
+ monitorsToSetFor.forEach((monitorIndex) => {
+ PanelSettings.setPanelPosition(this._settings, monitorIndex, position)
+ })
+ this._setAnchorLabels(this._currentMonitorIndex)
+ }
+
+ _setPositionRadios(position) {
+ this._ignorePositionRadios = true
+
+ switch (position) {
+ case Pos.BOTTOM:
+ this._builder.get_object('position_bottom_button').set_active(true)
+ break
+ case Pos.TOP:
+ this._builder.get_object('position_top_button').set_active(true)
+ break
+ case Pos.LEFT:
+ this._builder.get_object('position_left_button').set_active(true)
+ break
+ case Pos.RIGHT:
+ this._builder.get_object('position_right_button').set_active(true)
+ break
}
- _updateVerticalRelatedOptions() {
- let position = this._getPanelPosition(this._currentMonitorIndex);
- let isVertical = position == Pos.LEFT || position == Pos.RIGHT;
- let showDesktopWidthLabel = this._builder.get_object('show_showdesktop_width_label');
+ this._ignorePositionRadios = false
+ }
- showDesktopWidthLabel.set_title(isVertical ? _('Show Desktop button height (px)') : _('Show Desktop button width (px)'));
+ /**
+ * Set panel anchor combo labels according to whether the monitor's panel is vertical
+ * or horizontal, or if all monitors' panels are being configured and they are a mix
+ * of vertical and horizontal.
+ */
+ _setAnchorLabels(currentMonitorIndex) {
+ const monitorSync = this._settings.get_boolean(
+ 'panel-element-positions-monitors-sync',
+ )
+ const monitorsToSetFor = monitorSync ? this.monitors : [currentMonitorIndex]
+ const allVertical = monitorsToSetFor.every((i) => {
+ const position = PanelSettings.getPanelPosition(this._settings, i)
+ return position === Pos.LEFT || position === Pos.RIGHT
+ })
+ const allHorizontal = monitorsToSetFor.every((i) => {
+ const position = PanelSettings.getPanelPosition(this._settings, i)
+ return position === Pos.TOP || position === Pos.BOTTOM
+ })
- this._displayPanelPositionsForMonitor(this._currentMonitorIndex);
+ const anchor_combo = this._builder.get_object('panel_anchor_combo')
+ anchor_combo.remove_all()
+
+ if (allHorizontal) {
+ anchor_combo.append(Pos.START, _('Left'))
+ anchor_combo.append(Pos.MIDDLE, _('Center'))
+ anchor_combo.append(Pos.END, _('Right'))
+ } else if (allVertical) {
+ anchor_combo.append(Pos.START, _('Top'))
+ anchor_combo.append(Pos.MIDDLE, _('Middle'))
+ anchor_combo.append(Pos.END, _('Bottom'))
+ } else {
+ // Setting for a mix of horizontal and vertical panels on different monitors.
+ anchor_combo.append(Pos.START, _('Start'))
+ anchor_combo.append(Pos.MIDDLE, _('Middle'))
+ anchor_combo.append(Pos.END, _('End'))
}
- _maybeDisableTopPosition() {
- let keepTopPanel = this._settings.get_boolean('stockgs-keep-top-panel');
- let monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync');
- let topAvailable = !keepTopPanel || (!monitorSync && this._currentMonitorIndex != this.monitors[0]);
- let topRadio = this._builder.get_object('position_top_button');
+ // Set combo box after re-populating its options. But only if it's for a single-panel
+ // configuration, or a multi-panel configuration where they all have the same anchor
+ // setting. So don't set the combo box if there is a multi-panel configuration with
+ // different anchor settings.
+ const someAnchor = PanelSettings.getPanelAnchor(
+ this._settings,
+ currentMonitorIndex,
+ )
+ if (
+ monitorsToSetFor.every(
+ (i) => PanelSettings.getPanelAnchor(this._settings, i) === someAnchor,
+ )
+ ) {
+ const panel_anchor = PanelSettings.getPanelAnchor(
+ this._settings,
+ currentMonitorIndex,
+ )
+ this._builder.get_object('panel_anchor_combo').set_active_id(panel_anchor)
+ }
+ }
- topRadio.set_sensitive(topAvailable);
- topRadio.set_tooltip_text(!topAvailable ? _('Unavailable when gnome-shell top panel is present') : '');
+ /**
+ * When a monitor is selected, update the widgets for panel position, size, anchoring,
+ * and contents so they accurately show the settings for the panel on that monitor.
+ */
+ _updateWidgetSettingsForMonitor(monitorIndex) {
+ // Update display of panel screen position setting
+ this._maybeDisableTopPosition()
+ const panelPosition = this._getPanelPosition(monitorIndex)
+ this._setPositionRadios(panelPosition)
+
+ // Update display of thickness, length, and anchor settings
+ const panel_size_scale = this._builder.get_object('panel_size_scale')
+ const size = PanelSettings.getPanelSize(this._settings, monitorIndex)
+ panel_size_scale.set_value(size)
+
+ const panel_length_scale = this._builder.get_object('panel_length_scale')
+ const length = PanelSettings.getPanelLength(this._settings, monitorIndex)
+ panel_length_scale.set_value(length)
+ this._setAnchorWidgetSensitivity(length)
+
+ this._setAnchorLabels(monitorIndex)
+
+ // Update display of panel content settings
+ this._displayPanelPositionsForMonitor(monitorIndex)
+ }
+
+ /**
+ * Anchor is only relevant if panel length is less than 100%. Enable or disable
+ * anchor widget sensitivity accordingly.
+ */
+ _setAnchorWidgetSensitivity(panelLength) {
+ const isPartialLength = panelLength < 100
+ this._builder
+ .get_object('panel_anchor_label')
+ .set_sensitive(isPartialLength)
+ this._builder
+ .get_object('panel_anchor_combo')
+ .set_sensitive(isPartialLength)
+ }
+
+ _displayPanelPositionsForMonitor(monitorIndex) {
+ let taskbarListBox = this._builder.get_object('taskbar_display_listbox')
+
+ while (taskbarListBox.get_first_child()) {
+ taskbarListBox.remove(taskbarListBox.get_first_child())
}
- _getPanelPosition(monitorIndex) {
- return PanelSettings.getPanelPosition(this._settings, monitorIndex);
+ let labels = {}
+ let panelPosition = this._getPanelPosition(monitorIndex)
+ let isVertical = panelPosition == Pos.LEFT || panelPosition == Pos.RIGHT
+ let panelElementPositionsSettings = PanelSettings.getSettingsJson(
+ this._settings,
+ 'panel-element-positions',
+ )
+ let panelElementPositions =
+ panelElementPositionsSettings[monitorIndex] || Pos.defaults
+ let updateElementsSettings = () => {
+ let newPanelElementPositions = []
+ let monitorSync = this._settings.get_boolean(
+ 'panel-element-positions-monitors-sync',
+ )
+ let monitors = monitorSync ? this.monitors : [monitorIndex]
+
+ let child = taskbarListBox.get_first_child()
+ while (child != null) {
+ newPanelElementPositions.push({
+ element: child.id,
+ visible: child.visibleToggleBtn.get_active(),
+ position: child.positionCombo.get_active_id(),
+ })
+ child = child.get_next_sibling()
+ }
+
+ monitors.forEach(
+ (m) => (panelElementPositionsSettings[m] = newPanelElementPositions),
+ )
+ this._settings.set_string(
+ 'panel-element-positions',
+ JSON.stringify(panelElementPositionsSettings),
+ )
}
- _setPanelPosition(position) {
- const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync');
- const monitorsToSetFor = monitorSync ? this.monitors : [this._currentMonitorIndex];
- monitorsToSetFor.forEach(monitorIndex => {
- PanelSettings.setPanelPosition(this._settings, monitorIndex, position);
- });
- this._setAnchorLabels(this._currentMonitorIndex);
- }
+ labels[Pos.SHOW_APPS_BTN] = _('Show Applications button')
+ labels[Pos.ACTIVITIES_BTN] = _('Activities button')
+ labels[Pos.TASKBAR] = _('Taskbar')
+ labels[Pos.DATE_MENU] = _('Date menu')
+ labels[Pos.SYSTEM_MENU] = _('System menu')
+ labels[Pos.LEFT_BOX] = _('Left box')
+ labels[Pos.CENTER_BOX] = _('Center box')
+ labels[Pos.RIGHT_BOX] = _('Right box')
+ labels[Pos.DESKTOP_BTN] = _('Desktop button')
- _setPositionRadios(position) {
- this._ignorePositionRadios = true;
+ panelElementPositions.forEach((el) => {
+ let row = new Gtk.ListBoxRow()
+ let grid = new Gtk.Grid({
+ margin_start: 12,
+ margin_end: 12,
+ column_spacing: 8,
+ })
+ let upDownGrid = new Gtk.Grid({ column_spacing: 2 })
+ let upBtn = new Gtk.Button({ tooltip_text: _('Move up') })
+ let upImg = new Gtk.Image({ icon_name: 'go-up-symbolic', pixel_size: 12 })
+ let downBtn = new Gtk.Button({ tooltip_text: _('Move down') })
+ let downImg = new Gtk.Image({
+ icon_name: 'go-down-symbolic',
+ pixel_size: 12,
+ })
+ let visibleToggleBtn = new Gtk.ToggleButton({
+ label: _('Visible'),
+ active: el.visible,
+ })
+ let positionCombo = new Gtk.ComboBoxText({
+ tooltip_text: _('Select element position'),
+ })
+ let upDownClickHandler = (limit) => {
+ let index = row.get_index()
- switch (position) {
- case Pos.BOTTOM:
- this._builder.get_object('position_bottom_button').set_active(true);
- break;
- case Pos.TOP:
- this._builder.get_object('position_top_button').set_active(true);
- break;
- case Pos.LEFT:
- this._builder.get_object('position_left_button').set_active(true);
- break;
- case Pos.RIGHT:
- this._builder.get_object('position_right_button').set_active(true);
- break;
+ if (index != limit) {
+ taskbarListBox.remove(row)
+ taskbarListBox.insert(row, index + (!limit ? -1 : 1))
+ updateElementsSettings()
}
-
- this._ignorePositionRadios = false;
- }
-
- /**
- * Set panel anchor combo labels according to whether the monitor's panel is vertical
- * or horizontal, or if all monitors' panels are being configured and they are a mix
- * of vertical and horizontal.
- */
- _setAnchorLabels(currentMonitorIndex) {
- const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync');
- const monitorsToSetFor = monitorSync ? this.monitors : [currentMonitorIndex];
- const allVertical = monitorsToSetFor.every(i => {
- const position = PanelSettings.getPanelPosition(this._settings, i);
- return position === Pos.LEFT || position === Pos.RIGHT
- });
- const allHorizontal = monitorsToSetFor.every(i => {
- const position = PanelSettings.getPanelPosition(this._settings, i);
- return position === Pos.TOP || position === Pos.BOTTOM;
- });
-
- const anchor_combo = this._builder.get_object('panel_anchor_combo');
- anchor_combo.remove_all();
-
- if (allHorizontal) {
- anchor_combo.append(Pos.START, _('Left'));
- anchor_combo.append(Pos.MIDDLE, _('Center'));
- anchor_combo.append(Pos.END, _('Right'));
- } else if (allVertical) {
- anchor_combo.append(Pos.START, _('Top'));
- anchor_combo.append(Pos.MIDDLE, _('Middle'));
- anchor_combo.append(Pos.END, _('Bottom'));
- } else {
- // Setting for a mix of horizontal and vertical panels on different monitors.
- anchor_combo.append(Pos.START, _('Start'));
- anchor_combo.append(Pos.MIDDLE, _('Middle'));
- anchor_combo.append(Pos.END, _('End'));
- }
-
- // Set combo box after re-populating its options. But only if it's for a single-panel
- // configuration, or a multi-panel configuration where they all have the same anchor
- // setting. So don't set the combo box if there is a multi-panel configuration with
- // different anchor settings.
- const someAnchor = PanelSettings.getPanelAnchor(this._settings, currentMonitorIndex);
- if (monitorsToSetFor.every(i =>
- PanelSettings.getPanelAnchor(this._settings, i) === someAnchor)) {
- const panel_anchor = PanelSettings.getPanelAnchor(this._settings, currentMonitorIndex);
- this._builder.get_object('panel_anchor_combo').set_active_id(panel_anchor);
- }
- }
-
- /**
- * When a monitor is selected, update the widgets for panel position, size, anchoring,
- * and contents so they accurately show the settings for the panel on that monitor.
- */
- _updateWidgetSettingsForMonitor(monitorIndex) {
- // Update display of panel screen position setting
- this._maybeDisableTopPosition();
- const panelPosition = this._getPanelPosition(monitorIndex);
- this._setPositionRadios(panelPosition);
-
- // Update display of thickness, length, and anchor settings
- const panel_size_scale = this._builder.get_object('panel_size_scale');
- const size = PanelSettings.getPanelSize(this._settings, monitorIndex);
- panel_size_scale.set_value(size);
-
- const panel_length_scale = this._builder.get_object('panel_length_scale');
- const length = PanelSettings.getPanelLength(this._settings, monitorIndex);
- panel_length_scale.set_value(length);
- this._setAnchorWidgetSensitivity(length);
-
- this._setAnchorLabels(monitorIndex);
-
- // Update display of panel content settings
- this._displayPanelPositionsForMonitor(monitorIndex);
- }
-
- /**
- * Anchor is only relevant if panel length is less than 100%. Enable or disable
- * anchor widget sensitivity accordingly.
- */
- _setAnchorWidgetSensitivity(panelLength) {
- const isPartialLength = panelLength < 100;
- this._builder.get_object('panel_anchor_label').set_sensitive(isPartialLength);
- this._builder.get_object('panel_anchor_combo').set_sensitive(isPartialLength);
- }
-
- _displayPanelPositionsForMonitor(monitorIndex) {
- let taskbarListBox = this._builder.get_object('taskbar_display_listbox');
-
- while(taskbarListBox.get_first_child())
- {
- taskbarListBox.remove(taskbarListBox.get_first_child());
- }
-
- let labels = {};
- let panelPosition = this._getPanelPosition(monitorIndex);
- let isVertical = panelPosition == Pos.LEFT || panelPosition == Pos.RIGHT;
- let panelElementPositionsSettings = PanelSettings.getSettingsJson(this._settings, 'panel-element-positions');
- let panelElementPositions = panelElementPositionsSettings[monitorIndex] || Pos.defaults;
- let updateElementsSettings = () => {
- let newPanelElementPositions = [];
- let monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync');
- let monitors = monitorSync ? this.monitors : [monitorIndex];
-
- let child = taskbarListBox.get_first_child();
- while (child != null)
- {
- newPanelElementPositions.push({
- element: child.id,
- visible: child.visibleToggleBtn.get_active(),
- position: child.positionCombo.get_active_id()
- });
- child = child.get_next_sibling();
- }
-
- monitors.forEach(m => panelElementPositionsSettings[m] = newPanelElementPositions);
- this._settings.set_string('panel-element-positions', JSON.stringify(panelElementPositionsSettings));
- };
-
-
- labels[Pos.SHOW_APPS_BTN] = _('Show Applications button');
- labels[Pos.ACTIVITIES_BTN] = _('Activities button');
- labels[Pos.TASKBAR] = _('Taskbar');
- labels[Pos.DATE_MENU] = _('Date menu');
- labels[Pos.SYSTEM_MENU] = _('System menu');
- labels[Pos.LEFT_BOX] = _('Left box');
- labels[Pos.CENTER_BOX] = _('Center box');
- labels[Pos.RIGHT_BOX] = _('Right box');
- labels[Pos.DESKTOP_BTN] = _('Desktop button');
-
- panelElementPositions.forEach(el => {
- let row = new Gtk.ListBoxRow();
- let grid = new Gtk.Grid({ margin_start: 12, margin_end: 12, column_spacing: 8 });
- let upDownGrid = new Gtk.Grid({ column_spacing: 2 });
- let upBtn = new Gtk.Button({ tooltip_text: _('Move up') });
- let upImg = new Gtk.Image({ icon_name: 'go-up-symbolic', pixel_size: 12 });
- let downBtn = new Gtk.Button({ tooltip_text: _('Move down') });
- let downImg = new Gtk.Image({ icon_name: 'go-down-symbolic', pixel_size: 12 });
- let visibleToggleBtn = new Gtk.ToggleButton({ label: _('Visible'), active: el.visible });
- let positionCombo = new Gtk.ComboBoxText({ tooltip_text: _('Select element position') });
- let upDownClickHandler = limit => {
- let index = row.get_index();
-
- if (index != limit) {
- taskbarListBox.remove(row);
- taskbarListBox.insert(row, index + (!limit ? -1 : 1));
- updateElementsSettings();
- }
- };
-
- positionCombo.append(Pos.STACKED_TL, isVertical ? _('Stacked to top') : _('Stacked to left'));
- positionCombo.append(Pos.STACKED_BR, isVertical ? _('Stacked to bottom') :_('Stacked to right'));
- positionCombo.append(Pos.CENTERED, _('Centered'));
- positionCombo.append(Pos.CENTERED_MONITOR, _('Monitor Center'));
- positionCombo.set_active_id(el.position);
-
- upBtn.connect('clicked', () => upDownClickHandler(0));
- downBtn.connect('clicked', () => upDownClickHandler(panelElementPositions.length - 1));
- visibleToggleBtn.connect('toggled', () => updateElementsSettings());
- positionCombo.connect('changed', () => updateElementsSettings());
-
- upBtn.set_child(upImg);
- downBtn.set_child(downImg);
-
- upDownGrid.attach(upBtn, 0, 0, 1, 1);
- upDownGrid.attach(downBtn, 1, 0, 1, 1);
-
- grid.attach(upDownGrid, 0, 0, 1, 1);
- grid.attach(new Gtk.Label({ label: labels[el.element], xalign: 0, hexpand: true }), 1, 0, 1, 1);
-
- if (Pos.optionDialogFunctions[el.element]) {
- let cogImg = new Gtk.Image({ icon_name: 'emblem-system-symbolic' });
- let optionsBtn = new Gtk.Button({ tooltip_text: _('More options') });
-
- optionsBtn.get_style_context().add_class('circular');
- optionsBtn.set_child(cogImg);
- grid.attach(optionsBtn, 2, 0, 1, 1);
-
- optionsBtn.connect('clicked', () => this[Pos.optionDialogFunctions[el.element]]());
- }
-
- grid.attach(visibleToggleBtn, 3, 0, 1, 1);
- grid.attach(positionCombo, 4, 0, 1, 1);
-
- row.id = el.element;
- row.visibleToggleBtn = visibleToggleBtn;
- row.positionCombo = positionCombo;
-
- row.set_child(grid);
- taskbarListBox.insert(row, -1);
- });
- }
-
- _createPreferencesDialog(title, content, reset_function = null) {
- let dialog;
-
- dialog = new Gtk.Dialog({ title: title,
- transient_for: this.notebook.get_root(),
- use_header_bar: true,
- modal: true });
-
- // GTK+ leaves positive values for application-defined response ids.
- // Use +1 for the reset action
- if (reset_function != null)
- dialog.add_button(_('Reset to defaults'), 1);
-
- dialog.get_content_area().append(content);
-
- dialog.connect('response', (dialog, id) => {
- if (id == 1) {
- // restore default settings
- if (reset_function)
- reset_function();
- } else {
- // remove the settings content so it doesn't get destroyed;
- dialog.get_content_area().remove(content);
- dialog.destroy();
- }
- return;
- });
-
- return dialog;
- }
-
- _showShowAppsButtonOptions() {
- let box = this._builder.get_object('show_applications_options');
-
- let dialog = this._createPreferencesDialog(_('Show Applications options'), box, () =>
- {
- // restore default settings
- this._settings.set_value('show-apps-icon-side-padding', this._settings.get_default_value('show-apps-icon-side-padding'));
- this._builder.get_object('show_applications_side_padding_spinbutton').set_value(this._settings.get_int('show-apps-icon-side-padding'));
- this._settings.set_value('show-apps-override-escape', this._settings.get_default_value('show-apps-override-escape'));
- handleIconChange.call(this, null);
- });
-
- let fileChooserButton = this._builder.get_object('show_applications_icon_file_filebutton');
- let fileChooser = new Gtk.FileChooserNative({ title: _('Open icon'), transient_for: dialog });
- let fileImage = this._builder.get_object('show_applications_current_icon_image');
- let fileFilter = new Gtk.FileFilter();
- fileFilter.add_pixbuf_formats();
- fileChooser.filter = fileFilter;
-
- let handleIconChange = function(newIconPath) {
- if (newIconPath && GLib.file_test(newIconPath, GLib.FileTest.EXISTS)) {
- let file = Gio.File.new_for_path(newIconPath);
- let pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(file.read(null), 32, 32, true, null);
-
- fileImage.set_from_pixbuf(pixbuf);
- fileChooser.set_file(file);
- fileChooserButton.set_label(newIconPath);
- } else {
- newIconPath = '';
- fileImage.set_from_icon_name('view-app-grid-symbolic');
- let picturesFolder = Gio.File.new_for_path(GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES));
- fileChooser.set_file(picturesFolder);
- fileChooserButton.set_label("(None)");
- }
-
- this._settings.set_string('show-apps-icon-file', newIconPath || '');
- };
-
- fileChooserButton.connect('clicked', () => {
- fileChooser.show();
- });
-
- fileChooser.connect('response', widget => handleIconChange.call(this, widget.get_file().get_path()));
- handleIconChange.call(this, this._settings.get_string('show-apps-icon-file'));
-
- // we have to destroy the fileChooser as well
- dialog.connect('response', (dialog, id) => {
- if (id != 1) {
- fileChooser.destroy();
- }
- return;
- });
-
- dialog.show();
- dialog.set_default_size(1, 1);
- }
-
- _showDesktopButtonOptions() {
- let box = this._builder.get_object('box_show_showdesktop_options');
-
- let dialog = this._createPreferencesDialog(_('Show Desktop options'), box, () =>
- {
- // restore default settings
- this._settings.set_value('showdesktop-button-width', this._settings.get_default_value('showdesktop-button-width'));
- this._builder.get_object('show_showdesktop_width_spinbutton').set_value(this._settings.get_int('showdesktop-button-width'));
-
- this._settings.set_value('desktop-line-use-custom-color', this._settings.get_default_value('desktop-line-use-custom-color'));
-
- this._settings.set_value('show-showdesktop-hover', this._settings.get_default_value('show-showdesktop-hover'));
-
- this._settings.set_value('show-showdesktop-delay', this._settings.get_default_value('show-showdesktop-delay'));
- this._builder.get_object('show_showdesktop_delay_spinbutton').set_value(this._settings.get_int('show-showdesktop-delay'));
-
- this._settings.set_value('show-showdesktop-time', this._settings.get_default_value('show-showdesktop-time'));
- this._builder.get_object('show_showdesktop_time_spinbutton').set_value(this._settings.get_int('show-showdesktop-time'));
- });
-
- this._builder.get_object('show_showdesktop_width_spinbutton').set_value(this._settings.get_int('showdesktop-button-width'));
- this._builder.get_object('show_showdesktop_width_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('showdesktop-button-width', widget.get_value());
- });
-
- this._builder.get_object('show_showdesktop_delay_spinbutton').set_value(this._settings.get_int('show-showdesktop-delay'));
- this._builder.get_object('show_showdesktop_delay_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('show-showdesktop-delay', widget.get_value());
- });
-
- this._builder.get_object('show_showdesktop_time_spinbutton').set_value(this._settings.get_int('show-showdesktop-time'));
- this._builder.get_object('show_showdesktop_time_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('show-showdesktop-time', widget.get_value());
- });
-
- dialog.show();
- dialog.set_default_size(1, 1);
- }
-
- _addFormatValueCallbacks() {
- // position
- this._builder.get_object('panel_size_scale')
- .set_format_value_func((scale, value) => {
- return value + ' px';
- });
-
- // style
- this._builder.get_object('appicon_margin_scale')
- .set_format_value_func((scale, value) => {
- return value + ' px';
- });
- this._builder.get_object('appicon_margin_todesktop_scale')
- .set_format_value_func((scale, value) => {
- return value + ' px';
- });
- this._builder.get_object('appicon_margin_toscreenborder_scale')
- .set_format_value_func((scale, value) => {
- return value + ' px';
- });
-
- this._builder.get_object('appicon_padding_scale')
- .set_format_value_func((scale, value) => {
- return value + ' px';
- });
-
- // fine-tune box1
- this._builder.get_object('tray_size_scale')
- .set_format_value_func((scale, value) => {
- return value + ' px';
- });
-
- this._builder.get_object('leftbox_size_scale')
- .set_format_value_func((scale, value) => {
- return value + ' px';
- });
-
- // fine-tune box2
- this._builder.get_object('tray_padding_scale')
- .set_format_value_func((scale, value) => {
- return value + ' px';
- });
-
- this._builder.get_object('statusicon_padding_scale')
- .set_format_value_func((scale, value) => {
- return value + ' px';
- });
-
- this._builder.get_object('leftbox_padding_scale')
- .set_format_value_func((scale, value) => {
- return value + ' px';
- });
-
- // animate hovering app icons dialog
- this._builder.get_object('animate_appicon_hover_options_duration_scale')
- .set_format_value_func((scale, value) => {
- return _("%d ms").format(value);
- });
-
- this._builder.get_object('animate_appicon_hover_options_rotation_scale')
- .set_format_value_func((scale, value) => {
- return _("%d °").format(value);
- });
-
- this._builder.get_object('animate_appicon_hover_options_travel_scale')
- .set_format_value_func((scale, value) => {
- return _("%d %%").format(value);
- });
-
- this._builder.get_object('animate_appicon_hover_options_zoom_scale')
- .set_format_value_func((scale, value) => {
- return _("%d %%").format(value);
- });
-
- this._builder.get_object('animate_appicon_hover_options_convexity_scale')
- .set_format_value_func((scale, value) => {
- return _("%.1f").format(value);
- });
-
- this._builder.get_object('animate_appicon_hover_options_extent_scale')
- .set_format_value_func((scale, value) => {
- return ngettext("%d icon", "%d icons", value).format(value);
- });
-
- // highlight appicon on hover dialog
- this._builder.get_object('highlight_appicon_borderradius')
- .set_format_value_func((scale, value) => {
- return value + ' px';
- });
- }
-
- _bindSettings() {
- // size options
- let panel_size_scale = this._builder.get_object('panel_size_scale');
- panel_size_scale.set_range(DEFAULT_PANEL_SIZES[DEFAULT_PANEL_SIZES.length - 1], DEFAULT_PANEL_SIZES[0]);
- DEFAULT_PANEL_SIZES.slice(1, -1).forEach(function(val) {
- panel_size_scale.add_mark(val, Gtk.PositionType.TOP, val.toString());
- });
-
- // Correct for rtl languages
- if (this._rtl) {
- // Flip value position: this is not done automatically
- panel_size_scale.set_value_pos(Gtk.PositionType.LEFT);
- // I suppose due to a bug, having a more than one mark and one above a value of 100
- // makes the rendering of the marks wrong in rtl. This doesn't happen setting the scale as not flippable
- // and then manually inverting it
- panel_size_scale.set_flippable(false);
- panel_size_scale.set_inverted(true);
- }
-
- // App icon style option
- this._builder.get_object('appicon_style_combo').set_active_id(this._settings.get_string('appicon-style'));
- this._builder.get_object('appicon_style_combo').connect('changed', (widget) => {
- this._settings.set_string('appicon-style', widget.get_active_id());
- });
-
- // Dots Position option
- let dotPosition = this._settings.get_string('dot-position');
-
- switch (dotPosition) {
- case 'BOTTOM':
- this._builder.get_object('dots_bottom_button').set_active(true);
- break;
- case 'TOP':
- this._builder.get_object('dots_top_button').set_active(true);
- break;
- case 'LEFT':
- this._builder.get_object('dots_left_button').set_active(true);
- break;
- case 'RIGHT':
- this._builder.get_object('dots_right_button').set_active(true);
- break;
- }
-
- this._builder.get_object('dot_style_focused_combo').set_active_id(this._settings.get_string('dot-style-focused'));
- this._builder.get_object('dot_style_focused_combo').connect('changed', (widget) => {
- this._settings.set_string('dot-style-focused', widget.get_active_id());
- });
-
- this._builder.get_object('dot_style_unfocused_combo').set_active_id(this._settings.get_string('dot-style-unfocused'));
- this._builder.get_object('dot_style_unfocused_combo').connect('changed', (widget) => {
- this._settings.set_string('dot-style-unfocused', widget.get_active_id());
- });
-
- for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) {
- let idx = i;
- this._builder.get_object('dot_color_' + idx + '_colorbutton').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- let hexString = cssHexString(css);
- this._settings.set_string('dot-color-' + idx, hexString);
- });
-
- this._builder.get_object('dot_color_unfocused_' + idx + '_colorbutton').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- let hexString = cssHexString(css);
- this._settings.set_string('dot-color-unfocused-' + idx, hexString);
- });
- }
-
- this._builder.get_object('dot_color_apply_all_button').connect('clicked', () => {
- for (let i = 2; i <= MAX_WINDOW_INDICATOR; i++) {
- this._settings.set_value('dot-color-' + i, this._settings.get_value('dot-color-1'));
- let rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('dot-color-' + i));
- this._builder.get_object('dot_color_' + i + '_colorbutton').set_rgba(rgba);
- }
- });
-
- this._builder.get_object('dot_color_unfocused_apply_all_button').connect('clicked', () => {
- for (let i = 2; i <= MAX_WINDOW_INDICATOR; i++) {
- this._settings.set_value('dot-color-unfocused-' + i, this._settings.get_value('dot-color-unfocused-1'));
- let rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('dot-color-unfocused-' + i));
- this._builder.get_object('dot_color_unfocused_' + i + '_colorbutton').set_rgba(rgba);
- }
- });
-
- this._builder.get_object('focus_highlight_color_colorbutton').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- let hexString = cssHexString(css);
- this._settings.set_string('focus-highlight-color', hexString);
- });
-
- this._builder.get_object('dot_style_options_button').connect('clicked', () => {
- let box = this._builder.get_object('box_dots_options');
-
- let dialog = this._createPreferencesDialog(_('Running Indicator Options'), box, () =>
- {
- // restore default settings
- this._settings.set_value('dot-color-dominant', this._settings.get_default_value('dot-color-dominant'));
- this._settings.set_value('dot-color-override', this._settings.get_default_value('dot-color-override'));
- this._settings.set_value('dot-color-unfocused-different', this._settings.get_default_value('dot-color-unfocused-different'));
-
- this._settings.set_value('focus-highlight-color', this._settings.get_default_value('focus-highlight-color'));
- let rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('focus-highlight-color'));
- this._builder.get_object('focus_highlight_color_colorbutton').set_rgba(rgba);
-
- this._settings.set_value('focus-highlight-opacity', this._settings.get_default_value('focus-highlight-opacity'));
- this._builder.get_object('focus_highlight_opacity_spinbutton').set_value(this._settings.get_int('focus-highlight-opacity'));
-
- for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) {
- this._settings.set_value('dot-color-' + i, this._settings.get_default_value('dot-color-' + i));
- rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('dot-color-' + i));
- this._builder.get_object('dot_color_' + i + '_colorbutton').set_rgba(rgba);
-
- this._settings.set_value('dot-color-unfocused-' + i, this._settings.get_default_value('dot-color-unfocused-' + i));
- rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('dot-color-unfocused-' + i));
- this._builder.get_object('dot_color_unfocused_' + i + '_colorbutton').set_rgba(rgba);
- }
-
- this._settings.set_value('dot-size', this._settings.get_default_value('dot-size'));
- this._builder.get_object('dot_size_spinbutton').set_value(this._settings.get_int('dot-size'));
-
- this._settings.set_value('focus-highlight', this._settings.get_default_value('focus-highlight'));
- this._settings.set_value('focus-highlight-dominant', this._settings.get_default_value('focus-highlight-dominant'));
- });
-
- this._settings.bind('dot-color-dominant',
- this._builder.get_object('dot_color_dominant_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('dot-color-override',
- this._builder.get_object('dot_color_override_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- // when either becomes active, turn the other off
- this._builder.get_object('dot_color_dominant_switch').connect('state-set', (widget) => {
- if (widget.get_active()) this._settings.set_boolean('dot-color-override', false);
- });
- this._builder.get_object('dot_color_override_switch').connect('state-set', (widget) => {
- if (widget.get_active()) this._settings.set_boolean('dot-color-dominant', false);
- else this._settings.set_boolean('dot-color-unfocused-different', false);
- });
-
- this._settings.bind('dot-color-unfocused-different',
- this._builder.get_object('dot_color_unfocused_different_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('dot-color-override',
- this._builder.get_object('grid_dot_color'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('dot-color-override',
- this._builder.get_object('dot_color_unfocused_box'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('dot-color-unfocused-different',
- this._builder.get_object('grid_dot_color_unfocused'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) {
- let rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('dot-color-' + i));
- this._builder.get_object('dot_color_' + i + '_colorbutton').set_rgba(rgba);
-
- rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('dot-color-unfocused-' + i));
- this._builder.get_object('dot_color_unfocused_' + i + '_colorbutton').set_rgba(rgba);
- }
-
- this._settings.bind('focus-highlight',
- this._builder.get_object('focus_highlight_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('focus-highlight',
- this._builder.get_object('grid_focus_highlight_options'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('focus-highlight-dominant',
- this._builder.get_object('focus_highlight_dominant_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('focus-highlight-dominant',
- this._builder.get_object('focus_highlight_color_label'),
- 'sensitive',
- Gio.SettingsBindFlags.INVERT_BOOLEAN);
-
- this._settings.bind('focus-highlight-dominant',
- this._builder.get_object('focus_highlight_color_colorbutton'),
- 'sensitive',
- Gio.SettingsBindFlags.INVERT_BOOLEAN);
-
-
- (function() {
- let rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('focus-highlight-color'));
- this._builder.get_object('focus_highlight_color_colorbutton').set_rgba(rgba);
- }).apply(this);
-
- this._builder.get_object('focus_highlight_opacity_spinbutton').set_value(this._settings.get_int('focus-highlight-opacity'));
- this._builder.get_object('focus_highlight_opacity_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('focus-highlight-opacity', widget.get_value());
- });
-
- this._builder.get_object('dot_size_spinbutton').set_value(this._settings.get_int('dot-size'));
- this._builder.get_object('dot_size_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('dot-size', widget.get_value());
- });
-
- dialog.show();
- dialog.set_default_size(1, 1);
-
- });
-
- //multi-monitor
- this.monitors = this._settings.get_value('available-monitors').deep_unpack();
-
- let dtpPrimaryMonitorIndex = this.monitors.indexOf(this._settings.get_int('primary-monitor'));
-
- if (dtpPrimaryMonitorIndex < 0) {
- dtpPrimaryMonitorIndex = 0;
- }
-
- this._currentMonitorIndex = this.monitors[dtpPrimaryMonitorIndex];
-
- this._settings.connect('changed::panel-positions', () => this._updateVerticalRelatedOptions());
- this._updateVerticalRelatedOptions();
-
- for (let i = 0; i < this.monitors.length; ++i) {
- //the gnome-shell primary index is the first one in the "available-monitors" setting
- let label = !i ? _('Primary monitor') : _('Monitor ') + (i + 1);
-
- this._builder.get_object('multimon_primary_combo').append_text(label);
- this._builder.get_object('taskbar_position_monitor_combo').append_text(label);
- }
-
- this._builder.get_object('multimon_primary_combo').set_active(dtpPrimaryMonitorIndex);
- this._builder.get_object('taskbar_position_monitor_combo').set_active(dtpPrimaryMonitorIndex);
-
- this._settings.bind('panel-element-positions-monitors-sync',
- this._builder.get_object('taskbar_position_sync_button'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('panel-element-positions-monitors-sync',
- this._builder.get_object('taskbar_position_monitor_combo'),
- 'sensitive',
- Gio.SettingsBindFlags.INVERT_BOOLEAN);
-
- this._settings.connect('changed::panel-element-positions-monitors-sync', () => {
- this._maybeDisableTopPosition();
- // The anchor combo box may has different labels for single- or all-monitor configuration.
- this._setAnchorLabels(this._currentMonitorIndex);
- });
-
- this._builder.get_object('multimon_primary_combo').connect('changed', (widget) => {
- this._settings.set_int('primary-monitor', this.monitors[widget.get_active()]);
- });
-
- this._builder.get_object('taskbar_position_monitor_combo').connect('changed', (widget) => {
- this._currentMonitorIndex = this.monitors[widget.get_active()];
- this._updateWidgetSettingsForMonitor(this._currentMonitorIndex);
- });
-
- this._settings.bind('multi-monitors',
- this._builder.get_object('multimon_multi_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- if (this.monitors.length === 1) {
- this._builder.get_object('multimon_multi_switch').set_sensitive(false);
- }
-
- const panel_length_scale = this._builder.get_object('panel_length_scale');
- panel_length_scale.connect('value-changed', (widget) => {
- const value = widget.get_value();
- const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync');
- const monitorsToSetFor = monitorSync ? this.monitors : [this._currentMonitorIndex];
- monitorsToSetFor.forEach(monitorIndex => {
- PanelSettings.setPanelLength(this._settings, monitorIndex, value);
- });
-
- this._setAnchorWidgetSensitivity(value);
- });
-
- this._builder.get_object('panel_anchor_combo').connect('changed', (widget) => {
- const value = widget.get_active_id();
- // Value can be null while anchor labels are being swapped out
- if (value !== null) {
- const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync');
- const monitorsToSetFor = monitorSync ? this.monitors : [this._currentMonitorIndex];
- monitorsToSetFor.forEach(monitorIndex => {
- PanelSettings.setPanelAnchor(this._settings, monitorIndex, value);
- });
- }
- });
-
- this._updateWidgetSettingsForMonitor(this._currentMonitorIndex);
-
- //dynamic opacity
- this._settings.bind('trans-use-custom-bg',
- this._builder.get_object('trans_bg_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('trans-use-custom-bg',
- this._builder.get_object('trans_bg_color_colorbutton'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- let rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('trans-bg-color'));
- this._builder.get_object('trans_bg_color_colorbutton').set_rgba(rgba);
-
- this._builder.get_object('trans_bg_color_colorbutton').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- let hexString = cssHexString(css);
- this._settings.set_string('trans-bg-color', hexString);
- });
-
- this._settings.bind('trans-use-custom-opacity',
- this._builder.get_object('trans_opacity_override_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('trans-use-custom-opacity',
- this._builder.get_object('trans_opacity_box'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('trans-use-custom-opacity',
- this._builder.get_object('trans_opacity_box2'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._builder.get_object('trans_opacity_override_switch').connect('notify::active', (widget) => {
- if (!widget.get_active())
- this._builder.get_object('trans_dyn_switch').set_active(false);
- });
-
- this._builder.get_object('trans_opacity_spinbutton').set_value(this._settings.get_double('trans-panel-opacity') * 100);
- this._builder.get_object('trans_opacity_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_double('trans-panel-opacity', widget.get_value() * 0.01);
- });
-
- this._settings.bind('trans-use-dynamic-opacity',
- this._builder.get_object('trans_dyn_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('trans-use-dynamic-opacity',
- this._builder.get_object('trans_dyn_options_button'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('trans-dynamic-behavior',
- this._builder.get_object('trans_options_window_type_combo'),
- 'active-id',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('trans-use-custom-gradient',
- this._builder.get_object('trans_gradient_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('trans-use-custom-gradient',
- this._builder.get_object('trans_gradient_box'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('trans-use-custom-gradient',
- this._builder.get_object('trans_gradient_box2'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- rgba.parse(this._settings.get_string('trans-gradient-top-color'));
- this._builder.get_object('trans_gradient_color1_colorbutton').set_rgba(rgba);
-
- this._builder.get_object('trans_gradient_color1_colorbutton').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- let hexString = cssHexString(css);
- this._settings.set_string('trans-gradient-top-color', hexString);
- });
-
- this._builder.get_object('trans_gradient_color1_spinbutton').set_value(this._settings.get_double('trans-gradient-top-opacity') * 100);
- this._builder.get_object('trans_gradient_color1_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_double('trans-gradient-top-opacity', widget.get_value() * 0.01);
- });
-
- rgba.parse(this._settings.get_string('trans-gradient-bottom-color'));
- this._builder.get_object('trans_gradient_color2_colorbutton').set_rgba(rgba);
-
- this._builder.get_object('trans_gradient_color2_colorbutton').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- let hexString = cssHexString(css);
- this._settings.set_string('trans-gradient-bottom-color', hexString);
- });
-
- this._builder.get_object('trans_gradient_color2_spinbutton').set_value(this._settings.get_double('trans-gradient-bottom-opacity') * 100);
- this._builder.get_object('trans_gradient_color2_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_double('trans-gradient-bottom-opacity', widget.get_value() * 0.01);
- });
-
- this._builder.get_object('trans_options_distance_spinbutton').set_value(this._settings.get_int('trans-dynamic-distance'));
- this._builder.get_object('trans_options_distance_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('trans-dynamic-distance', widget.get_value());
- });
-
- this._builder.get_object('trans_options_min_opacity_spinbutton').set_value(this._settings.get_double('trans-dynamic-anim-target') * 100);
- this._builder.get_object('trans_options_min_opacity_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_double('trans-dynamic-anim-target', widget.get_value() * 0.01);
- });
-
- this._builder.get_object('trans_options_anim_time_spinbutton').set_value(this._settings.get_int('trans-dynamic-anim-time'));
- this._builder.get_object('trans_options_anim_time_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('trans-dynamic-anim-time', widget.get_value());
- });
-
- this._builder.get_object('trans_dyn_options_button').connect('clicked', () => {
- let box = this._builder.get_object('box_dynamic_opacity_options');
-
- let dialog = this._createPreferencesDialog(_('Dynamic opacity options'), box, () =>
- {
- // restore default settings
- this._settings.set_value('trans-dynamic-behavior', this._settings.get_default_value('trans-dynamic-behavior'));
-
- this._settings.set_value('trans-dynamic-distance', this._settings.get_default_value('trans-dynamic-distance'));
- this._builder.get_object('trans_options_distance_spinbutton').set_value(this._settings.get_int('trans-dynamic-distance'));
-
- this._settings.set_value('trans-dynamic-anim-target', this._settings.get_default_value('trans-dynamic-anim-target'));
- this._builder.get_object('trans_options_min_opacity_spinbutton').set_value(this._settings.get_double('trans-dynamic-anim-target') * 100);
-
- this._settings.set_value('trans-dynamic-anim-time', this._settings.get_default_value('trans-dynamic-anim-time'));
- this._builder.get_object('trans_options_anim_time_spinbutton').set_value(this._settings.get_int('trans-dynamic-anim-time'));
- });
-
- dialog.show();
- dialog.set_default_size(1, 1);
-
- });
-
- this._settings.bind('desktop-line-use-custom-color',
- this._builder.get_object('override_show_desktop_line_color_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('desktop-line-use-custom-color',
- this._builder.get_object('override_show_desktop_line_color_colorbutton'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- rgba.parse(this._settings.get_string('desktop-line-custom-color'));
- this._builder.get_object('override_show_desktop_line_color_colorbutton').set_rgba(rgba);
- this._builder.get_object('override_show_desktop_line_color_colorbutton').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- this._settings.set_string('desktop-line-custom-color', css);
- });
-
-
- this._settings.bind('intellihide',
- this._builder.get_object('intellihide_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('intellihide',
- this._builder.get_object('intellihide_options_button'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('intellihide-hide-from-windows',
- this._builder.get_object('intellihide_window_hide_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('intellihide-hide-from-windows',
- this._builder.get_object('intellihide_behaviour_options'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('intellihide-behaviour',
- this._builder.get_object('intellihide_behaviour_combo'),
- 'active-id',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('intellihide-use-pressure',
- this._builder.get_object('intellihide_use_pressure_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('intellihide-use-pressure',
- this._builder.get_object('intellihide_use_pressure_options'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('intellihide-use-pressure',
- this._builder.get_object('intellihide_use_pressure_options2'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('intellihide-show-in-fullscreen',
- this._builder.get_object('intellihide_show_in_fullscreen_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('intellihide-only-secondary',
- this._builder.get_object('intellihide_only_secondary_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('multi-monitors',
- this._builder.get_object('grid_intellihide_only_secondary'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._builder.get_object('multimon_multi_switch').connect('notify::active', (widget) => {
- if (!widget.get_active())
- this._builder.get_object('intellihide_only_secondary_switch').set_active(false);
- });
-
- this._builder.get_object('intellihide_pressure_threshold_spinbutton').set_value(this._settings.get_int('intellihide-pressure-threshold'));
- this._builder.get_object('intellihide_pressure_threshold_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('intellihide-pressure-threshold', widget.get_value());
- });
-
- this._builder.get_object('intellihide_pressure_time_spinbutton').set_value(this._settings.get_int('intellihide-pressure-time'));
- this._builder.get_object('intellihide_pressure_time_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('intellihide-pressure-time', widget.get_value());
- });
-
- this._settings.bind('intellihide-key-toggle-text',
- this._builder.get_object('intellihide_toggle_entry'),
- 'text',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.connect('changed::intellihide-key-toggle-text', () => setShortcut(this._settings, 'intellihide-key-toggle'));
-
- this._builder.get_object('intellihide_animation_time_spinbutton').set_value(this._settings.get_int('intellihide-animation-time'));
- this._builder.get_object('intellihide_animation_time_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('intellihide-animation-time', widget.get_value());
- });
-
- this._builder.get_object('intellihide_close_delay_spinbutton').set_value(this._settings.get_int('intellihide-close-delay'));
- this._builder.get_object('intellihide_close_delay_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('intellihide-close-delay', widget.get_value());
- });
-
- this._builder.get_object('intellihide_enable_start_delay_spinbutton').set_value(this._settings.get_int('intellihide-enable-start-delay'));
- this._builder.get_object('intellihide_enable_start_delay_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('intellihide-enable-start-delay', widget.get_value());
- });
-
- this._builder.get_object('intellihide_options_button').connect('clicked', () => {
- let box = this._builder.get_object('box_intellihide_options');
-
- let dialog = this._createPreferencesDialog(_('Intellihide options'), box, () =>
- {
- // restore default settings
- this._settings.set_value('intellihide-hide-from-windows', this._settings.get_default_value('intellihide-hide-from-windows'));
- this._settings.set_value('intellihide-behaviour', this._settings.get_default_value('intellihide-behaviour'));
- this._settings.set_value('intellihide-use-pressure', this._settings.get_default_value('intellihide-use-pressure'));
- this._settings.set_value('intellihide-show-in-fullscreen', this._settings.get_default_value('intellihide-show-in-fullscreen'));
- this._settings.set_value('intellihide-only-secondary', this._settings.get_default_value('intellihide-only-secondary'));
-
- this._settings.set_value('intellihide-pressure-threshold', this._settings.get_default_value('intellihide-pressure-threshold'));
- this._builder.get_object('intellihide_pressure_threshold_spinbutton').set_value(this._settings.get_int('intellihide-pressure-threshold'));
-
- this._settings.set_value('intellihide-pressure-time', this._settings.get_default_value('intellihide-pressure-time'));
- this._builder.get_object('intellihide_pressure_time_spinbutton').set_value(this._settings.get_int('intellihide-pressure-time'));
-
- this._settings.set_value('intellihide-key-toggle-text', this._settings.get_default_value('intellihide-key-toggle-text'));
-
- this._settings.set_value('intellihide-animation-time', this._settings.get_default_value('intellihide-animation-time'));
- this._builder.get_object('intellihide_animation_time_spinbutton').set_value(this._settings.get_int('intellihide-animation-time'));
-
- this._settings.set_value('intellihide-close-delay', this._settings.get_default_value('intellihide-close-delay'));
- this._builder.get_object('intellihide_close_delay_spinbutton').set_value(this._settings.get_int('intellihide-close-delay'));
-
- this._settings.set_value('intellihide-enable-start-delay', this._settings.get_default_value('intellihide-enable-start-delay'));
- this._builder.get_object('intellihide_enable_start_delay_spinbutton').set_value(this._settings.get_int('intellihide-enable-start-delay'));
- });
-
- dialog.show();
- dialog.set_default_size(1, 1);
-
- });
-
- // Behavior panel
-
- this._builder.get_object('show_applications_side_padding_spinbutton').set_value(this._settings.get_int('show-apps-icon-side-padding'));
- this._builder.get_object('show_applications_side_padding_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('show-apps-icon-side-padding', widget.get_value());
- });
-
- this._settings.bind('show-apps-override-escape',
- this._builder.get_object('show_applications_esc_key_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('show-showdesktop-hover',
- this._builder.get_object('show_showdesktop_hide_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('show-showdesktop-hover',
- this._builder.get_object('grid_show_showdesktop_hide_options'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('show-showdesktop-hover',
- this._builder.get_object('grid_show_showdesktop_hide_options2'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('show-window-previews',
- this._builder.get_object('show_window_previews_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('show-window-previews',
- this._builder.get_object('show_window_previews_button'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('show-tooltip',
- this._builder.get_object('show_tooltip_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('show-favorites',
- this._builder.get_object('show_favorite_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('show-favorites-all-monitors',
- this._builder.get_object('multimon_multi_show_favorites_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('show-favorites',
- this._builder.get_object('multimon_multi_show_favorites_switch'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('show-running-apps',
- this._builder.get_object('show_runnning_apps_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._setPreviewTitlePosition();
-
- this._builder.get_object('grid_preview_title_font_color_colorbutton').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- let hexString = cssHexString(css);
- this._settings.set_string('window-preview-title-font-color', hexString);
- });
-
- this._builder.get_object('show_window_previews_button').connect('clicked', () => {
- let scrolledWindow = this._builder.get_object('box_window_preview_options');
-
- let dialog = this._createPreferencesDialog(_('Window preview options'), scrolledWindow, () =>
- {
- // restore default settings
- this._settings.set_value('show-window-previews-timeout', this._settings.get_default_value('show-window-previews-timeout'));
- this._builder.get_object('preview_timeout_spinbutton').set_value(this._settings.get_int('show-window-previews-timeout'));
-
- this._settings.set_value('leave-timeout', this._settings.get_default_value('leave-timeout'));
- this._builder.get_object('leave_timeout_spinbutton').set_value(this._settings.get_int('leave-timeout'));
-
- this._settings.set_value('window-preview-hide-immediate-click', this._settings.get_default_value('window-preview-hide-immediate-click'));
-
- this._settings.set_value('window-preview-animation-time', this._settings.get_default_value('window-preview-animation-time'));
- this._builder.get_object('animation_time_spinbutton').set_value(this._settings.get_int('window-preview-animation-time'));
-
- this._settings.set_value('preview-use-custom-opacity', this._settings.get_default_value('preview-use-custom-opacity'));
-
- this._settings.set_value('window-preview-use-custom-icon-size', this._settings.get_default_value('window-preview-use-custom-icon-size'));
-
- this._settings.set_value('preview-custom-opacity', this._settings.get_default_value('preview-custom-opacity'));
- this._builder.get_object('preview_custom_opacity_spinbutton').set_value(this._settings.get_int('preview-custom-opacity'));
-
- this._settings.set_value('window-preview-title-position', this._settings.get_default_value('window-preview-title-position'));
- this._setPreviewTitlePosition();
-
- this._settings.set_value('peek-mode', this._settings.get_default_value('peek-mode'));
- this._settings.set_value('window-preview-show-title', this._settings.get_default_value('window-preview-show-title'));
- this._settings.set_value('enter-peek-mode-timeout', this._settings.get_default_value('enter-peek-mode-timeout'));
- this._builder.get_object('enter_peek_mode_timeout_spinbutton').set_value(this._settings.get_int('enter-peek-mode-timeout'));
- this._settings.set_value('peek-mode-opacity', this._settings.get_default_value('peek-mode-opacity'));
- this._builder.get_object('peek_mode_opacity_spinbutton').set_value(this._settings.get_int('peek-mode-opacity'));
-
- this._settings.set_value('window-preview-size', this._settings.get_default_value('window-preview-size'));
- this._builder.get_object('preview_size_spinbutton').set_value(this._settings.get_int('window-preview-size'));
-
- this._settings.set_value('window-preview-fixed-x', this._settings.get_default_value('window-preview-fixed-x'));
- this._settings.set_value('window-preview-fixed-y', this._settings.get_default_value('window-preview-fixed-y'));
-
- this._settings.set_value('window-preview-aspect-ratio-x', this._settings.get_default_value('window-preview-aspect-ratio-x'));
- this._builder.get_object('preview_aspect_ratio_x_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-x').toString());
-
- this._settings.set_value('window-preview-aspect-ratio-y', this._settings.get_default_value('window-preview-aspect-ratio-y'));
- this._builder.get_object('preview_aspect_ratio_y_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-y').toString());
-
- this._settings.set_value('window-preview-padding', this._settings.get_default_value('window-preview-padding'));
- this._builder.get_object('preview_padding_spinbutton').set_value(this._settings.get_int('window-preview-padding'));
-
- this._settings.set_value('preview-middle-click-close', this._settings.get_default_value('preview-middle-click-close'));
-
- this._settings.set_value('window-preview-title-font-size', this._settings.get_default_value('window-preview-title-font-size'));
- this._builder.get_object('preview_title_size_spinbutton').set_value(this._settings.get_int('window-preview-title-font-size'));
-
- this._settings.set_value('window-preview-custom-icon-size', this._settings.get_default_value('window-preview-custom-icon-size'));
- this._builder.get_object('preview_custom_icon_size_spinbutton').set_value(this._settings.get_int('window-preview-custom-icon-size'));
-
- this._settings.set_value('window-preview-title-font-weight', this._settings.get_default_value('window-preview-title-font-weight'));
- this._builder.get_object('grid_preview_title_weight_combo').set_active_id(this._settings.get_string('window-preview-title-font-weight'));
-
- this._settings.set_value('window-preview-title-font-color', this._settings.get_default_value('window-preview-title-font-color'));
- let rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('window-preview-title-font-color'));
- this._builder.get_object('grid_preview_title_font_color_colorbutton').set_rgba(rgba);
- });
-
- this._builder.get_object('preview_timeout_spinbutton').set_value(this._settings.get_int('show-window-previews-timeout'));
- this._builder.get_object('preview_timeout_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('show-window-previews-timeout', widget.get_value());
- });
-
- this._settings.bind('preview-middle-click-close',
- this._builder.get_object('preview_middle_click_close_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('window-preview-fixed-x',
- this._builder.get_object('preview_aspect_ratio_x_fixed_togglebutton'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('window-preview-fixed-y',
- this._builder.get_object('preview_aspect_ratio_y_fixed_togglebutton'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('preview-use-custom-opacity',
- this._builder.get_object('preview_custom_opacity_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('preview-use-custom-opacity',
- this._builder.get_object('preview_custom_opacity_spinbutton'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('window-preview-use-custom-icon-size',
- this._builder.get_object('preview_custom_icon_size_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('window-preview-use-custom-icon-size',
- this._builder.get_object('preview_custom_icon_size_spinbutton'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._builder.get_object('preview_custom_opacity_spinbutton').set_value(this._settings.get_int('preview-custom-opacity'));
- this._builder.get_object('preview_custom_opacity_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('preview-custom-opacity', widget.get_value());
- });
-
- this._settings.bind('peek-mode',
- this._builder.get_object('peek_mode_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('peek-mode',
- this._builder.get_object('grid_enter_peek_mode_timeout'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('peek-mode',
- this._builder.get_object('grid_peek_mode_opacity'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('window-preview-show-title',
- this._builder.get_object('preview_show_title_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('window-preview-show-title',
- this._builder.get_object('grid_preview_custom_icon_size'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('window-preview-show-title',
- this._builder.get_object('grid_preview_title_size'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('window-preview-show-title',
- this._builder.get_object('grid_preview_title_weight'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('window-preview-show-title',
- this._builder.get_object('grid_preview_title_font_color'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._builder.get_object('enter_peek_mode_timeout_spinbutton').set_value(this._settings.get_int('enter-peek-mode-timeout'));
- this._builder.get_object('enter_peek_mode_timeout_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('enter-peek-mode-timeout', widget.get_value());
- });
-
- this._builder.get_object('leave_timeout_spinbutton').set_value(this._settings.get_int('leave-timeout'));
- this._builder.get_object('leave_timeout_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('leave-timeout', widget.get_value());
- });
-
- this._settings.bind('window-preview-hide-immediate-click',
- this._builder.get_object('preview_immediate_click_button'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._builder.get_object('animation_time_spinbutton').set_value(this._settings.get_int('window-preview-animation-time'));
- this._builder.get_object('animation_time_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('window-preview-animation-time', widget.get_value());
- });
-
- this._builder.get_object('peek_mode_opacity_spinbutton').set_value(this._settings.get_int('peek-mode-opacity'));
- this._builder.get_object('peek_mode_opacity_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('peek-mode-opacity', widget.get_value());
- });
-
- this._builder.get_object('preview_size_spinbutton').set_value(this._settings.get_int('window-preview-size'));
- this._builder.get_object('preview_size_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('window-preview-size', widget.get_value());
- });
-
- this._builder.get_object('preview_aspect_ratio_x_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-x').toString());
- this._builder.get_object('preview_aspect_ratio_x_combo').connect('changed', (widget) => {
- this._settings.set_int('window-preview-aspect-ratio-x', parseInt(widget.get_active_id(), 10));
- });
-
- this._builder.get_object('preview_aspect_ratio_y_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-y').toString());
- this._builder.get_object('preview_aspect_ratio_y_combo').connect('changed', (widget) => {
- this._settings.set_int('window-preview-aspect-ratio-y', parseInt(widget.get_active_id(), 10));
- });
-
- this._builder.get_object('preview_padding_spinbutton').set_value(this._settings.get_int('window-preview-padding'));
- this._builder.get_object('preview_padding_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('window-preview-padding', widget.get_value());
- });
-
- this._builder.get_object('preview_title_size_spinbutton').set_value(this._settings.get_int('window-preview-title-font-size'));
- this._builder.get_object('preview_title_size_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('window-preview-title-font-size', widget.get_value());
- });
-
- this._builder.get_object('preview_custom_icon_size_spinbutton').set_value(this._settings.get_int('window-preview-custom-icon-size'));
- this._builder.get_object('preview_custom_icon_size_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('window-preview-custom-icon-size', widget.get_value());
- });
-
- this._builder.get_object('grid_preview_title_weight_combo').set_active_id(this._settings.get_string('window-preview-title-font-weight'));
- this._builder.get_object('grid_preview_title_weight_combo').connect('changed', (widget) => {
- this._settings.set_string('window-preview-title-font-weight', widget.get_active_id());
- });
-
- (function() {
- let rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('window-preview-title-font-color'));
- this._builder.get_object('grid_preview_title_font_color_colorbutton').set_rgba(rgba);
- }).apply(this);
-
- dialog.show();
-
- });
-
- this._settings.bind('isolate-workspaces',
- this._builder.get_object('isolate_workspaces_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('isolate-monitors',
- this._builder.get_object('multimon_multi_isolate_monitor_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('overview-click-to-exit',
- this._builder.get_object('clicktoexit_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('hide-overview-on-startup',
- this._builder.get_object('hide_overview_on_startup_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('group-apps',
- this._builder.get_object('group_apps_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.INVERT_BOOLEAN);
-
- this._settings.bind('group-apps',
- this._builder.get_object('show_group_apps_options_button'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.INVERT_BOOLEAN);
-
- this._settings.bind('progress-show-count',
- this._builder.get_object('show_notification_badge_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._builder.get_object('group_apps_label_font_color_colorbutton').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- let hexString = cssHexString(css);
- this._settings.set_string('group-apps-label-font-color', hexString);
- });
-
- this._builder.get_object('group_apps_label_font_color_minimized_colorbutton').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- let hexString = cssHexString(css);
- this._settings.set_string('group-apps-label-font-color-minimized', hexString);
- });
-
- this._settings.bind('group-apps-use-fixed-width',
- this._builder.get_object('group_apps_use_fixed_width_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('group-apps-underline-unfocused',
- this._builder.get_object('group_apps_underline_unfocused_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('group-apps-use-launchers',
- this._builder.get_object('group_apps_use_launchers_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._builder.get_object('show_group_apps_options_button').connect('clicked', () => {
- let box = this._builder.get_object('box_group_apps_options');
-
- let dialog = this._createPreferencesDialog(_('Ungrouped application options'), box, () =>
- {
- // restore default settings
- this._settings.set_value('group-apps-label-font-size', this._settings.get_default_value('group-apps-label-font-size'));
- this._builder.get_object('group_apps_label_font_size_spinbutton').set_value(this._settings.get_int('group-apps-label-font-size'));
-
- this._settings.set_value('group-apps-label-font-weight', this._settings.get_default_value('group-apps-label-font-weight'));
- this._builder.get_object('group_apps_label_font_weight_combo').set_active_id(this._settings.get_string('group-apps-label-font-weight'));
-
- this._settings.set_value('group-apps-label-font-color', this._settings.get_default_value('group-apps-label-font-color'));
- let rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('group-apps-label-font-color'));
- this._builder.get_object('group_apps_label_font_color_colorbutton').set_rgba(rgba);
-
- this._settings.set_value('group-apps-label-font-color-minimized', this._settings.get_default_value('group-apps-label-font-color-minimized'));
- let minimizedFontColor = new Gdk.RGBA();
- minimizedFontColor.parse(this._settings.get_string('group-apps-label-font-color-minimized'));
- this._builder.get_object('group_apps_label_font_color_minimized_colorbutton').set_rgba(minimizedFontColor);
-
- this._settings.set_value('group-apps-label-max-width', this._settings.get_default_value('group-apps-label-max-width'));
- this._builder.get_object('group_apps_label_max_width_spinbutton').set_value(this._settings.get_int('group-apps-label-max-width'));
-
- this._settings.set_value('group-apps-use-fixed-width', this._settings.get_default_value('group-apps-use-fixed-width'));
- this._settings.set_value('group-apps-underline-unfocused', this._settings.get_default_value('group-apps-underline-unfocused'));
- this._settings.set_value('group-apps-use-launchers', this._settings.get_default_value('group-apps-use-launchers'));
- });
-
- this._builder.get_object('group_apps_label_font_size_spinbutton').set_value(this._settings.get_int('group-apps-label-font-size'));
- this._builder.get_object('group_apps_label_font_size_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('group-apps-label-font-size', widget.get_value());
- });
-
- this._builder.get_object('group_apps_label_font_weight_combo').set_active_id(this._settings.get_string('group-apps-label-font-weight'));
- this._builder.get_object('group_apps_label_font_weight_combo').connect('changed', (widget) => {
- this._settings.set_string('group-apps-label-font-weight', widget.get_active_id());
- });
-
- (function() {
- let rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('group-apps-label-font-color'));
- this._builder.get_object('group_apps_label_font_color_colorbutton').set_rgba(rgba);
- }).apply(this);
-
- (function() {
- let rgba = new Gdk.RGBA();
- rgba.parse(this._settings.get_string('group-apps-label-font-color-minimized'));
- this._builder.get_object('group_apps_label_font_color_minimized_colorbutton').set_rgba(rgba);
- }).apply(this);
-
- this._builder.get_object('group_apps_label_max_width_spinbutton').set_value(this._settings.get_int('group-apps-label-max-width'));
- this._builder.get_object('group_apps_label_max_width_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('group-apps-label-max-width', widget.get_value());
- });
-
- dialog.show();
- dialog.set_default_size(600, 1);
-
- });
-
- this._builder.get_object('click_action_combo').set_active_id(this._settings.get_string('click-action'));
- this._builder.get_object('click_action_combo').connect('changed', (widget) => {
- this._settings.set_string('click-action', widget.get_active_id());
- });
-
- this._builder.get_object('shift_click_action_combo').connect('changed', (widget) => {
- this._settings.set_string('shift-click-action', widget.get_active_id());
- });
-
- this._builder.get_object('middle_click_action_combo').connect('changed', (widget) => {
- this._settings.set_string('middle-click-action', widget.get_active_id());
- });
- this._builder.get_object('shift_middle_click_action_combo').connect('changed', (widget) => {
- this._settings.set_string('shift-middle-click-action', widget.get_active_id());
- });
-
- // Create dialog for middle-click options
- this._builder.get_object('middle_click_options_button').connect('clicked', () => {
- let box = this._builder.get_object('box_middle_click_options');
-
- let dialog = this._createPreferencesDialog(_('Customize middle-click behavior'), box, () =>
- {
- // restore default settings for the relevant keys
- let keys = ['shift-click-action', 'middle-click-action', 'shift-middle-click-action'];
- keys.forEach(function(val) {
- this._settings.set_value(val, this._settings.get_default_value(val));
- }, this);
- this._builder.get_object('shift_click_action_combo').set_active_id(this._settings.get_string('shift-click-action'));
- this._builder.get_object('middle_click_action_combo').set_active_id(this._settings.get_string('middle-click-action'));
- this._builder.get_object('shift_middle_click_action_combo').set_active_id(this._settings.get_string('shift-middle-click-action'));
- });
-
- this._builder.get_object('shift_click_action_combo').set_active_id(this._settings.get_string('shift-click-action'));
-
- this._builder.get_object('middle_click_action_combo').set_active_id(this._settings.get_string('middle-click-action'));
-
- this._builder.get_object('shift_middle_click_action_combo').set_active_id(this._settings.get_string('shift-middle-click-action'));
-
- this._settings.bind('shift-click-action',
- this._builder.get_object('shift_click_action_combo'),
- 'active-id',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('middle-click-action',
- this._builder.get_object('middle_click_action_combo'),
- 'active-id',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('shift-middle-click-action',
- this._builder.get_object('shift_middle_click_action_combo'),
- 'active-id',
- Gio.SettingsBindFlags.DEFAULT);
-
- dialog.show();
- dialog.set_default_size(700, 1);
-
- });
-
- this._builder.get_object('scroll_panel_combo').set_active_id(this._settings.get_string('scroll-panel-action'));
- this._builder.get_object('scroll_panel_combo').connect('changed', (widget) => {
- this._settings.set_string('scroll-panel-action', widget.get_active_id());
- });
-
- this._builder.get_object('scroll_icon_combo').set_active_id(this._settings.get_string('scroll-icon-action'));
- this._builder.get_object('scroll_icon_combo').connect('changed', (widget) => {
- this._settings.set_string('scroll-icon-action', widget.get_active_id());
- });
-
- // Create dialog for panel scroll options
- this._builder.get_object('scroll_panel_options_button').connect('clicked', () => {
- let box = this._builder.get_object('scroll_panel_options_box');
-
- let dialog = this._createPreferencesDialog(_('Customize panel scroll behavior'), box, () =>
- {
- // restore default settings
- this._settings.set_value('scroll-panel-delay', this._settings.get_default_value('scroll-panel-delay'));
- this._builder.get_object('scroll_panel_options_delay_spinbutton').set_value(this._settings.get_int('scroll-panel-delay'));
-
- this._settings.set_value('scroll-panel-show-ws-popup', this._settings.get_default_value('scroll-panel-show-ws-popup'));
- });
-
- this._builder.get_object('scroll_panel_options_delay_spinbutton').set_value(this._settings.get_int('scroll-panel-delay'));
- this._builder.get_object('scroll_panel_options_delay_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('scroll-panel-delay', widget.get_value());
- });
-
- this._settings.bind('scroll-panel-show-ws-popup',
- this._builder.get_object('scroll_panel_options_show_ws_popup_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- dialog.show();
- dialog.set_default_size(640, 1);
-
- });
-
- // Create dialog for icon scroll options
- this._builder.get_object('scroll_icon_options_button').connect('clicked', () => {
- let box = this._builder.get_object('scroll_icon_options_box');
-
- let dialog = this._createPreferencesDialog(_('Customize icon scroll behavior'), box, () =>
- {
- // restore default settings
- this._settings.set_value('scroll-icon-delay', this._settings.get_default_value('scroll-icon-delay'));
- this._builder.get_object('scroll_icon_options_delay_spinbutton').set_value(this._settings.get_int('scroll-icon-delay'));
- });
-
- this._builder.get_object('scroll_icon_options_delay_spinbutton').set_value(this._settings.get_int('scroll-icon-delay'));
- this._builder.get_object('scroll_icon_options_delay_spinbutton').connect('value-changed', (widget) => {
- this._settings.set_int('scroll-icon-delay', widget.get_value());
- });
-
- dialog.show();
- dialog.set_default_size(640, 1);
-
- });
-
- this._settings.bind('hot-keys',
- this._builder.get_object('hot_keys_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.bind('hot-keys',
- this._builder.get_object('overlay_button'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._builder.get_object('overlay_combo').connect('changed', (widget) => {
- this._settings.set_string('hotkeys-overlay-combo', widget.get_active_id());
- });
-
- this._settings.bind('shortcut-previews',
- this._builder.get_object('shortcut_preview_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._builder.get_object('shortcut_num_keys_combo').set_active_id(this._settings.get_string('shortcut-num-keys'));
- this._builder.get_object('shortcut_num_keys_combo').connect('changed', (widget) => {
- this._settings.set_string('shortcut-num-keys', widget.get_active_id());
- });
-
- this._settings.connect('changed::hotkey-prefix-text', () => {checkHotkeyPrefix(this._settings);});
-
- this._builder.get_object('hotkey_prefix_combo').set_active_id(this._settings.get_string('hotkey-prefix-text'));
-
- this._settings.bind('hotkey-prefix-text',
- this._builder.get_object('hotkey_prefix_combo'),
- 'active-id',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._builder.get_object('overlay_combo').set_active_id(this._settings.get_string('hotkeys-overlay-combo'));
-
- this._settings.bind('hotkeys-overlay-combo',
- this._builder.get_object('overlay_combo'),
- 'active-id',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('overlay-timeout',
- this._builder.get_object('timeout_spinbutton'),
- 'value',
- Gio.SettingsBindFlags.DEFAULT);
- if (this._settings.get_string('hotkeys-overlay-combo') !== 'TEMPORARILY') {
- this._builder.get_object('timeout_spinbutton').set_sensitive(false);
- }
-
- this._settings.connect('changed::hotkeys-overlay-combo', () => {
- if (this._settings.get_string('hotkeys-overlay-combo') !== 'TEMPORARILY')
- this._builder.get_object('timeout_spinbutton').set_sensitive(false);
- else
- this._builder.get_object('timeout_spinbutton').set_sensitive(true);
- });
-
- this._settings.bind('shortcut-text',
- this._builder.get_object('shortcut_entry'),
- 'text',
- Gio.SettingsBindFlags.DEFAULT);
- this._settings.connect('changed::shortcut-text', () => {setShortcut(this._settings, 'shortcut');});
-
- // Create dialog for number overlay options
- this._builder.get_object('overlay_button').connect('clicked', () => {
- let box = this._builder.get_object('box_overlay_shortcut');
-
- let dialog = this._createPreferencesDialog(_('Advanced hotkeys options'), box, () =>
- {
- // restore default settings for the relevant keys
- let keys = ['hotkey-prefix-text', 'shortcut-text', 'hotkeys-overlay-combo', 'overlay-timeout', 'shortcut-previews'];
- keys.forEach(function(val) {
- this._settings.set_value(val, this._settings.get_default_value(val));
- }, this);
- });
-
- dialog.show();
- dialog.set_default_size(600, 1);
-
- });
-
- // setup dialog for secondary menu options
- this._builder.get_object('secondarymenu_options_button').connect('clicked', () => {
- let box = this._builder.get_object('box_secondarymenu_options');
-
- let dialog = this._createPreferencesDialog(_('Secondary Menu Options'), box, () =>
- {
- // restore default settings
- this._settings.set_value('secondarymenu-contains-appmenu', this._settings.get_default_value('secondarymenu-contains-appmenu'));
- this._settings.set_value('secondarymenu-contains-showdetails', this._settings.get_default_value('secondarymenu-contains-showdetails'));
- });
-
- // TODO setting secondarymenu-contains-appmenu is not being used anywhere
- this._settings.bind('secondarymenu-contains-appmenu',
- this._builder.get_object('secondarymenu_appmenu_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('secondarymenu-contains-showdetails',
- this._builder.get_object('secondarymenu_showdetails_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- dialog.show();
- dialog.set_default_size(480, 1);
-
- });
-
- // setup dialog for advanced options
- this._builder.get_object('button_advanced_options').connect('clicked', () => {
- let box = this._builder.get_object('box_advanced_options');
-
- let dialog = this._createPreferencesDialog(_('Advanced Options'), box);
-
- dialog.show();
- dialog.set_default_size(480, 1);
-
- });
-
- // Fine-tune panel
-
- let sizeScales = [
- {objectName: 'tray_size_scale', valueName: 'tray-size', range: DEFAULT_FONT_SIZES },
- {objectName: 'leftbox_size_scale', valueName: 'leftbox-size', range: DEFAULT_FONT_SIZES },
- {objectName: 'appicon_margin_scale', valueName: 'appicon-margin', range: DEFAULT_MARGIN_SIZES },
- {objectName: 'appicon_margin_todesktop_scale', valueName: 'appicon-margin-todesktop', range: DEFAULT_MARGIN_SIZES },
- {objectName: 'appicon_margin_toscreenborder_scale', valueName: 'appicon-margin-toscreenborder', range: DEFAULT_MARGIN_SIZES },
- {objectName: 'appicon_padding_scale', valueName: 'appicon-padding', range: DEFAULT_MARGIN_SIZES },
- {objectName: 'tray_padding_scale', valueName: 'tray-padding', range: DEFAULT_PADDING_SIZES },
- {objectName: 'leftbox_padding_scale', valueName: 'leftbox-padding', range: DEFAULT_PADDING_SIZES },
- {objectName: 'statusicon_padding_scale', valueName: 'status-icon-padding', range: DEFAULT_PADDING_SIZES },
- {objectName: 'panel_length_scale', valueName: '', range: LENGTH_MARKS },
- {objectName: 'highlight_appicon_borderradius', valueName: 'highlight-appicon-hover-border-radius', range: [ 16, 12, 8, 4, 2, 0 ] },
- ];
-
- for(const idx in sizeScales) {
- let size_scale = this._builder.get_object(sizeScales[idx].objectName);
- let range = sizeScales[idx].range;
- size_scale.set_range(range[range.length - 1], range[0]);
- let value;
- if (sizeScales[idx].objectName === 'panel_length_scale') {
- value = PanelSettings.getPanelLength(this._settings, this._currentMonitorIndex);
- } else {
- value = this._settings.get_int(sizeScales[idx].valueName);
- }
- size_scale.set_value(value);
- // Add marks from range arrays, omitting the first and last values.
- range.slice(1, -1).forEach(function(val) {
- size_scale.add_mark(val, Gtk.PositionType.TOP, val.toString());
- });
-
- // Corrent for rtl languages
- if (this._rtl) {
- // Flip value position: this is not done automatically
- size_scale.set_value_pos(Gtk.PositionType.LEFT);
- // I suppose due to a bug, having a more than one mark and one above a value of 100
- // makes the rendering of the marks wrong in rtl. This doesn't happen setting the scale as not flippable
- // and then manually inverting it
- size_scale.set_flippable(false);
- size_scale.set_inverted(true);
- }
- }
-
- this._settings.bind('animate-app-switch',
- this._builder.get_object('animate_app_switch_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('animate-window-launch',
- this._builder.get_object('animate_window_launch_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('animate-appicon-hover',
- this._builder.get_object('animate_appicon_hover_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('animate-appicon-hover',
- this._builder.get_object('animate_appicon_hover_button'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- {
- this._settings.bind('animate-appicon-hover-animation-type',
- this._builder.get_object('animate_appicon_hover_options_type_combo'),
- 'active-id',
- Gio.SettingsBindFlags.DEFAULT);
-
- let scales = [
- ['animate_appicon_hover_options_duration_scale', 'animate-appicon-hover-animation-duration', 1],
- ['animate_appicon_hover_options_rotation_scale', 'animate-appicon-hover-animation-rotation', 1],
- ['animate_appicon_hover_options_travel_scale', 'animate-appicon-hover-animation-travel', 100],
- ['animate_appicon_hover_options_zoom_scale', 'animate-appicon-hover-animation-zoom', 100],
- ['animate_appicon_hover_options_convexity_scale', 'animate-appicon-hover-animation-convexity', 1],
- ['animate_appicon_hover_options_extent_scale', 'animate-appicon-hover-animation-extent', 1],
- ];
-
- let updateScale = scale => {
- let [id, key, factor] = scale;
- let type = this._settings.get_string('animate-appicon-hover-animation-type');
- let value = this._settings.get_value(key).deep_unpack()[type];
- let defaultValue = this._settings.get_default_value(key).deep_unpack()[type];
- this._builder.get_object(id).sensitive = defaultValue !== undefined;
- this._builder.get_object(id).set_value(value * factor || 0);
- this._builder.get_object(id).clear_marks();
- this._builder.get_object(id).add_mark(defaultValue * factor, Gtk.PositionType.TOP,
- defaultValue !== undefined ? (defaultValue * factor).toString() : ' ');
- };
-
- scales.forEach(scale => {
- let [id, key, factor] = scale;
- this._settings.connect('changed::' + key, () => updateScale(scale));
- this._builder.get_object(id).connect('value-changed', widget => {
- let type = this._settings.get_string('animate-appicon-hover-animation-type');
- let variant = this._settings.get_value(key);
- let unpacked = variant.deep_unpack();
- if (unpacked[type] != widget.get_value() / factor) {
- unpacked[type] = widget.get_value() / factor;
- this._settings.set_value(key, new GLib.Variant(variant.get_type_string(), unpacked));
- }
- });
- });
-
- this._settings.connect('changed::animate-appicon-hover-animation-type', () => scales.forEach(updateScale));
- scales.forEach(updateScale);
- }
-
- this._builder.get_object('animate_appicon_hover_button').connect('clicked', () => {
- let box = this._builder.get_object('animate_appicon_hover_options');
-
- let dialog = this._createPreferencesDialog(_('App icon animation options'), box, () =>
- {
- // restore default settings
- this._settings.set_value('animate-appicon-hover-animation-type', this._settings.get_default_value('animate-appicon-hover-animation-type'));
- this._settings.set_value('animate-appicon-hover-animation-duration', this._settings.get_default_value('animate-appicon-hover-animation-duration'));
- this._settings.set_value('animate-appicon-hover-animation-rotation', this._settings.get_default_value('animate-appicon-hover-animation-rotation'));
- this._settings.set_value('animate-appicon-hover-animation-travel', this._settings.get_default_value('animate-appicon-hover-animation-travel'));
- this._settings.set_value('animate-appicon-hover-animation-zoom', this._settings.get_default_value('animate-appicon-hover-animation-zoom'));
- this._settings.set_value('animate-appicon-hover-animation-convexity', this._settings.get_default_value('animate-appicon-hover-animation-convexity'));
- this._settings.set_value('animate-appicon-hover-animation-extent', this._settings.get_default_value('animate-appicon-hover-animation-extent'));
- });
-
- dialog.show();
-
- });
-
- this._settings.bind('highlight-appicon-hover',
- this._builder.get_object('highlight_appicon_hover_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('highlight-appicon-hover',
- this._builder.get_object('highlight_appicon_hover_button'),
- 'sensitive',
- Gio.SettingsBindFlags.DEFAULT);
-
- {
- rgba.parse(this._settings.get_string('highlight-appicon-hover-background-color'));
- this._builder.get_object('highlight_appicon_color').set_rgba(rgba);
- this._builder.get_object('highlight_appicon_color').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- this._settings.set_string('highlight-appicon-hover-background-color', css);
- });
-
- rgba.parse(this._settings.get_string('highlight-appicon-pressed-background-color'));
- this._builder.get_object('pressed_appicon_color').set_rgba(rgba);
- this._builder.get_object('pressed_appicon_color').connect('color-set', (button) => {
- let rgba = button.get_rgba();
- let css = rgba.to_string();
- this._settings.set_string('highlight-appicon-pressed-background-color', css);
- });
-
- let scales = [
- ['highlight_appicon_borderradius', 'highlight-appicon-hover-border-radius'],
- ];
-
- const updateScale = scale => {
- let [id, key] = scale;
- this._builder.get_object(id).set_value(this._settings.get_int(key));
- };
- scales.forEach(scale => {
- updateScale(scale);
- let [id, key] = scale;
- this._builder.get_object(id).connect('value-changed', widget => {
- this._settings.set_int(key, widget.get_value());
- });
- });
-
- }
-
- this._builder.get_object('highlight_appicon_hover_button').connect('clicked', () => {
- let box = this._builder.get_object('highlight_appicon_hover_options');
-
- let dialog = this._createPreferencesDialog(_('App icon highlight options'), box, () =>
- {
- // restore default settings
- this._settings.set_value('highlight-appicon-hover-background-color', this._settings.get_default_value('highlight-appicon-hover-background-color'));
- rgba.parse(this._settings.get_string('highlight-appicon-hover-background-color'));
- this._builder.get_object('highlight_appicon_color').set_rgba(rgba);
- this._settings.set_value('highlight-appicon-pressed-background-color', this._settings.get_default_value('highlight-appicon-pressed-background-color'));
- rgba.parse(this._settings.get_string('highlight-appicon-pressed-background-color'));
- this._builder.get_object('pressed_appicon_color').set_rgba(rgba);
- this._settings.set_value('highlight-appicon-hover-border-radius', this._settings.get_default_value('highlight-appicon-hover-border-radius'));
- this._builder.get_object('highlight_appicon_borderradius').set_value(this._settings.get_int('highlight-appicon-hover-border-radius'));
- });
-
- dialog.show();
-
- });
-
- this._settings.bind('stockgs-keep-dash',
- this._builder.get_object('stockgs_dash_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('stockgs-keep-top-panel',
- this._builder.get_object('stockgs_top_panel_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
-
-
- this._settings.connect('changed::stockgs-keep-top-panel', () => this._maybeDisableTopPosition());
-
- this._maybeDisableTopPosition();
-
- this._settings.bind('stockgs-panelbtn-click-only',
- this._builder.get_object('stockgs_panelbtn_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- this._settings.bind('stockgs-force-hotcorner',
- this._builder.get_object('stockgs_hotcorner_switch'),
- 'active',
- Gio.SettingsBindFlags.DEFAULT);
-
- // About Panel
-
- this._builder.get_object('extension_version').set_label(this._metadata.version.toString() + (this._metadata.commit ? ' (' + this._metadata.commit + ')' : ''));
-
- this._builder.get_object('importexport_export_button').connect('clicked', widget => {
- this._showFileChooser(
- _('Export settings'),
- { action: Gtk.FileChooserAction.SAVE },
- "Save",
- filename => {
- let file = Gio.file_new_for_path(filename);
- let raw = file.replace(null, false, Gio.FileCreateFlags.NONE, null);
- let out = Gio.BufferedOutputStream.new_sized(raw, 4096);
-
- out.write_all(GLib.spawn_command_line_sync('dconf dump ' + SCHEMA_PATH)[1], null);
- out.close(null);
- }
- );
- });
-
- this._builder.get_object('importexport_import_button').connect('clicked', widget => {
- this._showFileChooser(
- _('Import settings'),
- { action: Gtk.FileChooserAction.OPEN },
- "Open",
- filename => {
- if (filename && GLib.file_test(filename, GLib.FileTest.EXISTS)) {
- let settingsFile = Gio.File.new_for_path(filename);
- let [ , pid, stdin, stdout, stderr] =
- GLib.spawn_async_with_pipes(
- null,
- ['dconf', 'load', SCHEMA_PATH],
- null,
- GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
- null
- );
-
- stdin = new Gio.UnixOutputStream({ fd: stdin, close_fd: true });
- GLib.close(stdout);
- GLib.close(stderr);
-
- stdin.splice(settingsFile.read(null), Gio.OutputStreamSpliceFlags.CLOSE_SOURCE | Gio.OutputStreamSpliceFlags.CLOSE_TARGET, null);
- }
- }
- );
- });
-
- // Donation panel
-
- let revealDonateTimeout = 0;
- let donationIconSwitch = this._builder.get_object('donation_icon_switch')
- let donationRevealer = this._builder.get_object('donation_revealer');
- let hiddenDonateIcon = !!this._settings.get_string('hide-donate-icon-unixtime')
-
- this._builder.get_object('donation_logo').set_from_file(`${this._path}/img/dash-to-panel-logo-light.svg`)
- this._builder.get_object('paypal_logo').set_from_file(`${this._path}/img/paypal.png`)
- this._builder.get_object('stripe_logo').set_from_file(`${this._path}/img/stripe.png`)
- this._builder.get_object('kofi_logo').set_from_file(`${this._path}/img/kofi.png`)
-
- donationIconSwitch.set_active(hiddenDonateIcon)
- donationRevealer.set_reveal_child(hiddenDonateIcon)
-
- donationIconSwitch.connect('notify::active', (widget) =>
- this._settings.set_string('hide-donate-icon-unixtime', widget.get_active() ? Date.now().toString() : '')
+ }
+
+ positionCombo.append(
+ Pos.STACKED_TL,
+ isVertical ? _('Stacked to top') : _('Stacked to left'),
+ )
+ positionCombo.append(
+ Pos.STACKED_BR,
+ isVertical ? _('Stacked to bottom') : _('Stacked to right'),
+ )
+ positionCombo.append(Pos.CENTERED, _('Centered'))
+ positionCombo.append(Pos.CENTERED_MONITOR, _('Monitor Center'))
+ positionCombo.set_active_id(el.position)
+
+ upBtn.connect('clicked', () => upDownClickHandler(0))
+ downBtn.connect('clicked', () =>
+ upDownClickHandler(panelElementPositions.length - 1),
+ )
+ visibleToggleBtn.connect('toggled', () => updateElementsSettings())
+ positionCombo.connect('changed', () => updateElementsSettings())
+
+ upBtn.set_child(upImg)
+ downBtn.set_child(downImg)
+
+ upDownGrid.attach(upBtn, 0, 0, 1, 1)
+ upDownGrid.attach(downBtn, 1, 0, 1, 1)
+
+ grid.attach(upDownGrid, 0, 0, 1, 1)
+ grid.attach(
+ new Gtk.Label({ label: labels[el.element], xalign: 0, hexpand: true }),
+ 1,
+ 0,
+ 1,
+ 1,
+ )
+
+ if (Pos.optionDialogFunctions[el.element]) {
+ let cogImg = new Gtk.Image({ icon_name: 'emblem-system-symbolic' })
+ let optionsBtn = new Gtk.Button({ tooltip_text: _('More options') })
+
+ optionsBtn.get_style_context().add_class('circular')
+ optionsBtn.set_child(cogImg)
+ grid.attach(optionsBtn, 2, 0, 1, 1)
+
+ optionsBtn.connect('clicked', () =>
+ this[Pos.optionDialogFunctions[el.element]](),
)
-
- this.notebook.connect('notify::visible-page', () => {
- clearTimeout(revealDonateTimeout)
-
- if (this.notebook.visible_page_name == 'donation' && !donationRevealer.get_reveal_child())
- revealDonateTimeout = setTimeout(() => donationRevealer.set_reveal_child(true), 10000)
+ }
+
+ grid.attach(visibleToggleBtn, 3, 0, 1, 1)
+ grid.attach(positionCombo, 4, 0, 1, 1)
+
+ row.id = el.element
+ row.visibleToggleBtn = visibleToggleBtn
+ row.positionCombo = positionCombo
+
+ row.set_child(grid)
+ taskbarListBox.insert(row, -1)
+ })
+ }
+
+ _createPreferencesDialog(title, content, reset_function = null) {
+ let dialog
+
+ dialog = new Gtk.Dialog({
+ title: title,
+ transient_for: this.notebook.get_root(),
+ use_header_bar: true,
+ modal: true,
+ })
+
+ // GTK+ leaves positive values for application-defined response ids.
+ // Use +1 for the reset action
+ if (reset_function != null) dialog.add_button(_('Reset to defaults'), 1)
+
+ dialog.get_content_area().append(content)
+
+ dialog.connect('response', (dialog, id) => {
+ if (id == 1) {
+ // restore default settings
+ if (reset_function) reset_function()
+ } else {
+ // remove the settings content so it doesn't get destroyed;
+ dialog.get_content_area().remove(content)
+ dialog.destroy()
+ }
+ return
+ })
+
+ return dialog
+ }
+
+ _showShowAppsButtonOptions() {
+ let box = this._builder.get_object('show_applications_options')
+
+ let dialog = this._createPreferencesDialog(
+ _('Show Applications options'),
+ box,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'show-apps-icon-side-padding',
+ this._settings.get_default_value('show-apps-icon-side-padding'),
+ )
+ this._builder
+ .get_object('show_applications_side_padding_spinbutton')
+ .set_value(this._settings.get_int('show-apps-icon-side-padding'))
+ this._settings.set_value(
+ 'show-apps-override-escape',
+ this._settings.get_default_value('show-apps-override-escape'),
+ )
+ handleIconChange.call(this, null)
+ },
+ )
+
+ let fileChooserButton = this._builder.get_object(
+ 'show_applications_icon_file_filebutton',
+ )
+ let fileChooser = new Gtk.FileChooserNative({
+ title: _('Open icon'),
+ transient_for: dialog,
+ })
+ let fileImage = this._builder.get_object(
+ 'show_applications_current_icon_image',
+ )
+ let fileFilter = new Gtk.FileFilter()
+ fileFilter.add_pixbuf_formats()
+ fileChooser.filter = fileFilter
+
+ let handleIconChange = function (newIconPath) {
+ if (newIconPath && GLib.file_test(newIconPath, GLib.FileTest.EXISTS)) {
+ let file = Gio.File.new_for_path(newIconPath)
+ let pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
+ file.read(null),
+ 32,
+ 32,
+ true,
+ null,
+ )
+
+ fileImage.set_from_pixbuf(pixbuf)
+ fileChooser.set_file(file)
+ fileChooserButton.set_label(newIconPath)
+ } else {
+ newIconPath = ''
+ fileImage.set_from_icon_name('view-app-grid-symbolic')
+ let picturesFolder = Gio.File.new_for_path(
+ GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES),
+ )
+ fileChooser.set_file(picturesFolder)
+ fileChooserButton.set_label('(None)')
+ }
+
+ this._settings.set_string('show-apps-icon-file', newIconPath || '')
+ }
+
+ fileChooserButton.connect('clicked', () => {
+ fileChooser.show()
+ })
+
+ fileChooser.connect('response', (widget) =>
+ handleIconChange.call(this, widget.get_file().get_path()),
+ )
+ handleIconChange.call(
+ this,
+ this._settings.get_string('show-apps-icon-file'),
+ )
+
+ // we have to destroy the fileChooser as well
+ dialog.connect('response', (dialog, id) => {
+ if (id != 1) {
+ fileChooser.destroy()
+ }
+ return
+ })
+
+ dialog.show()
+ dialog.set_default_size(1, 1)
+ }
+
+ _showDesktopButtonOptions() {
+ let box = this._builder.get_object('box_show_showdesktop_options')
+
+ let dialog = this._createPreferencesDialog(
+ _('Show Desktop options'),
+ box,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'showdesktop-button-width',
+ this._settings.get_default_value('showdesktop-button-width'),
+ )
+ this._builder
+ .get_object('show_showdesktop_width_spinbutton')
+ .set_value(this._settings.get_int('showdesktop-button-width'))
+
+ this._settings.set_value(
+ 'desktop-line-use-custom-color',
+ this._settings.get_default_value('desktop-line-use-custom-color'),
+ )
+
+ this._settings.set_value(
+ 'show-showdesktop-hover',
+ this._settings.get_default_value('show-showdesktop-hover'),
+ )
+
+ this._settings.set_value(
+ 'show-showdesktop-delay',
+ this._settings.get_default_value('show-showdesktop-delay'),
+ )
+ this._builder
+ .get_object('show_showdesktop_delay_spinbutton')
+ .set_value(this._settings.get_int('show-showdesktop-delay'))
+
+ this._settings.set_value(
+ 'show-showdesktop-time',
+ this._settings.get_default_value('show-showdesktop-time'),
+ )
+ this._builder
+ .get_object('show_showdesktop_time_spinbutton')
+ .set_value(this._settings.get_int('show-showdesktop-time'))
+ },
+ )
+
+ this._builder
+ .get_object('show_showdesktop_width_spinbutton')
+ .set_value(this._settings.get_int('showdesktop-button-width'))
+ this._builder
+ .get_object('show_showdesktop_width_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('showdesktop-button-width', widget.get_value())
+ })
+
+ this._builder
+ .get_object('show_showdesktop_delay_spinbutton')
+ .set_value(this._settings.get_int('show-showdesktop-delay'))
+ this._builder
+ .get_object('show_showdesktop_delay_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('show-showdesktop-delay', widget.get_value())
+ })
+
+ this._builder
+ .get_object('show_showdesktop_time_spinbutton')
+ .set_value(this._settings.get_int('show-showdesktop-time'))
+ this._builder
+ .get_object('show_showdesktop_time_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('show-showdesktop-time', widget.get_value())
+ })
+
+ dialog.show()
+ dialog.set_default_size(1, 1)
+ }
+
+ _addFormatValueCallbacks() {
+ // position
+ this._builder
+ .get_object('panel_size_scale')
+ .set_format_value_func((scale, value) => {
+ return value + ' px'
+ })
+
+ // style
+ this._builder
+ .get_object('appicon_margin_scale')
+ .set_format_value_func((scale, value) => {
+ return value + ' px'
+ })
+ this._builder
+ .get_object('appicon_margin_todesktop_scale')
+ .set_format_value_func((scale, value) => {
+ return value + ' px'
+ })
+ this._builder
+ .get_object('appicon_margin_toscreenborder_scale')
+ .set_format_value_func((scale, value) => {
+ return value + ' px'
+ })
+
+ this._builder
+ .get_object('appicon_padding_scale')
+ .set_format_value_func((scale, value) => {
+ return value + ' px'
+ })
+
+ // fine-tune box1
+ this._builder
+ .get_object('tray_size_scale')
+ .set_format_value_func((scale, value) => {
+ return value + ' px'
+ })
+
+ this._builder
+ .get_object('leftbox_size_scale')
+ .set_format_value_func((scale, value) => {
+ return value + ' px'
+ })
+
+ // fine-tune box2
+ this._builder
+ .get_object('tray_padding_scale')
+ .set_format_value_func((scale, value) => {
+ return value + ' px'
+ })
+
+ this._builder
+ .get_object('statusicon_padding_scale')
+ .set_format_value_func((scale, value) => {
+ return value + ' px'
+ })
+
+ this._builder
+ .get_object('leftbox_padding_scale')
+ .set_format_value_func((scale, value) => {
+ return value + ' px'
+ })
+
+ // animate hovering app icons dialog
+ this._builder
+ .get_object('animate_appicon_hover_options_duration_scale')
+ .set_format_value_func((scale, value) => {
+ return _('%d ms').format(value)
+ })
+
+ this._builder
+ .get_object('animate_appicon_hover_options_rotation_scale')
+ .set_format_value_func((scale, value) => {
+ return _('%d °').format(value)
+ })
+
+ this._builder
+ .get_object('animate_appicon_hover_options_travel_scale')
+ .set_format_value_func((scale, value) => {
+ return _('%d %%').format(value)
+ })
+
+ this._builder
+ .get_object('animate_appicon_hover_options_zoom_scale')
+ .set_format_value_func((scale, value) => {
+ return _('%d %%').format(value)
+ })
+
+ this._builder
+ .get_object('animate_appicon_hover_options_convexity_scale')
+ .set_format_value_func((scale, value) => {
+ return _('%.1f').format(value)
+ })
+
+ this._builder
+ .get_object('animate_appicon_hover_options_extent_scale')
+ .set_format_value_func((scale, value) => {
+ return ngettext('%d icon', '%d icons', value).format(value)
+ })
+
+ // highlight appicon on hover dialog
+ this._builder
+ .get_object('highlight_appicon_borderradius')
+ .set_format_value_func((scale, value) => {
+ return value + ' px'
+ })
+ }
+
+ _bindSettings() {
+ // size options
+ let panel_size_scale = this._builder.get_object('panel_size_scale')
+ panel_size_scale.set_range(
+ DEFAULT_PANEL_SIZES[DEFAULT_PANEL_SIZES.length - 1],
+ DEFAULT_PANEL_SIZES[0],
+ )
+ DEFAULT_PANEL_SIZES.slice(1, -1).forEach(function (val) {
+ panel_size_scale.add_mark(val, Gtk.PositionType.TOP, val.toString())
+ })
+
+ // Correct for rtl languages
+ if (this._rtl) {
+ // Flip value position: this is not done automatically
+ panel_size_scale.set_value_pos(Gtk.PositionType.LEFT)
+ // I suppose due to a bug, having a more than one mark and one above a value of 100
+ // makes the rendering of the marks wrong in rtl. This doesn't happen setting the scale as not flippable
+ // and then manually inverting it
+ panel_size_scale.set_flippable(false)
+ panel_size_scale.set_inverted(true)
+ }
+
+ // App icon style option
+ this._builder
+ .get_object('appicon_style_combo')
+ .set_active_id(this._settings.get_string('appicon-style'))
+ this._builder
+ .get_object('appicon_style_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string('appicon-style', widget.get_active_id())
+ })
+
+ // Dots Position option
+ let dotPosition = this._settings.get_string('dot-position')
+
+ switch (dotPosition) {
+ case 'BOTTOM':
+ this._builder.get_object('dots_bottom_button').set_active(true)
+ break
+ case 'TOP':
+ this._builder.get_object('dots_top_button').set_active(true)
+ break
+ case 'LEFT':
+ this._builder.get_object('dots_left_button').set_active(true)
+ break
+ case 'RIGHT':
+ this._builder.get_object('dots_right_button').set_active(true)
+ break
+ }
+
+ this._builder
+ .get_object('dot_style_focused_combo')
+ .set_active_id(this._settings.get_string('dot-style-focused'))
+ this._builder
+ .get_object('dot_style_focused_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string('dot-style-focused', widget.get_active_id())
+ })
+
+ this._builder
+ .get_object('dot_style_unfocused_combo')
+ .set_active_id(this._settings.get_string('dot-style-unfocused'))
+ this._builder
+ .get_object('dot_style_unfocused_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string('dot-style-unfocused', widget.get_active_id())
+ })
+
+ for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) {
+ let idx = i
+ this._builder
+ .get_object('dot_color_' + idx + '_colorbutton')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ let hexString = cssHexString(css)
+ this._settings.set_string('dot-color-' + idx, hexString)
+ })
+
+ this._builder
+ .get_object('dot_color_unfocused_' + idx + '_colorbutton')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ let hexString = cssHexString(css)
+ this._settings.set_string('dot-color-unfocused-' + idx, hexString)
})
}
- _setPreviewTitlePosition() {
- switch (this._settings.get_string('window-preview-title-position')) {
- case 'BOTTOM':
- this._builder.get_object('preview_title_position_bottom_button').set_active(true);
- break;
- case 'TOP':
- this._builder.get_object('preview_title_position_top_button').set_active(true);
- break;
+ this._builder
+ .get_object('dot_color_apply_all_button')
+ .connect('clicked', () => {
+ for (let i = 2; i <= MAX_WINDOW_INDICATOR; i++) {
+ this._settings.set_value(
+ 'dot-color-' + i,
+ this._settings.get_value('dot-color-1'),
+ )
+ let rgba = new Gdk.RGBA()
+ rgba.parse(this._settings.get_string('dot-color-' + i))
+ this._builder
+ .get_object('dot_color_' + i + '_colorbutton')
+ .set_rgba(rgba)
}
+ })
+
+ this._builder
+ .get_object('dot_color_unfocused_apply_all_button')
+ .connect('clicked', () => {
+ for (let i = 2; i <= MAX_WINDOW_INDICATOR; i++) {
+ this._settings.set_value(
+ 'dot-color-unfocused-' + i,
+ this._settings.get_value('dot-color-unfocused-1'),
+ )
+ let rgba = new Gdk.RGBA()
+ rgba.parse(this._settings.get_string('dot-color-unfocused-' + i))
+ this._builder
+ .get_object('dot_color_unfocused_' + i + '_colorbutton')
+ .set_rgba(rgba)
+ }
+ })
+
+ this._builder
+ .get_object('focus_highlight_color_colorbutton')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ let hexString = cssHexString(css)
+ this._settings.set_string('focus-highlight-color', hexString)
+ })
+
+ this._builder
+ .get_object('dot_style_options_button')
+ .connect('clicked', () => {
+ let box = this._builder.get_object('box_dots_options')
+
+ let dialog = this._createPreferencesDialog(
+ _('Running Indicator Options'),
+ box,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'dot-color-dominant',
+ this._settings.get_default_value('dot-color-dominant'),
+ )
+ this._settings.set_value(
+ 'dot-color-override',
+ this._settings.get_default_value('dot-color-override'),
+ )
+ this._settings.set_value(
+ 'dot-color-unfocused-different',
+ this._settings.get_default_value('dot-color-unfocused-different'),
+ )
+
+ this._settings.set_value(
+ 'focus-highlight-color',
+ this._settings.get_default_value('focus-highlight-color'),
+ )
+ let rgba = new Gdk.RGBA()
+ rgba.parse(this._settings.get_string('focus-highlight-color'))
+ this._builder
+ .get_object('focus_highlight_color_colorbutton')
+ .set_rgba(rgba)
+
+ this._settings.set_value(
+ 'focus-highlight-opacity',
+ this._settings.get_default_value('focus-highlight-opacity'),
+ )
+ this._builder
+ .get_object('focus_highlight_opacity_spinbutton')
+ .set_value(this._settings.get_int('focus-highlight-opacity'))
+
+ for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) {
+ this._settings.set_value(
+ 'dot-color-' + i,
+ this._settings.get_default_value('dot-color-' + i),
+ )
+ rgba = new Gdk.RGBA()
+ rgba.parse(this._settings.get_string('dot-color-' + i))
+ this._builder
+ .get_object('dot_color_' + i + '_colorbutton')
+ .set_rgba(rgba)
+
+ this._settings.set_value(
+ 'dot-color-unfocused-' + i,
+ this._settings.get_default_value('dot-color-unfocused-' + i),
+ )
+ rgba = new Gdk.RGBA()
+ rgba.parse(this._settings.get_string('dot-color-unfocused-' + i))
+ this._builder
+ .get_object('dot_color_unfocused_' + i + '_colorbutton')
+ .set_rgba(rgba)
+ }
+
+ this._settings.set_value(
+ 'dot-size',
+ this._settings.get_default_value('dot-size'),
+ )
+ this._builder
+ .get_object('dot_size_spinbutton')
+ .set_value(this._settings.get_int('dot-size'))
+
+ this._settings.set_value(
+ 'focus-highlight',
+ this._settings.get_default_value('focus-highlight'),
+ )
+ this._settings.set_value(
+ 'focus-highlight-dominant',
+ this._settings.get_default_value('focus-highlight-dominant'),
+ )
+ },
+ )
+
+ this._settings.bind(
+ 'dot-color-dominant',
+ this._builder.get_object('dot_color_dominant_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'dot-color-override',
+ this._builder.get_object('dot_color_override_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ // when either becomes active, turn the other off
+ this._builder
+ .get_object('dot_color_dominant_switch')
+ .connect('state-set', (widget) => {
+ if (widget.get_active())
+ this._settings.set_boolean('dot-color-override', false)
+ })
+ this._builder
+ .get_object('dot_color_override_switch')
+ .connect('state-set', (widget) => {
+ if (widget.get_active())
+ this._settings.set_boolean('dot-color-dominant', false)
+ else
+ this._settings.set_boolean('dot-color-unfocused-different', false)
+ })
+
+ this._settings.bind(
+ 'dot-color-unfocused-different',
+ this._builder.get_object('dot_color_unfocused_different_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'dot-color-override',
+ this._builder.get_object('grid_dot_color'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'dot-color-override',
+ this._builder.get_object('dot_color_unfocused_box'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'dot-color-unfocused-different',
+ this._builder.get_object('grid_dot_color_unfocused'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) {
+ let rgba = new Gdk.RGBA()
+ rgba.parse(this._settings.get_string('dot-color-' + i))
+ this._builder
+ .get_object('dot_color_' + i + '_colorbutton')
+ .set_rgba(rgba)
+
+ rgba = new Gdk.RGBA()
+ rgba.parse(this._settings.get_string('dot-color-unfocused-' + i))
+ this._builder
+ .get_object('dot_color_unfocused_' + i + '_colorbutton')
+ .set_rgba(rgba)
+ }
+
+ this._settings.bind(
+ 'focus-highlight',
+ this._builder.get_object('focus_highlight_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'focus-highlight',
+ this._builder.get_object('grid_focus_highlight_options'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'focus-highlight-dominant',
+ this._builder.get_object('focus_highlight_dominant_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'focus-highlight-dominant',
+ this._builder.get_object('focus_highlight_color_label'),
+ 'sensitive',
+ Gio.SettingsBindFlags.INVERT_BOOLEAN,
+ )
+
+ this._settings.bind(
+ 'focus-highlight-dominant',
+ this._builder.get_object('focus_highlight_color_colorbutton'),
+ 'sensitive',
+ Gio.SettingsBindFlags.INVERT_BOOLEAN,
+ )
+ ;(function () {
+ let rgba = new Gdk.RGBA()
+ rgba.parse(this._settings.get_string('focus-highlight-color'))
+ this._builder
+ .get_object('focus_highlight_color_colorbutton')
+ .set_rgba(rgba)
+ }).apply(this)
+
+ this._builder
+ .get_object('focus_highlight_opacity_spinbutton')
+ .set_value(this._settings.get_int('focus-highlight-opacity'))
+ this._builder
+ .get_object('focus_highlight_opacity_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int(
+ 'focus-highlight-opacity',
+ widget.get_value(),
+ )
+ })
+
+ this._builder
+ .get_object('dot_size_spinbutton')
+ .set_value(this._settings.get_int('dot-size'))
+ this._builder
+ .get_object('dot_size_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('dot-size', widget.get_value())
+ })
+
+ dialog.show()
+ dialog.set_default_size(1, 1)
+ })
+
+ //multi-monitor
+ this.monitors = this._settings.get_value('available-monitors').deep_unpack()
+
+ let dtpPrimaryMonitorIndex = this.monitors.indexOf(
+ this._settings.get_int('primary-monitor'),
+ )
+
+ if (dtpPrimaryMonitorIndex < 0) {
+ dtpPrimaryMonitorIndex = 0
}
- _showFileChooser(title, params, acceptBtn, acceptHandler) {
- let dialog = new Gtk.FileChooserDialog(mergeObjects({ title: title, transient_for: this.notebook.get_root() }, params));
+ this._currentMonitorIndex = this.monitors[dtpPrimaryMonitorIndex]
- dialog.add_button("Cancel", Gtk.ResponseType.CANCEL);
- dialog.add_button(acceptBtn, Gtk.ResponseType.ACCEPT);
+ this._settings.connect('changed::panel-positions', () =>
+ this._updateVerticalRelatedOptions(),
+ )
+ this._updateVerticalRelatedOptions()
- dialog.show();
+ for (let i = 0; i < this.monitors.length; ++i) {
+ //the gnome-shell primary index is the first one in the "available-monitors" setting
+ let label = !i ? _('Primary monitor') : _('Monitor ') + (i + 1)
- dialog.connect('response', (dialog, id) => {
- if (id == Gtk.ResponseType.ACCEPT)
- acceptHandler.call(this, dialog.get_file().get_path());
-
- dialog.destroy();
- });
+ this._builder.get_object('multimon_primary_combo').append_text(label)
+ this._builder
+ .get_object('taskbar_position_monitor_combo')
+ .append_text(label)
}
+
+ this._builder
+ .get_object('multimon_primary_combo')
+ .set_active(dtpPrimaryMonitorIndex)
+ this._builder
+ .get_object('taskbar_position_monitor_combo')
+ .set_active(dtpPrimaryMonitorIndex)
+
+ this._settings.bind(
+ 'panel-element-positions-monitors-sync',
+ this._builder.get_object('taskbar_position_sync_button'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'panel-element-positions-monitors-sync',
+ this._builder.get_object('taskbar_position_monitor_combo'),
+ 'sensitive',
+ Gio.SettingsBindFlags.INVERT_BOOLEAN,
+ )
+
+ this._settings.connect(
+ 'changed::panel-element-positions-monitors-sync',
+ () => {
+ this._maybeDisableTopPosition()
+ // The anchor combo box may has different labels for single- or all-monitor configuration.
+ this._setAnchorLabels(this._currentMonitorIndex)
+ },
+ )
+
+ this._builder
+ .get_object('multimon_primary_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_int(
+ 'primary-monitor',
+ this.monitors[widget.get_active()],
+ )
+ })
+
+ this._builder
+ .get_object('taskbar_position_monitor_combo')
+ .connect('changed', (widget) => {
+ this._currentMonitorIndex = this.monitors[widget.get_active()]
+ this._updateWidgetSettingsForMonitor(this._currentMonitorIndex)
+ })
+
+ this._settings.bind(
+ 'multi-monitors',
+ this._builder.get_object('multimon_multi_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ if (this.monitors.length === 1) {
+ this._builder.get_object('multimon_multi_switch').set_sensitive(false)
+ }
+
+ const panel_length_scale = this._builder.get_object('panel_length_scale')
+ panel_length_scale.connect('value-changed', (widget) => {
+ const value = widget.get_value()
+ const monitorSync = this._settings.get_boolean(
+ 'panel-element-positions-monitors-sync',
+ )
+ const monitorsToSetFor = monitorSync
+ ? this.monitors
+ : [this._currentMonitorIndex]
+ monitorsToSetFor.forEach((monitorIndex) => {
+ PanelSettings.setPanelLength(this._settings, monitorIndex, value)
+ })
+
+ this._setAnchorWidgetSensitivity(value)
+ })
+
+ this._builder
+ .get_object('panel_anchor_combo')
+ .connect('changed', (widget) => {
+ const value = widget.get_active_id()
+ // Value can be null while anchor labels are being swapped out
+ if (value !== null) {
+ const monitorSync = this._settings.get_boolean(
+ 'panel-element-positions-monitors-sync',
+ )
+ const monitorsToSetFor = monitorSync
+ ? this.monitors
+ : [this._currentMonitorIndex]
+ monitorsToSetFor.forEach((monitorIndex) => {
+ PanelSettings.setPanelAnchor(this._settings, monitorIndex, value)
+ })
+ }
+ })
+
+ this._updateWidgetSettingsForMonitor(this._currentMonitorIndex)
+
+ //dynamic opacity
+ this._settings.bind(
+ 'trans-use-custom-bg',
+ this._builder.get_object('trans_bg_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'trans-use-custom-bg',
+ this._builder.get_object('trans_bg_color_colorbutton'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ let rgba = new Gdk.RGBA()
+ rgba.parse(this._settings.get_string('trans-bg-color'))
+ this._builder.get_object('trans_bg_color_colorbutton').set_rgba(rgba)
+
+ this._builder
+ .get_object('trans_bg_color_colorbutton')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ let hexString = cssHexString(css)
+ this._settings.set_string('trans-bg-color', hexString)
+ })
+
+ this._settings.bind(
+ 'trans-use-custom-opacity',
+ this._builder.get_object('trans_opacity_override_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'trans-use-custom-opacity',
+ this._builder.get_object('trans_opacity_box'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'trans-use-custom-opacity',
+ this._builder.get_object('trans_opacity_box2'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._builder
+ .get_object('trans_opacity_override_switch')
+ .connect('notify::active', (widget) => {
+ if (!widget.get_active())
+ this._builder.get_object('trans_dyn_switch').set_active(false)
+ })
+
+ this._builder
+ .get_object('trans_opacity_spinbutton')
+ .set_value(this._settings.get_double('trans-panel-opacity') * 100)
+ this._builder
+ .get_object('trans_opacity_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_double(
+ 'trans-panel-opacity',
+ widget.get_value() * 0.01,
+ )
+ })
+
+ this._settings.bind(
+ 'trans-use-dynamic-opacity',
+ this._builder.get_object('trans_dyn_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'trans-use-dynamic-opacity',
+ this._builder.get_object('trans_dyn_options_button'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'trans-dynamic-behavior',
+ this._builder.get_object('trans_options_window_type_combo'),
+ 'active-id',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'trans-use-custom-gradient',
+ this._builder.get_object('trans_gradient_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'trans-use-custom-gradient',
+ this._builder.get_object('trans_gradient_box'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'trans-use-custom-gradient',
+ this._builder.get_object('trans_gradient_box2'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ rgba.parse(this._settings.get_string('trans-gradient-top-color'))
+ this._builder.get_object('trans_gradient_color1_colorbutton').set_rgba(rgba)
+
+ this._builder
+ .get_object('trans_gradient_color1_colorbutton')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ let hexString = cssHexString(css)
+ this._settings.set_string('trans-gradient-top-color', hexString)
+ })
+
+ this._builder
+ .get_object('trans_gradient_color1_spinbutton')
+ .set_value(this._settings.get_double('trans-gradient-top-opacity') * 100)
+ this._builder
+ .get_object('trans_gradient_color1_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_double(
+ 'trans-gradient-top-opacity',
+ widget.get_value() * 0.01,
+ )
+ })
+
+ rgba.parse(this._settings.get_string('trans-gradient-bottom-color'))
+ this._builder.get_object('trans_gradient_color2_colorbutton').set_rgba(rgba)
+
+ this._builder
+ .get_object('trans_gradient_color2_colorbutton')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ let hexString = cssHexString(css)
+ this._settings.set_string('trans-gradient-bottom-color', hexString)
+ })
+
+ this._builder
+ .get_object('trans_gradient_color2_spinbutton')
+ .set_value(
+ this._settings.get_double('trans-gradient-bottom-opacity') * 100,
+ )
+ this._builder
+ .get_object('trans_gradient_color2_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_double(
+ 'trans-gradient-bottom-opacity',
+ widget.get_value() * 0.01,
+ )
+ })
+
+ this._builder
+ .get_object('trans_options_distance_spinbutton')
+ .set_value(this._settings.get_int('trans-dynamic-distance'))
+ this._builder
+ .get_object('trans_options_distance_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('trans-dynamic-distance', widget.get_value())
+ })
+
+ this._builder
+ .get_object('trans_options_min_opacity_spinbutton')
+ .set_value(this._settings.get_double('trans-dynamic-anim-target') * 100)
+ this._builder
+ .get_object('trans_options_min_opacity_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_double(
+ 'trans-dynamic-anim-target',
+ widget.get_value() * 0.01,
+ )
+ })
+
+ this._builder
+ .get_object('trans_options_anim_time_spinbutton')
+ .set_value(this._settings.get_int('trans-dynamic-anim-time'))
+ this._builder
+ .get_object('trans_options_anim_time_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('trans-dynamic-anim-time', widget.get_value())
+ })
+
+ this._builder
+ .get_object('trans_dyn_options_button')
+ .connect('clicked', () => {
+ let box = this._builder.get_object('box_dynamic_opacity_options')
+
+ let dialog = this._createPreferencesDialog(
+ _('Dynamic opacity options'),
+ box,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'trans-dynamic-behavior',
+ this._settings.get_default_value('trans-dynamic-behavior'),
+ )
+
+ this._settings.set_value(
+ 'trans-dynamic-distance',
+ this._settings.get_default_value('trans-dynamic-distance'),
+ )
+ this._builder
+ .get_object('trans_options_distance_spinbutton')
+ .set_value(this._settings.get_int('trans-dynamic-distance'))
+
+ this._settings.set_value(
+ 'trans-dynamic-anim-target',
+ this._settings.get_default_value('trans-dynamic-anim-target'),
+ )
+ this._builder
+ .get_object('trans_options_min_opacity_spinbutton')
+ .set_value(
+ this._settings.get_double('trans-dynamic-anim-target') * 100,
+ )
+
+ this._settings.set_value(
+ 'trans-dynamic-anim-time',
+ this._settings.get_default_value('trans-dynamic-anim-time'),
+ )
+ this._builder
+ .get_object('trans_options_anim_time_spinbutton')
+ .set_value(this._settings.get_int('trans-dynamic-anim-time'))
+ },
+ )
+
+ dialog.show()
+ dialog.set_default_size(1, 1)
+ })
+
+ this._settings.bind(
+ 'desktop-line-use-custom-color',
+ this._builder.get_object('override_show_desktop_line_color_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'desktop-line-use-custom-color',
+ this._builder.get_object('override_show_desktop_line_color_colorbutton'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ rgba.parse(this._settings.get_string('desktop-line-custom-color'))
+ this._builder
+ .get_object('override_show_desktop_line_color_colorbutton')
+ .set_rgba(rgba)
+ this._builder
+ .get_object('override_show_desktop_line_color_colorbutton')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ this._settings.set_string('desktop-line-custom-color', css)
+ })
+
+ this._settings.bind(
+ 'intellihide',
+ this._builder.get_object('intellihide_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'intellihide',
+ this._builder.get_object('intellihide_options_button'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'intellihide-hide-from-windows',
+ this._builder.get_object('intellihide_window_hide_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'intellihide-hide-from-windows',
+ this._builder.get_object('intellihide_behaviour_options'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'intellihide-behaviour',
+ this._builder.get_object('intellihide_behaviour_combo'),
+ 'active-id',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'intellihide-use-pressure',
+ this._builder.get_object('intellihide_use_pressure_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'intellihide-use-pressure',
+ this._builder.get_object('intellihide_use_pressure_options'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'intellihide-use-pressure',
+ this._builder.get_object('intellihide_use_pressure_options2'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'intellihide-show-in-fullscreen',
+ this._builder.get_object('intellihide_show_in_fullscreen_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'intellihide-only-secondary',
+ this._builder.get_object('intellihide_only_secondary_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'multi-monitors',
+ this._builder.get_object('grid_intellihide_only_secondary'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._builder
+ .get_object('multimon_multi_switch')
+ .connect('notify::active', (widget) => {
+ if (!widget.get_active())
+ this._builder
+ .get_object('intellihide_only_secondary_switch')
+ .set_active(false)
+ })
+
+ this._builder
+ .get_object('intellihide_pressure_threshold_spinbutton')
+ .set_value(this._settings.get_int('intellihide-pressure-threshold'))
+ this._builder
+ .get_object('intellihide_pressure_threshold_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int(
+ 'intellihide-pressure-threshold',
+ widget.get_value(),
+ )
+ })
+
+ this._builder
+ .get_object('intellihide_pressure_time_spinbutton')
+ .set_value(this._settings.get_int('intellihide-pressure-time'))
+ this._builder
+ .get_object('intellihide_pressure_time_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('intellihide-pressure-time', widget.get_value())
+ })
+
+ this._settings.bind(
+ 'intellihide-key-toggle-text',
+ this._builder.get_object('intellihide_toggle_entry'),
+ 'text',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.connect('changed::intellihide-key-toggle-text', () =>
+ setShortcut(this._settings, 'intellihide-key-toggle'),
+ )
+
+ this._builder
+ .get_object('intellihide_animation_time_spinbutton')
+ .set_value(this._settings.get_int('intellihide-animation-time'))
+ this._builder
+ .get_object('intellihide_animation_time_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('intellihide-animation-time', widget.get_value())
+ })
+
+ this._builder
+ .get_object('intellihide_close_delay_spinbutton')
+ .set_value(this._settings.get_int('intellihide-close-delay'))
+ this._builder
+ .get_object('intellihide_close_delay_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('intellihide-close-delay', widget.get_value())
+ })
+
+ this._builder
+ .get_object('intellihide_enable_start_delay_spinbutton')
+ .set_value(this._settings.get_int('intellihide-enable-start-delay'))
+ this._builder
+ .get_object('intellihide_enable_start_delay_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int(
+ 'intellihide-enable-start-delay',
+ widget.get_value(),
+ )
+ })
+
+ this._builder
+ .get_object('intellihide_options_button')
+ .connect('clicked', () => {
+ let box = this._builder.get_object('box_intellihide_options')
+
+ let dialog = this._createPreferencesDialog(
+ _('Intellihide options'),
+ box,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'intellihide-hide-from-windows',
+ this._settings.get_default_value('intellihide-hide-from-windows'),
+ )
+ this._settings.set_value(
+ 'intellihide-behaviour',
+ this._settings.get_default_value('intellihide-behaviour'),
+ )
+ this._settings.set_value(
+ 'intellihide-use-pressure',
+ this._settings.get_default_value('intellihide-use-pressure'),
+ )
+ this._settings.set_value(
+ 'intellihide-show-in-fullscreen',
+ this._settings.get_default_value(
+ 'intellihide-show-in-fullscreen',
+ ),
+ )
+ this._settings.set_value(
+ 'intellihide-only-secondary',
+ this._settings.get_default_value('intellihide-only-secondary'),
+ )
+
+ this._settings.set_value(
+ 'intellihide-pressure-threshold',
+ this._settings.get_default_value(
+ 'intellihide-pressure-threshold',
+ ),
+ )
+ this._builder
+ .get_object('intellihide_pressure_threshold_spinbutton')
+ .set_value(
+ this._settings.get_int('intellihide-pressure-threshold'),
+ )
+
+ this._settings.set_value(
+ 'intellihide-pressure-time',
+ this._settings.get_default_value('intellihide-pressure-time'),
+ )
+ this._builder
+ .get_object('intellihide_pressure_time_spinbutton')
+ .set_value(this._settings.get_int('intellihide-pressure-time'))
+
+ this._settings.set_value(
+ 'intellihide-key-toggle-text',
+ this._settings.get_default_value('intellihide-key-toggle-text'),
+ )
+
+ this._settings.set_value(
+ 'intellihide-animation-time',
+ this._settings.get_default_value('intellihide-animation-time'),
+ )
+ this._builder
+ .get_object('intellihide_animation_time_spinbutton')
+ .set_value(this._settings.get_int('intellihide-animation-time'))
+
+ this._settings.set_value(
+ 'intellihide-close-delay',
+ this._settings.get_default_value('intellihide-close-delay'),
+ )
+ this._builder
+ .get_object('intellihide_close_delay_spinbutton')
+ .set_value(this._settings.get_int('intellihide-close-delay'))
+
+ this._settings.set_value(
+ 'intellihide-enable-start-delay',
+ this._settings.get_default_value(
+ 'intellihide-enable-start-delay',
+ ),
+ )
+ this._builder
+ .get_object('intellihide_enable_start_delay_spinbutton')
+ .set_value(
+ this._settings.get_int('intellihide-enable-start-delay'),
+ )
+ },
+ )
+
+ dialog.show()
+ dialog.set_default_size(1, 1)
+ })
+
+ // Behavior panel
+
+ this._builder
+ .get_object('show_applications_side_padding_spinbutton')
+ .set_value(this._settings.get_int('show-apps-icon-side-padding'))
+ this._builder
+ .get_object('show_applications_side_padding_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int(
+ 'show-apps-icon-side-padding',
+ widget.get_value(),
+ )
+ })
+
+ this._settings.bind(
+ 'show-apps-override-escape',
+ this._builder.get_object('show_applications_esc_key_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'show-showdesktop-hover',
+ this._builder.get_object('show_showdesktop_hide_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'show-showdesktop-hover',
+ this._builder.get_object('grid_show_showdesktop_hide_options'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'show-showdesktop-hover',
+ this._builder.get_object('grid_show_showdesktop_hide_options2'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'show-window-previews',
+ this._builder.get_object('show_window_previews_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'show-window-previews',
+ this._builder.get_object('show_window_previews_button'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'show-tooltip',
+ this._builder.get_object('show_tooltip_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'show-favorites',
+ this._builder.get_object('show_favorite_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'show-favorites-all-monitors',
+ this._builder.get_object('multimon_multi_show_favorites_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'show-favorites',
+ this._builder.get_object('multimon_multi_show_favorites_switch'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'show-running-apps',
+ this._builder.get_object('show_runnning_apps_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._setPreviewTitlePosition()
+
+ this._builder
+ .get_object('grid_preview_title_font_color_colorbutton')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ let hexString = cssHexString(css)
+ this._settings.set_string('window-preview-title-font-color', hexString)
+ })
+
+ this._builder
+ .get_object('show_window_previews_button')
+ .connect('clicked', () => {
+ let scrolledWindow = this._builder.get_object(
+ 'box_window_preview_options',
+ )
+
+ let dialog = this._createPreferencesDialog(
+ _('Window preview options'),
+ scrolledWindow,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'show-window-previews-timeout',
+ this._settings.get_default_value('show-window-previews-timeout'),
+ )
+ this._builder
+ .get_object('preview_timeout_spinbutton')
+ .set_value(this._settings.get_int('show-window-previews-timeout'))
+
+ this._settings.set_value(
+ 'leave-timeout',
+ this._settings.get_default_value('leave-timeout'),
+ )
+ this._builder
+ .get_object('leave_timeout_spinbutton')
+ .set_value(this._settings.get_int('leave-timeout'))
+
+ this._settings.set_value(
+ 'window-preview-hide-immediate-click',
+ this._settings.get_default_value(
+ 'window-preview-hide-immediate-click',
+ ),
+ )
+
+ this._settings.set_value(
+ 'window-preview-animation-time',
+ this._settings.get_default_value('window-preview-animation-time'),
+ )
+ this._builder
+ .get_object('animation_time_spinbutton')
+ .set_value(
+ this._settings.get_int('window-preview-animation-time'),
+ )
+
+ this._settings.set_value(
+ 'preview-use-custom-opacity',
+ this._settings.get_default_value('preview-use-custom-opacity'),
+ )
+
+ this._settings.set_value(
+ 'window-preview-use-custom-icon-size',
+ this._settings.get_default_value(
+ 'window-preview-use-custom-icon-size',
+ ),
+ )
+
+ this._settings.set_value(
+ 'preview-custom-opacity',
+ this._settings.get_default_value('preview-custom-opacity'),
+ )
+ this._builder
+ .get_object('preview_custom_opacity_spinbutton')
+ .set_value(this._settings.get_int('preview-custom-opacity'))
+
+ this._settings.set_value(
+ 'window-preview-title-position',
+ this._settings.get_default_value('window-preview-title-position'),
+ )
+ this._setPreviewTitlePosition()
+
+ this._settings.set_value(
+ 'peek-mode',
+ this._settings.get_default_value('peek-mode'),
+ )
+ this._settings.set_value(
+ 'window-preview-show-title',
+ this._settings.get_default_value('window-preview-show-title'),
+ )
+ this._settings.set_value(
+ 'enter-peek-mode-timeout',
+ this._settings.get_default_value('enter-peek-mode-timeout'),
+ )
+ this._builder
+ .get_object('enter_peek_mode_timeout_spinbutton')
+ .set_value(this._settings.get_int('enter-peek-mode-timeout'))
+ this._settings.set_value(
+ 'peek-mode-opacity',
+ this._settings.get_default_value('peek-mode-opacity'),
+ )
+ this._builder
+ .get_object('peek_mode_opacity_spinbutton')
+ .set_value(this._settings.get_int('peek-mode-opacity'))
+
+ this._settings.set_value(
+ 'window-preview-size',
+ this._settings.get_default_value('window-preview-size'),
+ )
+ this._builder
+ .get_object('preview_size_spinbutton')
+ .set_value(this._settings.get_int('window-preview-size'))
+
+ this._settings.set_value(
+ 'window-preview-fixed-x',
+ this._settings.get_default_value('window-preview-fixed-x'),
+ )
+ this._settings.set_value(
+ 'window-preview-fixed-y',
+ this._settings.get_default_value('window-preview-fixed-y'),
+ )
+
+ this._settings.set_value(
+ 'window-preview-aspect-ratio-x',
+ this._settings.get_default_value('window-preview-aspect-ratio-x'),
+ )
+ this._builder
+ .get_object('preview_aspect_ratio_x_combo')
+ .set_active_id(
+ this._settings
+ .get_int('window-preview-aspect-ratio-x')
+ .toString(),
+ )
+
+ this._settings.set_value(
+ 'window-preview-aspect-ratio-y',
+ this._settings.get_default_value('window-preview-aspect-ratio-y'),
+ )
+ this._builder
+ .get_object('preview_aspect_ratio_y_combo')
+ .set_active_id(
+ this._settings
+ .get_int('window-preview-aspect-ratio-y')
+ .toString(),
+ )
+
+ this._settings.set_value(
+ 'window-preview-padding',
+ this._settings.get_default_value('window-preview-padding'),
+ )
+ this._builder
+ .get_object('preview_padding_spinbutton')
+ .set_value(this._settings.get_int('window-preview-padding'))
+
+ this._settings.set_value(
+ 'preview-middle-click-close',
+ this._settings.get_default_value('preview-middle-click-close'),
+ )
+
+ this._settings.set_value(
+ 'window-preview-title-font-size',
+ this._settings.get_default_value(
+ 'window-preview-title-font-size',
+ ),
+ )
+ this._builder
+ .get_object('preview_title_size_spinbutton')
+ .set_value(
+ this._settings.get_int('window-preview-title-font-size'),
+ )
+
+ this._settings.set_value(
+ 'window-preview-custom-icon-size',
+ this._settings.get_default_value(
+ 'window-preview-custom-icon-size',
+ ),
+ )
+ this._builder
+ .get_object('preview_custom_icon_size_spinbutton')
+ .set_value(
+ this._settings.get_int('window-preview-custom-icon-size'),
+ )
+
+ this._settings.set_value(
+ 'window-preview-title-font-weight',
+ this._settings.get_default_value(
+ 'window-preview-title-font-weight',
+ ),
+ )
+ this._builder
+ .get_object('grid_preview_title_weight_combo')
+ .set_active_id(
+ this._settings.get_string('window-preview-title-font-weight'),
+ )
+
+ this._settings.set_value(
+ 'window-preview-title-font-color',
+ this._settings.get_default_value(
+ 'window-preview-title-font-color',
+ ),
+ )
+ let rgba = new Gdk.RGBA()
+ rgba.parse(
+ this._settings.get_string('window-preview-title-font-color'),
+ )
+ this._builder
+ .get_object('grid_preview_title_font_color_colorbutton')
+ .set_rgba(rgba)
+ },
+ )
+
+ this._builder
+ .get_object('preview_timeout_spinbutton')
+ .set_value(this._settings.get_int('show-window-previews-timeout'))
+ this._builder
+ .get_object('preview_timeout_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int(
+ 'show-window-previews-timeout',
+ widget.get_value(),
+ )
+ })
+
+ this._settings.bind(
+ 'preview-middle-click-close',
+ this._builder.get_object('preview_middle_click_close_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'window-preview-fixed-x',
+ this._builder.get_object('preview_aspect_ratio_x_fixed_togglebutton'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'window-preview-fixed-y',
+ this._builder.get_object('preview_aspect_ratio_y_fixed_togglebutton'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'preview-use-custom-opacity',
+ this._builder.get_object('preview_custom_opacity_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'preview-use-custom-opacity',
+ this._builder.get_object('preview_custom_opacity_spinbutton'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'window-preview-use-custom-icon-size',
+ this._builder.get_object('preview_custom_icon_size_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'window-preview-use-custom-icon-size',
+ this._builder.get_object('preview_custom_icon_size_spinbutton'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._builder
+ .get_object('preview_custom_opacity_spinbutton')
+ .set_value(this._settings.get_int('preview-custom-opacity'))
+ this._builder
+ .get_object('preview_custom_opacity_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('preview-custom-opacity', widget.get_value())
+ })
+
+ this._settings.bind(
+ 'peek-mode',
+ this._builder.get_object('peek_mode_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'peek-mode',
+ this._builder.get_object('grid_enter_peek_mode_timeout'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'peek-mode',
+ this._builder.get_object('grid_peek_mode_opacity'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'window-preview-show-title',
+ this._builder.get_object('preview_show_title_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'window-preview-show-title',
+ this._builder.get_object('grid_preview_custom_icon_size'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'window-preview-show-title',
+ this._builder.get_object('grid_preview_title_size'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'window-preview-show-title',
+ this._builder.get_object('grid_preview_title_weight'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'window-preview-show-title',
+ this._builder.get_object('grid_preview_title_font_color'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._builder
+ .get_object('enter_peek_mode_timeout_spinbutton')
+ .set_value(this._settings.get_int('enter-peek-mode-timeout'))
+ this._builder
+ .get_object('enter_peek_mode_timeout_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int(
+ 'enter-peek-mode-timeout',
+ widget.get_value(),
+ )
+ })
+
+ this._builder
+ .get_object('leave_timeout_spinbutton')
+ .set_value(this._settings.get_int('leave-timeout'))
+ this._builder
+ .get_object('leave_timeout_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('leave-timeout', widget.get_value())
+ })
+
+ this._settings.bind(
+ 'window-preview-hide-immediate-click',
+ this._builder.get_object('preview_immediate_click_button'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._builder
+ .get_object('animation_time_spinbutton')
+ .set_value(this._settings.get_int('window-preview-animation-time'))
+ this._builder
+ .get_object('animation_time_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int(
+ 'window-preview-animation-time',
+ widget.get_value(),
+ )
+ })
+
+ this._builder
+ .get_object('peek_mode_opacity_spinbutton')
+ .set_value(this._settings.get_int('peek-mode-opacity'))
+ this._builder
+ .get_object('peek_mode_opacity_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('peek-mode-opacity', widget.get_value())
+ })
+
+ this._builder
+ .get_object('preview_size_spinbutton')
+ .set_value(this._settings.get_int('window-preview-size'))
+ this._builder
+ .get_object('preview_size_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('window-preview-size', widget.get_value())
+ })
+
+ this._builder
+ .get_object('preview_aspect_ratio_x_combo')
+ .set_active_id(
+ this._settings.get_int('window-preview-aspect-ratio-x').toString(),
+ )
+ this._builder
+ .get_object('preview_aspect_ratio_x_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_int(
+ 'window-preview-aspect-ratio-x',
+ parseInt(widget.get_active_id(), 10),
+ )
+ })
+
+ this._builder
+ .get_object('preview_aspect_ratio_y_combo')
+ .set_active_id(
+ this._settings.get_int('window-preview-aspect-ratio-y').toString(),
+ )
+ this._builder
+ .get_object('preview_aspect_ratio_y_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_int(
+ 'window-preview-aspect-ratio-y',
+ parseInt(widget.get_active_id(), 10),
+ )
+ })
+
+ this._builder
+ .get_object('preview_padding_spinbutton')
+ .set_value(this._settings.get_int('window-preview-padding'))
+ this._builder
+ .get_object('preview_padding_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('window-preview-padding', widget.get_value())
+ })
+
+ this._builder
+ .get_object('preview_title_size_spinbutton')
+ .set_value(this._settings.get_int('window-preview-title-font-size'))
+ this._builder
+ .get_object('preview_title_size_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int(
+ 'window-preview-title-font-size',
+ widget.get_value(),
+ )
+ })
+
+ this._builder
+ .get_object('preview_custom_icon_size_spinbutton')
+ .set_value(this._settings.get_int('window-preview-custom-icon-size'))
+ this._builder
+ .get_object('preview_custom_icon_size_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int(
+ 'window-preview-custom-icon-size',
+ widget.get_value(),
+ )
+ })
+
+ this._builder
+ .get_object('grid_preview_title_weight_combo')
+ .set_active_id(
+ this._settings.get_string('window-preview-title-font-weight'),
+ )
+ this._builder
+ .get_object('grid_preview_title_weight_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string(
+ 'window-preview-title-font-weight',
+ widget.get_active_id(),
+ )
+ })
+ ;(function () {
+ let rgba = new Gdk.RGBA()
+ rgba.parse(
+ this._settings.get_string('window-preview-title-font-color'),
+ )
+ this._builder
+ .get_object('grid_preview_title_font_color_colorbutton')
+ .set_rgba(rgba)
+ }).apply(this)
+
+ dialog.show()
+ })
+
+ this._settings.bind(
+ 'isolate-workspaces',
+ this._builder.get_object('isolate_workspaces_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'isolate-monitors',
+ this._builder.get_object('multimon_multi_isolate_monitor_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'overview-click-to-exit',
+ this._builder.get_object('clicktoexit_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'hide-overview-on-startup',
+ this._builder.get_object('hide_overview_on_startup_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'group-apps',
+ this._builder.get_object('group_apps_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.INVERT_BOOLEAN,
+ )
+
+ this._settings.bind(
+ 'group-apps',
+ this._builder.get_object('show_group_apps_options_button'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.INVERT_BOOLEAN,
+ )
+
+ this._settings.bind(
+ 'progress-show-count',
+ this._builder.get_object('show_notification_badge_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._builder
+ .get_object('group_apps_label_font_color_colorbutton')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ let hexString = cssHexString(css)
+ this._settings.set_string('group-apps-label-font-color', hexString)
+ })
+
+ this._builder
+ .get_object('group_apps_label_font_color_minimized_colorbutton')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ let hexString = cssHexString(css)
+ this._settings.set_string(
+ 'group-apps-label-font-color-minimized',
+ hexString,
+ )
+ })
+
+ this._settings.bind(
+ 'group-apps-use-fixed-width',
+ this._builder.get_object('group_apps_use_fixed_width_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'group-apps-underline-unfocused',
+ this._builder.get_object('group_apps_underline_unfocused_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'group-apps-use-launchers',
+ this._builder.get_object('group_apps_use_launchers_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._builder
+ .get_object('show_group_apps_options_button')
+ .connect('clicked', () => {
+ let box = this._builder.get_object('box_group_apps_options')
+
+ let dialog = this._createPreferencesDialog(
+ _('Ungrouped application options'),
+ box,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'group-apps-label-font-size',
+ this._settings.get_default_value('group-apps-label-font-size'),
+ )
+ this._builder
+ .get_object('group_apps_label_font_size_spinbutton')
+ .set_value(this._settings.get_int('group-apps-label-font-size'))
+
+ this._settings.set_value(
+ 'group-apps-label-font-weight',
+ this._settings.get_default_value('group-apps-label-font-weight'),
+ )
+ this._builder
+ .get_object('group_apps_label_font_weight_combo')
+ .set_active_id(
+ this._settings.get_string('group-apps-label-font-weight'),
+ )
+
+ this._settings.set_value(
+ 'group-apps-label-font-color',
+ this._settings.get_default_value('group-apps-label-font-color'),
+ )
+ let rgba = new Gdk.RGBA()
+ rgba.parse(this._settings.get_string('group-apps-label-font-color'))
+ this._builder
+ .get_object('group_apps_label_font_color_colorbutton')
+ .set_rgba(rgba)
+
+ this._settings.set_value(
+ 'group-apps-label-font-color-minimized',
+ this._settings.get_default_value(
+ 'group-apps-label-font-color-minimized',
+ ),
+ )
+ let minimizedFontColor = new Gdk.RGBA()
+ minimizedFontColor.parse(
+ this._settings.get_string(
+ 'group-apps-label-font-color-minimized',
+ ),
+ )
+ this._builder
+ .get_object('group_apps_label_font_color_minimized_colorbutton')
+ .set_rgba(minimizedFontColor)
+
+ this._settings.set_value(
+ 'group-apps-label-max-width',
+ this._settings.get_default_value('group-apps-label-max-width'),
+ )
+ this._builder
+ .get_object('group_apps_label_max_width_spinbutton')
+ .set_value(this._settings.get_int('group-apps-label-max-width'))
+
+ this._settings.set_value(
+ 'group-apps-use-fixed-width',
+ this._settings.get_default_value('group-apps-use-fixed-width'),
+ )
+ this._settings.set_value(
+ 'group-apps-underline-unfocused',
+ this._settings.get_default_value(
+ 'group-apps-underline-unfocused',
+ ),
+ )
+ this._settings.set_value(
+ 'group-apps-use-launchers',
+ this._settings.get_default_value('group-apps-use-launchers'),
+ )
+ },
+ )
+
+ this._builder
+ .get_object('group_apps_label_font_size_spinbutton')
+ .set_value(this._settings.get_int('group-apps-label-font-size'))
+ this._builder
+ .get_object('group_apps_label_font_size_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int(
+ 'group-apps-label-font-size',
+ widget.get_value(),
+ )
+ })
+
+ this._builder
+ .get_object('group_apps_label_font_weight_combo')
+ .set_active_id(
+ this._settings.get_string('group-apps-label-font-weight'),
+ )
+ this._builder
+ .get_object('group_apps_label_font_weight_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string(
+ 'group-apps-label-font-weight',
+ widget.get_active_id(),
+ )
+ })
+ ;(function () {
+ let rgba = new Gdk.RGBA()
+ rgba.parse(this._settings.get_string('group-apps-label-font-color'))
+ this._builder
+ .get_object('group_apps_label_font_color_colorbutton')
+ .set_rgba(rgba)
+ }).apply(this)
+ ;(function () {
+ let rgba = new Gdk.RGBA()
+ rgba.parse(
+ this._settings.get_string('group-apps-label-font-color-minimized'),
+ )
+ this._builder
+ .get_object('group_apps_label_font_color_minimized_colorbutton')
+ .set_rgba(rgba)
+ }).apply(this)
+
+ this._builder
+ .get_object('group_apps_label_max_width_spinbutton')
+ .set_value(this._settings.get_int('group-apps-label-max-width'))
+ this._builder
+ .get_object('group_apps_label_max_width_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int(
+ 'group-apps-label-max-width',
+ widget.get_value(),
+ )
+ })
+
+ dialog.show()
+ dialog.set_default_size(600, 1)
+ })
+
+ this._builder
+ .get_object('click_action_combo')
+ .set_active_id(this._settings.get_string('click-action'))
+ this._builder
+ .get_object('click_action_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string('click-action', widget.get_active_id())
+ })
+
+ this._builder
+ .get_object('shift_click_action_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string('shift-click-action', widget.get_active_id())
+ })
+
+ this._builder
+ .get_object('middle_click_action_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string('middle-click-action', widget.get_active_id())
+ })
+ this._builder
+ .get_object('shift_middle_click_action_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string(
+ 'shift-middle-click-action',
+ widget.get_active_id(),
+ )
+ })
+
+ // Create dialog for middle-click options
+ this._builder
+ .get_object('middle_click_options_button')
+ .connect('clicked', () => {
+ let box = this._builder.get_object('box_middle_click_options')
+
+ let dialog = this._createPreferencesDialog(
+ _('Customize middle-click behavior'),
+ box,
+ () => {
+ // restore default settings for the relevant keys
+ let keys = [
+ 'shift-click-action',
+ 'middle-click-action',
+ 'shift-middle-click-action',
+ ]
+ keys.forEach(function (val) {
+ this._settings.set_value(
+ val,
+ this._settings.get_default_value(val),
+ )
+ }, this)
+ this._builder
+ .get_object('shift_click_action_combo')
+ .set_active_id(this._settings.get_string('shift-click-action'))
+ this._builder
+ .get_object('middle_click_action_combo')
+ .set_active_id(this._settings.get_string('middle-click-action'))
+ this._builder
+ .get_object('shift_middle_click_action_combo')
+ .set_active_id(
+ this._settings.get_string('shift-middle-click-action'),
+ )
+ },
+ )
+
+ this._builder
+ .get_object('shift_click_action_combo')
+ .set_active_id(this._settings.get_string('shift-click-action'))
+
+ this._builder
+ .get_object('middle_click_action_combo')
+ .set_active_id(this._settings.get_string('middle-click-action'))
+
+ this._builder
+ .get_object('shift_middle_click_action_combo')
+ .set_active_id(this._settings.get_string('shift-middle-click-action'))
+
+ this._settings.bind(
+ 'shift-click-action',
+ this._builder.get_object('shift_click_action_combo'),
+ 'active-id',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'middle-click-action',
+ this._builder.get_object('middle_click_action_combo'),
+ 'active-id',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'shift-middle-click-action',
+ this._builder.get_object('shift_middle_click_action_combo'),
+ 'active-id',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ dialog.show()
+ dialog.set_default_size(700, 1)
+ })
+
+ this._builder
+ .get_object('scroll_panel_combo')
+ .set_active_id(this._settings.get_string('scroll-panel-action'))
+ this._builder
+ .get_object('scroll_panel_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string('scroll-panel-action', widget.get_active_id())
+ })
+
+ this._builder
+ .get_object('scroll_icon_combo')
+ .set_active_id(this._settings.get_string('scroll-icon-action'))
+ this._builder
+ .get_object('scroll_icon_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string('scroll-icon-action', widget.get_active_id())
+ })
+
+ // Create dialog for panel scroll options
+ this._builder
+ .get_object('scroll_panel_options_button')
+ .connect('clicked', () => {
+ let box = this._builder.get_object('scroll_panel_options_box')
+
+ let dialog = this._createPreferencesDialog(
+ _('Customize panel scroll behavior'),
+ box,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'scroll-panel-delay',
+ this._settings.get_default_value('scroll-panel-delay'),
+ )
+ this._builder
+ .get_object('scroll_panel_options_delay_spinbutton')
+ .set_value(this._settings.get_int('scroll-panel-delay'))
+
+ this._settings.set_value(
+ 'scroll-panel-show-ws-popup',
+ this._settings.get_default_value('scroll-panel-show-ws-popup'),
+ )
+ },
+ )
+
+ this._builder
+ .get_object('scroll_panel_options_delay_spinbutton')
+ .set_value(this._settings.get_int('scroll-panel-delay'))
+ this._builder
+ .get_object('scroll_panel_options_delay_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('scroll-panel-delay', widget.get_value())
+ })
+
+ this._settings.bind(
+ 'scroll-panel-show-ws-popup',
+ this._builder.get_object('scroll_panel_options_show_ws_popup_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ dialog.show()
+ dialog.set_default_size(640, 1)
+ })
+
+ // Create dialog for icon scroll options
+ this._builder
+ .get_object('scroll_icon_options_button')
+ .connect('clicked', () => {
+ let box = this._builder.get_object('scroll_icon_options_box')
+
+ let dialog = this._createPreferencesDialog(
+ _('Customize icon scroll behavior'),
+ box,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'scroll-icon-delay',
+ this._settings.get_default_value('scroll-icon-delay'),
+ )
+ this._builder
+ .get_object('scroll_icon_options_delay_spinbutton')
+ .set_value(this._settings.get_int('scroll-icon-delay'))
+ },
+ )
+
+ this._builder
+ .get_object('scroll_icon_options_delay_spinbutton')
+ .set_value(this._settings.get_int('scroll-icon-delay'))
+ this._builder
+ .get_object('scroll_icon_options_delay_spinbutton')
+ .connect('value-changed', (widget) => {
+ this._settings.set_int('scroll-icon-delay', widget.get_value())
+ })
+
+ dialog.show()
+ dialog.set_default_size(640, 1)
+ })
+
+ this._settings.bind(
+ 'hot-keys',
+ this._builder.get_object('hot_keys_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.bind(
+ 'hot-keys',
+ this._builder.get_object('overlay_button'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._builder.get_object('overlay_combo').connect('changed', (widget) => {
+ this._settings.set_string('hotkeys-overlay-combo', widget.get_active_id())
+ })
+
+ this._settings.bind(
+ 'shortcut-previews',
+ this._builder.get_object('shortcut_preview_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._builder
+ .get_object('shortcut_num_keys_combo')
+ .set_active_id(this._settings.get_string('shortcut-num-keys'))
+ this._builder
+ .get_object('shortcut_num_keys_combo')
+ .connect('changed', (widget) => {
+ this._settings.set_string('shortcut-num-keys', widget.get_active_id())
+ })
+
+ this._settings.connect('changed::hotkey-prefix-text', () => {
+ checkHotkeyPrefix(this._settings)
+ })
+
+ this._builder
+ .get_object('hotkey_prefix_combo')
+ .set_active_id(this._settings.get_string('hotkey-prefix-text'))
+
+ this._settings.bind(
+ 'hotkey-prefix-text',
+ this._builder.get_object('hotkey_prefix_combo'),
+ 'active-id',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._builder
+ .get_object('overlay_combo')
+ .set_active_id(this._settings.get_string('hotkeys-overlay-combo'))
+
+ this._settings.bind(
+ 'hotkeys-overlay-combo',
+ this._builder.get_object('overlay_combo'),
+ 'active-id',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'overlay-timeout',
+ this._builder.get_object('timeout_spinbutton'),
+ 'value',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ if (this._settings.get_string('hotkeys-overlay-combo') !== 'TEMPORARILY') {
+ this._builder.get_object('timeout_spinbutton').set_sensitive(false)
+ }
+
+ this._settings.connect('changed::hotkeys-overlay-combo', () => {
+ if (this._settings.get_string('hotkeys-overlay-combo') !== 'TEMPORARILY')
+ this._builder.get_object('timeout_spinbutton').set_sensitive(false)
+ else this._builder.get_object('timeout_spinbutton').set_sensitive(true)
+ })
+
+ this._settings.bind(
+ 'shortcut-text',
+ this._builder.get_object('shortcut_entry'),
+ 'text',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+ this._settings.connect('changed::shortcut-text', () => {
+ setShortcut(this._settings, 'shortcut')
+ })
+
+ // Create dialog for number overlay options
+ this._builder.get_object('overlay_button').connect('clicked', () => {
+ let box = this._builder.get_object('box_overlay_shortcut')
+
+ let dialog = this._createPreferencesDialog(
+ _('Advanced hotkeys options'),
+ box,
+ () => {
+ // restore default settings for the relevant keys
+ let keys = [
+ 'hotkey-prefix-text',
+ 'shortcut-text',
+ 'hotkeys-overlay-combo',
+ 'overlay-timeout',
+ 'shortcut-previews',
+ ]
+ keys.forEach(function (val) {
+ this._settings.set_value(val, this._settings.get_default_value(val))
+ }, this)
+ },
+ )
+
+ dialog.show()
+ dialog.set_default_size(600, 1)
+ })
+
+ // setup dialog for secondary menu options
+ this._builder
+ .get_object('secondarymenu_options_button')
+ .connect('clicked', () => {
+ let box = this._builder.get_object('box_secondarymenu_options')
+
+ let dialog = this._createPreferencesDialog(
+ _('Secondary Menu Options'),
+ box,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'secondarymenu-contains-appmenu',
+ this._settings.get_default_value(
+ 'secondarymenu-contains-appmenu',
+ ),
+ )
+ this._settings.set_value(
+ 'secondarymenu-contains-showdetails',
+ this._settings.get_default_value(
+ 'secondarymenu-contains-showdetails',
+ ),
+ )
+ },
+ )
+
+ // TODO setting secondarymenu-contains-appmenu is not being used anywhere
+ this._settings.bind(
+ 'secondarymenu-contains-appmenu',
+ this._builder.get_object('secondarymenu_appmenu_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'secondarymenu-contains-showdetails',
+ this._builder.get_object('secondarymenu_showdetails_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ dialog.show()
+ dialog.set_default_size(480, 1)
+ })
+
+ // setup dialog for advanced options
+ this._builder
+ .get_object('button_advanced_options')
+ .connect('clicked', () => {
+ let box = this._builder.get_object('box_advanced_options')
+
+ let dialog = this._createPreferencesDialog(_('Advanced Options'), box)
+
+ dialog.show()
+ dialog.set_default_size(480, 1)
+ })
+
+ // Fine-tune panel
+
+ let sizeScales = [
+ {
+ objectName: 'tray_size_scale',
+ valueName: 'tray-size',
+ range: DEFAULT_FONT_SIZES,
+ },
+ {
+ objectName: 'leftbox_size_scale',
+ valueName: 'leftbox-size',
+ range: DEFAULT_FONT_SIZES,
+ },
+ {
+ objectName: 'appicon_margin_scale',
+ valueName: 'appicon-margin',
+ range: DEFAULT_MARGIN_SIZES,
+ },
+ {
+ objectName: 'appicon_margin_todesktop_scale',
+ valueName: 'appicon-margin-todesktop',
+ range: DEFAULT_MARGIN_SIZES,
+ },
+ {
+ objectName: 'appicon_margin_toscreenborder_scale',
+ valueName: 'appicon-margin-toscreenborder',
+ range: DEFAULT_MARGIN_SIZES,
+ },
+ {
+ objectName: 'appicon_padding_scale',
+ valueName: 'appicon-padding',
+ range: DEFAULT_MARGIN_SIZES,
+ },
+ {
+ objectName: 'tray_padding_scale',
+ valueName: 'tray-padding',
+ range: DEFAULT_PADDING_SIZES,
+ },
+ {
+ objectName: 'leftbox_padding_scale',
+ valueName: 'leftbox-padding',
+ range: DEFAULT_PADDING_SIZES,
+ },
+ {
+ objectName: 'statusicon_padding_scale',
+ valueName: 'status-icon-padding',
+ range: DEFAULT_PADDING_SIZES,
+ },
+ { objectName: 'panel_length_scale', valueName: '', range: LENGTH_MARKS },
+ {
+ objectName: 'highlight_appicon_borderradius',
+ valueName: 'highlight-appicon-hover-border-radius',
+ range: [16, 12, 8, 4, 2, 0],
+ },
+ ]
+
+ for (const idx in sizeScales) {
+ let size_scale = this._builder.get_object(sizeScales[idx].objectName)
+ let range = sizeScales[idx].range
+ size_scale.set_range(range[range.length - 1], range[0])
+ let value
+ if (sizeScales[idx].objectName === 'panel_length_scale') {
+ value = PanelSettings.getPanelLength(
+ this._settings,
+ this._currentMonitorIndex,
+ )
+ } else {
+ value = this._settings.get_int(sizeScales[idx].valueName)
+ }
+ size_scale.set_value(value)
+ // Add marks from range arrays, omitting the first and last values.
+ range.slice(1, -1).forEach(function (val) {
+ size_scale.add_mark(val, Gtk.PositionType.TOP, val.toString())
+ })
+
+ // Corrent for rtl languages
+ if (this._rtl) {
+ // Flip value position: this is not done automatically
+ size_scale.set_value_pos(Gtk.PositionType.LEFT)
+ // I suppose due to a bug, having a more than one mark and one above a value of 100
+ // makes the rendering of the marks wrong in rtl. This doesn't happen setting the scale as not flippable
+ // and then manually inverting it
+ size_scale.set_flippable(false)
+ size_scale.set_inverted(true)
+ }
+ }
+
+ this._settings.bind(
+ 'animate-app-switch',
+ this._builder.get_object('animate_app_switch_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'animate-window-launch',
+ this._builder.get_object('animate_window_launch_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'animate-appicon-hover',
+ this._builder.get_object('animate_appicon_hover_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'animate-appicon-hover',
+ this._builder.get_object('animate_appicon_hover_button'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ {
+ this._settings.bind(
+ 'animate-appicon-hover-animation-type',
+ this._builder.get_object('animate_appicon_hover_options_type_combo'),
+ 'active-id',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ let scales = [
+ [
+ 'animate_appicon_hover_options_duration_scale',
+ 'animate-appicon-hover-animation-duration',
+ 1,
+ ],
+ [
+ 'animate_appicon_hover_options_rotation_scale',
+ 'animate-appicon-hover-animation-rotation',
+ 1,
+ ],
+ [
+ 'animate_appicon_hover_options_travel_scale',
+ 'animate-appicon-hover-animation-travel',
+ 100,
+ ],
+ [
+ 'animate_appicon_hover_options_zoom_scale',
+ 'animate-appicon-hover-animation-zoom',
+ 100,
+ ],
+ [
+ 'animate_appicon_hover_options_convexity_scale',
+ 'animate-appicon-hover-animation-convexity',
+ 1,
+ ],
+ [
+ 'animate_appicon_hover_options_extent_scale',
+ 'animate-appicon-hover-animation-extent',
+ 1,
+ ],
+ ]
+
+ let updateScale = (scale) => {
+ let [id, key, factor] = scale
+ let type = this._settings.get_string(
+ 'animate-appicon-hover-animation-type',
+ )
+ let value = this._settings.get_value(key).deep_unpack()[type]
+ let defaultValue = this._settings.get_default_value(key).deep_unpack()[
+ type
+ ]
+ this._builder.get_object(id).sensitive = defaultValue !== undefined
+ this._builder.get_object(id).set_value(value * factor || 0)
+ this._builder.get_object(id).clear_marks()
+ this._builder
+ .get_object(id)
+ .add_mark(
+ defaultValue * factor,
+ Gtk.PositionType.TOP,
+ defaultValue !== undefined
+ ? (defaultValue * factor).toString()
+ : ' ',
+ )
+ }
+
+ scales.forEach((scale) => {
+ let [id, key, factor] = scale
+ this._settings.connect('changed::' + key, () => updateScale(scale))
+ this._builder.get_object(id).connect('value-changed', (widget) => {
+ let type = this._settings.get_string(
+ 'animate-appicon-hover-animation-type',
+ )
+ let variant = this._settings.get_value(key)
+ let unpacked = variant.deep_unpack()
+ if (unpacked[type] != widget.get_value() / factor) {
+ unpacked[type] = widget.get_value() / factor
+ this._settings.set_value(
+ key,
+ new GLib.Variant(variant.get_type_string(), unpacked),
+ )
+ }
+ })
+ })
+
+ this._settings.connect(
+ 'changed::animate-appicon-hover-animation-type',
+ () => scales.forEach(updateScale),
+ )
+ scales.forEach(updateScale)
+ }
+
+ this._builder
+ .get_object('animate_appicon_hover_button')
+ .connect('clicked', () => {
+ let box = this._builder.get_object('animate_appicon_hover_options')
+
+ let dialog = this._createPreferencesDialog(
+ _('App icon animation options'),
+ box,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'animate-appicon-hover-animation-type',
+ this._settings.get_default_value(
+ 'animate-appicon-hover-animation-type',
+ ),
+ )
+ this._settings.set_value(
+ 'animate-appicon-hover-animation-duration',
+ this._settings.get_default_value(
+ 'animate-appicon-hover-animation-duration',
+ ),
+ )
+ this._settings.set_value(
+ 'animate-appicon-hover-animation-rotation',
+ this._settings.get_default_value(
+ 'animate-appicon-hover-animation-rotation',
+ ),
+ )
+ this._settings.set_value(
+ 'animate-appicon-hover-animation-travel',
+ this._settings.get_default_value(
+ 'animate-appicon-hover-animation-travel',
+ ),
+ )
+ this._settings.set_value(
+ 'animate-appicon-hover-animation-zoom',
+ this._settings.get_default_value(
+ 'animate-appicon-hover-animation-zoom',
+ ),
+ )
+ this._settings.set_value(
+ 'animate-appicon-hover-animation-convexity',
+ this._settings.get_default_value(
+ 'animate-appicon-hover-animation-convexity',
+ ),
+ )
+ this._settings.set_value(
+ 'animate-appicon-hover-animation-extent',
+ this._settings.get_default_value(
+ 'animate-appicon-hover-animation-extent',
+ ),
+ )
+ },
+ )
+
+ dialog.show()
+ })
+
+ this._settings.bind(
+ 'highlight-appicon-hover',
+ this._builder.get_object('highlight_appicon_hover_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'highlight-appicon-hover',
+ this._builder.get_object('highlight_appicon_hover_button'),
+ 'sensitive',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ {
+ rgba.parse(
+ this._settings.get_string('highlight-appicon-hover-background-color'),
+ )
+ this._builder.get_object('highlight_appicon_color').set_rgba(rgba)
+ this._builder
+ .get_object('highlight_appicon_color')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ this._settings.set_string(
+ 'highlight-appicon-hover-background-color',
+ css,
+ )
+ })
+
+ rgba.parse(
+ this._settings.get_string('highlight-appicon-pressed-background-color'),
+ )
+ this._builder.get_object('pressed_appicon_color').set_rgba(rgba)
+ this._builder
+ .get_object('pressed_appicon_color')
+ .connect('color-set', (button) => {
+ let rgba = button.get_rgba()
+ let css = rgba.to_string()
+ this._settings.set_string(
+ 'highlight-appicon-pressed-background-color',
+ css,
+ )
+ })
+
+ let scales = [
+ [
+ 'highlight_appicon_borderradius',
+ 'highlight-appicon-hover-border-radius',
+ ],
+ ]
+
+ const updateScale = (scale) => {
+ let [id, key] = scale
+ this._builder.get_object(id).set_value(this._settings.get_int(key))
+ }
+ scales.forEach((scale) => {
+ updateScale(scale)
+ let [id, key] = scale
+ this._builder.get_object(id).connect('value-changed', (widget) => {
+ this._settings.set_int(key, widget.get_value())
+ })
+ })
+ }
+
+ this._builder
+ .get_object('highlight_appicon_hover_button')
+ .connect('clicked', () => {
+ let box = this._builder.get_object('highlight_appicon_hover_options')
+
+ let dialog = this._createPreferencesDialog(
+ _('App icon highlight options'),
+ box,
+ () => {
+ // restore default settings
+ this._settings.set_value(
+ 'highlight-appicon-hover-background-color',
+ this._settings.get_default_value(
+ 'highlight-appicon-hover-background-color',
+ ),
+ )
+ rgba.parse(
+ this._settings.get_string(
+ 'highlight-appicon-hover-background-color',
+ ),
+ )
+ this._builder.get_object('highlight_appicon_color').set_rgba(rgba)
+ this._settings.set_value(
+ 'highlight-appicon-pressed-background-color',
+ this._settings.get_default_value(
+ 'highlight-appicon-pressed-background-color',
+ ),
+ )
+ rgba.parse(
+ this._settings.get_string(
+ 'highlight-appicon-pressed-background-color',
+ ),
+ )
+ this._builder.get_object('pressed_appicon_color').set_rgba(rgba)
+ this._settings.set_value(
+ 'highlight-appicon-hover-border-radius',
+ this._settings.get_default_value(
+ 'highlight-appicon-hover-border-radius',
+ ),
+ )
+ this._builder
+ .get_object('highlight_appicon_borderradius')
+ .set_value(
+ this._settings.get_int('highlight-appicon-hover-border-radius'),
+ )
+ },
+ )
+
+ dialog.show()
+ })
+
+ this._settings.bind(
+ 'stockgs-keep-dash',
+ this._builder.get_object('stockgs_dash_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'stockgs-keep-top-panel',
+ this._builder.get_object('stockgs_top_panel_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.connect('changed::stockgs-keep-top-panel', () =>
+ this._maybeDisableTopPosition(),
+ )
+
+ this._maybeDisableTopPosition()
+
+ this._settings.bind(
+ 'stockgs-panelbtn-click-only',
+ this._builder.get_object('stockgs_panelbtn_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ this._settings.bind(
+ 'stockgs-force-hotcorner',
+ this._builder.get_object('stockgs_hotcorner_switch'),
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT,
+ )
+
+ // About Panel
+
+ this._builder
+ .get_object('extension_version')
+ .set_label(
+ this._metadata.version.toString() +
+ (this._metadata.commit ? ' (' + this._metadata.commit + ')' : ''),
+ )
+
+ this._builder
+ .get_object('importexport_export_button')
+ .connect('clicked', (widget) => {
+ this._showFileChooser(
+ _('Export settings'),
+ { action: Gtk.FileChooserAction.SAVE },
+ 'Save',
+ (filename) => {
+ let file = Gio.file_new_for_path(filename)
+ let raw = file.replace(null, false, Gio.FileCreateFlags.NONE, null)
+ let out = Gio.BufferedOutputStream.new_sized(raw, 4096)
+
+ out.write_all(
+ GLib.spawn_command_line_sync('dconf dump ' + SCHEMA_PATH)[1],
+ null,
+ )
+ out.close(null)
+ },
+ )
+ })
+
+ this._builder
+ .get_object('importexport_import_button')
+ .connect('clicked', (widget) => {
+ this._showFileChooser(
+ _('Import settings'),
+ { action: Gtk.FileChooserAction.OPEN },
+ 'Open',
+ (filename) => {
+ if (filename && GLib.file_test(filename, GLib.FileTest.EXISTS)) {
+ let settingsFile = Gio.File.new_for_path(filename)
+ let [, pid, stdin, stdout, stderr] = GLib.spawn_async_with_pipes(
+ null,
+ ['dconf', 'load', SCHEMA_PATH],
+ null,
+ GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
+ null,
+ )
+
+ stdin = new Gio.UnixOutputStream({ fd: stdin, close_fd: true })
+ GLib.close(stdout)
+ GLib.close(stderr)
+
+ stdin.splice(
+ settingsFile.read(null),
+ Gio.OutputStreamSpliceFlags.CLOSE_SOURCE |
+ Gio.OutputStreamSpliceFlags.CLOSE_TARGET,
+ null,
+ )
+ }
+ },
+ )
+ })
+
+ // Donation panel
+
+ let revealDonateTimeout = 0
+ let donationIconSwitch = this._builder.get_object('donation_icon_switch')
+ let donationRevealer = this._builder.get_object('donation_revealer')
+ let hiddenDonateIcon = !!this._settings.get_string(
+ 'hide-donate-icon-unixtime',
+ )
+
+ this._builder
+ .get_object('donation_logo')
+ .set_from_file(`${this._path}/img/dash-to-panel-logo-light.svg`)
+ this._builder
+ .get_object('paypal_logo')
+ .set_from_file(`${this._path}/img/paypal.png`)
+ this._builder
+ .get_object('stripe_logo')
+ .set_from_file(`${this._path}/img/stripe.png`)
+ this._builder
+ .get_object('kofi_logo')
+ .set_from_file(`${this._path}/img/kofi.png`)
+
+ donationIconSwitch.set_active(hiddenDonateIcon)
+ donationRevealer.set_reveal_child(hiddenDonateIcon)
+
+ donationIconSwitch.connect('notify::active', (widget) =>
+ this._settings.set_string(
+ 'hide-donate-icon-unixtime',
+ widget.get_active() ? Date.now().toString() : '',
+ ),
+ )
+
+ this.notebook.connect('notify::visible-page', () => {
+ clearTimeout(revealDonateTimeout)
+
+ if (
+ this.notebook.visible_page_name == 'donation' &&
+ !donationRevealer.get_reveal_child()
+ )
+ revealDonateTimeout = setTimeout(
+ () => donationRevealer.set_reveal_child(true),
+ 10000,
+ )
+ })
+ }
+
+ _setPreviewTitlePosition() {
+ switch (this._settings.get_string('window-preview-title-position')) {
+ case 'BOTTOM':
+ this._builder
+ .get_object('preview_title_position_bottom_button')
+ .set_active(true)
+ break
+ case 'TOP':
+ this._builder
+ .get_object('preview_title_position_top_button')
+ .set_active(true)
+ break
+ }
+ }
+
+ _showFileChooser(title, params, acceptBtn, acceptHandler) {
+ let dialog = new Gtk.FileChooserDialog(
+ mergeObjects(
+ { title: title, transient_for: this.notebook.get_root() },
+ params,
+ ),
+ )
+
+ dialog.add_button('Cancel', Gtk.ResponseType.CANCEL)
+ dialog.add_button(acceptBtn, Gtk.ResponseType.ACCEPT)
+
+ dialog.show()
+
+ dialog.connect('response', (dialog, id) => {
+ if (id == Gtk.ResponseType.ACCEPT)
+ acceptHandler.call(this, dialog.get_file().get_path())
+
+ dialog.destroy()
+ })
+ }
}
-
-const BuilderScope = GObject.registerClass({
+const BuilderScope = GObject.registerClass(
+ {
Implements: [Gtk.BuilderScope],
-}, class BuilderScope extends GObject.Object {
-
+ },
+ class BuilderScope extends GObject.Object {
_init(preferences) {
- this._preferences = preferences;
- super._init();
+ this._preferences = preferences
+ super._init()
}
vfunc_create_closure(builder, handlerName, flags, connectObject) {
- if (flags & Gtk.BuilderClosureFlags.SWAPPED)
- throw new Error('Unsupported template signal flag "swapped"');
+ if (flags & Gtk.BuilderClosureFlags.SWAPPED)
+ throw new Error('Unsupported template signal flag "swapped"')
- if (typeof this[handlerName] === 'undefined')
- throw new Error(`${handlerName} is undefined`);
+ if (typeof this[handlerName] === 'undefined')
+ throw new Error(`${handlerName} is undefined`)
- return this[handlerName].bind(connectObject || this);
+ return this[handlerName].bind(connectObject || this)
}
on_btn_click(connectObject) {
- connectObject.set_label("Clicked");
+ connectObject.set_label('Clicked')
}
position_bottom_button_clicked_cb(button) {
- if (!this._preferences._ignorePositionRadios && button.get_active()) this._preferences._setPanelPosition(Pos.BOTTOM);
+ if (!this._preferences._ignorePositionRadios && button.get_active())
+ this._preferences._setPanelPosition(Pos.BOTTOM)
}
position_top_button_clicked_cb(button) {
- if (!this._preferences._ignorePositionRadios && button.get_active()) this._preferences._setPanelPosition(Pos.TOP);
+ if (!this._preferences._ignorePositionRadios && button.get_active())
+ this._preferences._setPanelPosition(Pos.TOP)
}
position_left_button_clicked_cb(button) {
- if (!this._preferences._ignorePositionRadios && button.get_active()) this._preferences._setPanelPosition(Pos.LEFT);
+ if (!this._preferences._ignorePositionRadios && button.get_active())
+ this._preferences._setPanelPosition(Pos.LEFT)
}
position_right_button_clicked_cb(button) {
- if (!this._preferences._ignorePositionRadios && button.get_active()) this._preferences._setPanelPosition(Pos.RIGHT);
+ if (!this._preferences._ignorePositionRadios && button.get_active())
+ this._preferences._setPanelPosition(Pos.RIGHT)
}
dots_bottom_button_toggled_cb(button) {
- if (button.get_active())
- this._preferences._settings.set_string('dot-position', "BOTTOM");
+ if (button.get_active())
+ this._preferences._settings.set_string('dot-position', 'BOTTOM')
}
dots_top_button_toggled_cb(button) {
- if (button.get_active())
- this._preferences._settings.set_string('dot-position', "TOP");
+ if (button.get_active())
+ this._preferences._settings.set_string('dot-position', 'TOP')
}
dots_left_button_toggled_cb(button) {
- if (button.get_active())
- this._preferences._settings.set_string('dot-position', "LEFT");
+ if (button.get_active())
+ this._preferences._settings.set_string('dot-position', 'LEFT')
}
dots_right_button_toggled_cb(button) {
- if (button.get_active())
- this._preferences._settings.set_string('dot-position', "RIGHT");
+ if (button.get_active())
+ this._preferences._settings.set_string('dot-position', 'RIGHT')
}
preview_title_position_bottom_button_toggled_cb(button) {
- if (button.get_active())
- this._preferences._settings.set_string('window-preview-title-position', 'BOTTOM');
+ if (button.get_active())
+ this._preferences._settings.set_string(
+ 'window-preview-title-position',
+ 'BOTTOM',
+ )
}
preview_title_position_top_button_toggled_cb(button) {
- if (button.get_active())
- this._preferences._settings.set_string('window-preview-title-position', 'TOP');
+ if (button.get_active())
+ this._preferences._settings.set_string(
+ 'window-preview-title-position',
+ 'TOP',
+ )
}
panel_size_scale_value_changed_cb(scale) {
- // Avoid settings the size continuously
- if (this._preferences._panel_size_timeout > 0)
- GLib.Source.remove(this._preferences._panel_size_timeout);
+ // Avoid settings the size continuously
+ if (this._preferences._panel_size_timeout > 0)
+ GLib.Source.remove(this._preferences._panel_size_timeout)
- this._preferences._panel_size_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => {
- const value = scale.get_value();
- const monitorSync = this._preferences._settings.get_boolean('panel-element-positions-monitors-sync');
- const monitorsToSetFor = monitorSync ? this._preferences.monitors : [this._preferences._currentMonitorIndex];
- monitorsToSetFor.forEach(monitorIndex => {
- PanelSettings.setPanelSize(this._preferences._settings, monitorIndex, value);
- });
+ this._preferences._panel_size_timeout = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ SCALE_UPDATE_TIMEOUT,
+ () => {
+ const value = scale.get_value()
+ const monitorSync = this._preferences._settings.get_boolean(
+ 'panel-element-positions-monitors-sync',
+ )
+ const monitorsToSetFor = monitorSync
+ ? this._preferences.monitors
+ : [this._preferences._currentMonitorIndex]
+ monitorsToSetFor.forEach((monitorIndex) => {
+ PanelSettings.setPanelSize(
+ this._preferences._settings,
+ monitorIndex,
+ value,
+ )
+ })
- this._preferences._panel_size_timeout = 0;
- return GLib.SOURCE_REMOVE;
- });
+ this._preferences._panel_size_timeout = 0
+ return GLib.SOURCE_REMOVE
+ },
+ )
}
tray_size_scale_value_changed_cb(scale) {
- // Avoid settings the size consinuosly
- if (this._preferences._tray_size_timeout > 0)
- GLib.Source.remove(this._preferences._tray_size_timeout);
+ // Avoid settings the size consinuosly
+ if (this._preferences._tray_size_timeout > 0)
+ GLib.Source.remove(this._preferences._tray_size_timeout)
- this._preferences._tray_size_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => {
- this._preferences._settings.set_int('tray-size', scale.get_value());
- this._preferences._tray_size_timeout = 0;
- return GLib.SOURCE_REMOVE;
- });
+ this._preferences._tray_size_timeout = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ SCALE_UPDATE_TIMEOUT,
+ () => {
+ this._preferences._settings.set_int('tray-size', scale.get_value())
+ this._preferences._tray_size_timeout = 0
+ return GLib.SOURCE_REMOVE
+ },
+ )
}
leftbox_size_scale_value_changed_cb(scale) {
- // Avoid settings the size consinuosly
- if (this._preferences._leftbox_size_timeout > 0)
- GLib.Source.remove(this._preferences._leftbox_size_timeout);
+ // Avoid settings the size consinuosly
+ if (this._preferences._leftbox_size_timeout > 0)
+ GLib.Source.remove(this._preferences._leftbox_size_timeout)
- this._preferences._leftbox_size_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => {
- this._preferences._settings.set_int('leftbox-size', scale.get_value());
- this._preferences._leftbox_size_timeout = 0;
- return GLib.SOURCE_REMOVE;
- });
+ this._preferences._leftbox_size_timeout = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ SCALE_UPDATE_TIMEOUT,
+ () => {
+ this._preferences._settings.set_int('leftbox-size', scale.get_value())
+ this._preferences._leftbox_size_timeout = 0
+ return GLib.SOURCE_REMOVE
+ },
+ )
}
appicon_margin_scale_value_changed_cb(scale) {
- // Avoid settings the size consinuosly
- if (this._preferences._appicon_margin_timeout > 0)
- GLib.Source.remove(this._preferences._appicon_margin_timeout);
+ // Avoid settings the size consinuosly
+ if (this._preferences._appicon_margin_timeout > 0)
+ GLib.Source.remove(this._preferences._appicon_margin_timeout)
- this._preferences._appicon_margin_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => {
- this._preferences._settings.set_int('appicon-margin', scale.get_value());
- this._preferences._appicon_margin_timeout = 0;
- return GLib.SOURCE_REMOVE;
- });
+ this._preferences._appicon_margin_timeout = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ SCALE_UPDATE_TIMEOUT,
+ () => {
+ this._preferences._settings.set_int(
+ 'appicon-margin',
+ scale.get_value(),
+ )
+ this._preferences._appicon_margin_timeout = 0
+ return GLib.SOURCE_REMOVE
+ },
+ )
}
appicon_margin_todesktop_scale_value_changed_cb(scale) {
- // Avoid settings the size consinuosly
- if (this._preferences._appicon_margin_todesktop_timeout > 0)
- GLib.Source.remove(this._preferences._appicon_margin_todesktop_timeout);
+ // Avoid settings the size consinuosly
+ if (this._preferences._appicon_margin_todesktop_timeout > 0)
+ GLib.Source.remove(this._preferences._appicon_margin_todesktop_timeout)
- this._preferences._appicon_margin_todesktop_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => {
- this._preferences._settings.set_int('appicon-margin-todesktop', scale.get_value());
- this._preferences._appicon_margin_todesktop_timeout = 0;
- return GLib.SOURCE_REMOVE;
- });
+ this._preferences._appicon_margin_todesktop_timeout = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ SCALE_UPDATE_TIMEOUT,
+ () => {
+ this._preferences._settings.set_int(
+ 'appicon-margin-todesktop',
+ scale.get_value(),
+ )
+ this._preferences._appicon_margin_todesktop_timeout = 0
+ return GLib.SOURCE_REMOVE
+ },
+ )
}
appicon_margin_toscreenborder_scale_value_changed_cb(scale) {
- // Avoid settings the size consinuosly
- if (this._preferences._appicon_margin_toscreenborder_timeout > 0)
- GLib.Source.remove(this._preferences._appicon_margin_toscreenborder_timeout);
+ // Avoid settings the size consinuosly
+ if (this._preferences._appicon_margin_toscreenborder_timeout > 0)
+ GLib.Source.remove(
+ this._preferences._appicon_margin_toscreenborder_timeout,
+ )
- this._preferences._appicon_margin_toscreenborder_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => {
- this._preferences._settings.set_int('appicon-margin-toscreenborder', scale.get_value());
- this._preferences._appicon_margin_toscreenborder_timeout = 0;
- return GLib.SOURCE_REMOVE;
- });
+ this._preferences._appicon_margin_toscreenborder_timeout =
+ GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => {
+ this._preferences._settings.set_int(
+ 'appicon-margin-toscreenborder',
+ scale.get_value(),
+ )
+ this._preferences._appicon_margin_toscreenborder_timeout = 0
+ return GLib.SOURCE_REMOVE
+ })
}
appicon_padding_scale_value_changed_cb(scale) {
- // Avoid settings the size consinuosly
- if (this._preferences._appicon_padding_timeout > 0)
- GLib.Source.remove(this._preferences._appicon_padding_timeout);
+ // Avoid settings the size consinuosly
+ if (this._preferences._appicon_padding_timeout > 0)
+ GLib.Source.remove(this._preferences._appicon_padding_timeout)
- this._preferences._appicon_padding_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => {
- this._preferences._settings.set_int('appicon-padding', scale.get_value());
- this._preferences._appicon_padding_timeout = 0;
- return GLib.SOURCE_REMOVE;
- });
+ this._preferences._appicon_padding_timeout = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ SCALE_UPDATE_TIMEOUT,
+ () => {
+ this._preferences._settings.set_int(
+ 'appicon-padding',
+ scale.get_value(),
+ )
+ this._preferences._appicon_padding_timeout = 0
+ return GLib.SOURCE_REMOVE
+ },
+ )
}
tray_padding_scale_value_changed_cb(scale) {
- // Avoid settings the size consinuosly
- if (this._preferences._tray_padding_timeout > 0)
- GLib.Source.remove(this._preferences._tray_padding_timeout);
+ // Avoid settings the size consinuosly
+ if (this._preferences._tray_padding_timeout > 0)
+ GLib.Source.remove(this._preferences._tray_padding_timeout)
- this._preferences._tray_padding_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => {
- this._preferences._settings.set_int('tray-padding', scale.get_value());
- this._preferences._tray_padding_timeout = 0;
- return GLib.SOURCE_REMOVE;
- });
+ this._preferences._tray_padding_timeout = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ SCALE_UPDATE_TIMEOUT,
+ () => {
+ this._preferences._settings.set_int('tray-padding', scale.get_value())
+ this._preferences._tray_padding_timeout = 0
+ return GLib.SOURCE_REMOVE
+ },
+ )
}
statusicon_padding_scale_value_changed_cb(scale) {
- // Avoid settings the size consinuosly
- if (this._preferences._statusicon_padding_timeout > 0)
- GLib.Source.remove(this._preferences._statusicon_padding_timeout);
+ // Avoid settings the size consinuosly
+ if (this._preferences._statusicon_padding_timeout > 0)
+ GLib.Source.remove(this._preferences._statusicon_padding_timeout)
- this._preferences._statusicon_padding_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => {
- this._preferences._settings.set_int('status-icon-padding', scale.get_value());
- this._preferences._statusicon_padding_timeout = 0;
- return GLib.SOURCE_REMOVE;
- });
+ this._preferences._statusicon_padding_timeout = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ SCALE_UPDATE_TIMEOUT,
+ () => {
+ this._preferences._settings.set_int(
+ 'status-icon-padding',
+ scale.get_value(),
+ )
+ this._preferences._statusicon_padding_timeout = 0
+ return GLib.SOURCE_REMOVE
+ },
+ )
}
leftbox_padding_scale_value_changed_cb(scale) {
- // Avoid settings the size consinuosly
- if (this._preferences._leftbox_padding_timeout > 0)
- GLib.Source.remove(this._preferences._leftbox_padding_timeout);
+ // Avoid settings the size consinuosly
+ if (this._preferences._leftbox_padding_timeout > 0)
+ GLib.Source.remove(this._preferences._leftbox_padding_timeout)
- this._preferences._leftbox_padding_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => {
- this._preferences._settings.set_int('leftbox-padding', scale.get_value());
- this._preferences._leftbox_padding_timeout = 0;
- return GLib.SOURCE_REMOVE;
- });
+ this._preferences._leftbox_padding_timeout = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ SCALE_UPDATE_TIMEOUT,
+ () => {
+ this._preferences._settings.set_int(
+ 'leftbox-padding',
+ scale.get_value(),
+ )
+ this._preferences._leftbox_padding_timeout = 0
+ return GLib.SOURCE_REMOVE
+ },
+ )
}
-});
-
+ },
+)
export default class DashToPanelPreferences extends ExtensionPreferences {
- fillPreferencesWindow(window) {
- window._settings = this.getSettings('org.gnome.shell.extensions.dash-to-panel');
+ fillPreferencesWindow(window) {
+ window._settings = this.getSettings(
+ 'org.gnome.shell.extensions.dash-to-panel',
+ )
- // use default width or window
- window.set_default_size(0, 740);
+ // use default width or window
+ window.set_default_size(0, 740)
- let preferences = new Preferences(window, window._settings, this.path);
- }
+ let preferences = new Preferences(window, window._settings, this.path)
+ }
}
diff --git a/progress.js b/progress.js
index 48105ab..b3fedd3 100644
--- a/progress.js
+++ b/progress.js
@@ -19,579 +19,683 @@
* This file is based on code from the Dash to Dock extension by micheleg
*/
-import Cairo from 'cairo';
-import Gio from 'gi://Gio';
-import Clutter from 'gi://Clutter';
-import Pango from 'gi://Pango';
-import St from 'gi://St';
-import * as Utils from './utils.js';
-import {SETTINGS} from './extension.js';
-
-import {EventEmitter} from 'resource:///org/gnome/shell/misc/signals.js';
+import Cairo from 'cairo'
+import Gio from 'gi://Gio'
+import Clutter from 'gi://Clutter'
+import Pango from 'gi://Pango'
+import St from 'gi://St'
+import * as Utils from './utils.js'
+import { SETTINGS } from './extension.js'
+import { EventEmitter } from 'resource:///org/gnome/shell/misc/signals.js'
export const ProgressManager = class extends EventEmitter {
+ constructor() {
+ super()
- constructor() {
- super();
+ this._entriesByDBusName = {}
- this._entriesByDBusName = {};
+ this._launcher_entry_dbus_signal_id = Gio.DBus.session.signal_subscribe(
+ null, // sender
+ 'com.canonical.Unity.LauncherEntry', // iface
+ null, // member
+ null, // path
+ null, // arg0
+ Gio.DBusSignalFlags.NONE,
+ this._onEntrySignalReceived.bind(this),
+ )
- this._launcher_entry_dbus_signal_id =
- Gio.DBus.session.signal_subscribe(null, // sender
- 'com.canonical.Unity.LauncherEntry', // iface
- null, // member
- null, // path
- null, // arg0
- Gio.DBusSignalFlags.NONE,
- this._onEntrySignalReceived.bind(this));
+ this._dbus_name_owner_changed_signal_id = Gio.DBus.session.signal_subscribe(
+ 'org.freedesktop.DBus', // sender
+ 'org.freedesktop.DBus', // interface
+ 'NameOwnerChanged', // member
+ '/org/freedesktop/DBus', // path
+ null, // arg0
+ Gio.DBusSignalFlags.NONE,
+ this._onDBusNameOwnerChanged.bind(this),
+ )
- this._dbus_name_owner_changed_signal_id =
- Gio.DBus.session.signal_subscribe('org.freedesktop.DBus', // sender
- 'org.freedesktop.DBus', // interface
- 'NameOwnerChanged', // member
- '/org/freedesktop/DBus', // path
- null, // arg0
- Gio.DBusSignalFlags.NONE,
- this._onDBusNameOwnerChanged.bind(this));
+ this._acquireUnityDBus()
+ }
- this._acquireUnityDBus();
+ destroy() {
+ if (this._launcher_entry_dbus_signal_id) {
+ Gio.DBus.session.signal_unsubscribe(this._launcher_entry_dbus_signal_id)
}
- destroy() {
- if (this._launcher_entry_dbus_signal_id) {
- Gio.DBus.session.signal_unsubscribe(this._launcher_entry_dbus_signal_id);
- }
-
- if (this._dbus_name_owner_changed_signal_id) {
- Gio.DBus.session.signal_unsubscribe(this._dbus_name_owner_changed_signal_id);
- }
-
- this._releaseUnityDBus();
+ if (this._dbus_name_owner_changed_signal_id) {
+ Gio.DBus.session.signal_unsubscribe(
+ this._dbus_name_owner_changed_signal_id,
+ )
}
- size() {
- return Object.keys(this._entriesByDBusName).length;
+ this._releaseUnityDBus()
+ }
+
+ size() {
+ return Object.keys(this._entriesByDBusName).length
+ }
+
+ lookupByDBusName(dbusName) {
+ return this._entriesByDBusName.hasOwnProperty(dbusName)
+ ? this._entriesByDBusName[dbusName]
+ : null
+ }
+
+ lookupById(appId) {
+ let ret = []
+ for (let dbusName in this._entriesByDBusName) {
+ let entry = this._entriesByDBusName[dbusName]
+ if (entry && entry.appId() == appId) {
+ ret.push(entry)
+ }
}
- lookupByDBusName(dbusName) {
- return this._entriesByDBusName.hasOwnProperty(dbusName) ? this._entriesByDBusName[dbusName] : null;
+ return ret
+ }
+
+ addEntry(entry) {
+ let existingEntry = this.lookupByDBusName(entry.dbusName())
+ if (existingEntry) {
+ existingEntry.update(entry)
+ } else {
+ this._entriesByDBusName[entry.dbusName()] = entry
+ this.emit('progress-entry-added', entry)
+ }
+ }
+
+ removeEntry(entry) {
+ delete this._entriesByDBusName[entry.dbusName()]
+ this.emit('progress-entry-removed', entry)
+ }
+
+ _acquireUnityDBus() {
+ if (!this._unity_bus_id) {
+ Gio.DBus.session.own_name(
+ 'com.canonical.Unity',
+ Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT,
+ null,
+ null,
+ )
+ }
+ }
+
+ _releaseUnityDBus() {
+ if (this._unity_bus_id) {
+ Gio.DBus.session.unown_name(this._unity_bus_id)
+ this._unity_bus_id = 0
+ }
+ }
+
+ _onEntrySignalReceived(
+ connection,
+ sender_name,
+ object_path,
+ interface_name,
+ signal_name,
+ parameters,
+ user_data,
+ ) {
+ if (!parameters || !signal_name) return
+
+ if (signal_name == 'Update') {
+ if (!sender_name) {
+ return
+ }
+
+ this._handleUpdateRequest(sender_name, parameters)
+ }
+ }
+
+ _onDBusNameOwnerChanged(
+ connection,
+ sender_name,
+ object_path,
+ interface_name,
+ signal_name,
+ parameters,
+ user_data,
+ ) {
+ if (!parameters || !this.size()) return
+
+ let [name, before, after] = parameters.deep_unpack()
+
+ if (!after) {
+ if (this._entriesByDBusName.hasOwnProperty(before)) {
+ this.removeEntry(this._entriesByDBusName[before])
+ }
+ }
+ }
+
+ _handleUpdateRequest(senderName, parameters) {
+ if (!senderName || !parameters) {
+ return
}
- lookupById(appId) {
- let ret = [];
- for (let dbusName in this._entriesByDBusName) {
- let entry = this._entriesByDBusName[dbusName];
- if (entry && entry.appId() == appId) {
- ret.push(entry);
- }
- }
+ let [appUri, properties] = parameters.deep_unpack()
+ let appId = appUri.replace(/(^\w+:|^)\/\//, '')
+ let entry = this.lookupByDBusName(senderName)
- return ret;
- }
-
- addEntry(entry) {
- let existingEntry = this.lookupByDBusName(entry.dbusName());
- if (existingEntry) {
- existingEntry.update(entry);
- } else {
- this._entriesByDBusName[entry.dbusName()] = entry;
- this.emit('progress-entry-added', entry);
- }
- }
-
- removeEntry(entry) {
- delete this._entriesByDBusName[entry.dbusName()]
- this.emit('progress-entry-removed', entry);
- }
-
- _acquireUnityDBus() {
- if (!this._unity_bus_id) {
- Gio.DBus.session.own_name('com.canonical.Unity',
- Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null);
- }
- }
-
- _releaseUnityDBus() {
- if (this._unity_bus_id) {
- Gio.DBus.session.unown_name(this._unity_bus_id);
- this._unity_bus_id = 0;
- }
- }
-
- _onEntrySignalReceived(connection, sender_name, object_path,
- interface_name, signal_name, parameters, user_data) {
- if (!parameters || !signal_name)
- return;
-
- if (signal_name == 'Update') {
- if (!sender_name) {
- return;
- }
-
- this._handleUpdateRequest(sender_name, parameters);
- }
- }
-
- _onDBusNameOwnerChanged(connection, sender_name, object_path,
- interface_name, signal_name, parameters, user_data) {
- if (!parameters || !this.size())
- return;
-
- let [name, before, after] = parameters.deep_unpack();
-
- if (!after) {
- if (this._entriesByDBusName.hasOwnProperty(before)) {
- this.removeEntry(this._entriesByDBusName[before]);
- }
- }
- }
-
- _handleUpdateRequest(senderName, parameters) {
- if (!senderName || !parameters) {
- return;
- }
-
- let [appUri, properties] = parameters.deep_unpack();
- let appId = appUri.replace(/(^\w+:|^)\/\//, '');
- let entry = this.lookupByDBusName(senderName);
-
- if (entry) {
- entry.setDBusName(senderName);
- entry.update(properties);
- } else {
- let entry = new AppProgress(senderName, appId, properties);
- this.addEntry(entry);
- }
- }
-};
-
-export class AppProgress extends EventEmitter {
-
- constructor(dbusName, appId, properties) {
- super();
-
- this._dbusName = dbusName;
- this._appId = appId;
- this._count = 0;
- this._countVisible = false;
- this._progress = 0.0;
- this._progressVisible = false;
- this._urgent = false;
- this.update(properties);
- }
-
- appId() {
- return this._appId;
- }
-
- dbusName() {
- return this._dbusName;
- }
-
- count() {
- return this._count;
- }
-
- setCount(count) {
- if (this._count != count) {
- this._count = count;
- this.emit('count-changed', this._count);
- }
- }
-
- countVisible() {
- return this._countVisible;
- }
-
- setCountVisible(countVisible) {
- if (this._countVisible != countVisible) {
- this._countVisible = countVisible;
- this.emit('count-visible-changed', this._countVisible);
- }
- }
-
- progress() {
- return this._progress;
- }
-
- setProgress(progress) {
- if (this._progress != progress) {
- this._progress = progress;
- this.emit('progress-changed', this._progress);
- }
- }
-
- progressVisible() {
- return this._progressVisible;
- }
-
- setProgressVisible(progressVisible) {
- if (this._progressVisible != progressVisible) {
- this._progressVisible = progressVisible;
- this.emit('progress-visible-changed', this._progressVisible);
- }
- }
-
- urgent() {
- return this._urgent;
- }
-
- setUrgent(urgent) {
- if (this._urgent != urgent) {
- this._urgent = urgent;
- this.emit('urgent-changed', this._urgent);
- }
- }
-
- setDBusName(dbusName) {
- if (this._dbusName != dbusName) {
- let oldName = this._dbusName;
- this._dbusName = dbusName;
- this.emit('dbus-name-changed', oldName);
- }
- }
-
- update(other) {
- if (other instanceof AppProgress) {
- this.setDBusName(other.dbusName())
- this.setCount(other.count());
- this.setCountVisible(other.countVisible());
- this.setProgress(other.progress());
- this.setProgressVisible(other.progressVisible())
- this.setUrgent(other.urgent());
- } else {
- for (let property in other) {
- if (other.hasOwnProperty(property)) {
- if (property == 'count') {
- this.setCount(other[property].get_int64());
- } else if (property == 'count-visible') {
- this.setCountVisible(SETTINGS.get_boolean('progress-show-count') && other[property].get_boolean());
- } else if (property == 'progress') {
- this.setProgress(other[property].get_double());
- } else if (property == 'progress-visible') {
- this.setProgressVisible(SETTINGS.get_boolean('progress-show-bar') && other[property].get_boolean());
- } else if (property == 'urgent') {
- this.setUrgent(other[property].get_boolean());
- } else {
- // Not implemented yet
- }
- }
- }
- }
+ if (entry) {
+ entry.setDBusName(senderName)
+ entry.update(properties)
+ } else {
+ let entry = new AppProgress(senderName, appId, properties)
+ this.addEntry(entry)
}
+ }
}
+export class AppProgress extends EventEmitter {
+ constructor(dbusName, appId, properties) {
+ super()
+
+ this._dbusName = dbusName
+ this._appId = appId
+ this._count = 0
+ this._countVisible = false
+ this._progress = 0.0
+ this._progressVisible = false
+ this._urgent = false
+ this.update(properties)
+ }
+
+ appId() {
+ return this._appId
+ }
+
+ dbusName() {
+ return this._dbusName
+ }
+
+ count() {
+ return this._count
+ }
+
+ setCount(count) {
+ if (this._count != count) {
+ this._count = count
+ this.emit('count-changed', this._count)
+ }
+ }
+
+ countVisible() {
+ return this._countVisible
+ }
+
+ setCountVisible(countVisible) {
+ if (this._countVisible != countVisible) {
+ this._countVisible = countVisible
+ this.emit('count-visible-changed', this._countVisible)
+ }
+ }
+
+ progress() {
+ return this._progress
+ }
+
+ setProgress(progress) {
+ if (this._progress != progress) {
+ this._progress = progress
+ this.emit('progress-changed', this._progress)
+ }
+ }
+
+ progressVisible() {
+ return this._progressVisible
+ }
+
+ setProgressVisible(progressVisible) {
+ if (this._progressVisible != progressVisible) {
+ this._progressVisible = progressVisible
+ this.emit('progress-visible-changed', this._progressVisible)
+ }
+ }
+
+ urgent() {
+ return this._urgent
+ }
+
+ setUrgent(urgent) {
+ if (this._urgent != urgent) {
+ this._urgent = urgent
+ this.emit('urgent-changed', this._urgent)
+ }
+ }
+
+ setDBusName(dbusName) {
+ if (this._dbusName != dbusName) {
+ let oldName = this._dbusName
+ this._dbusName = dbusName
+ this.emit('dbus-name-changed', oldName)
+ }
+ }
+
+ update(other) {
+ if (other instanceof AppProgress) {
+ this.setDBusName(other.dbusName())
+ this.setCount(other.count())
+ this.setCountVisible(other.countVisible())
+ this.setProgress(other.progress())
+ this.setProgressVisible(other.progressVisible())
+ this.setUrgent(other.urgent())
+ } else {
+ for (let property in other) {
+ if (other.hasOwnProperty(property)) {
+ if (property == 'count') {
+ this.setCount(other[property].get_int64())
+ } else if (property == 'count-visible') {
+ this.setCountVisible(
+ SETTINGS.get_boolean('progress-show-count') &&
+ other[property].get_boolean(),
+ )
+ } else if (property == 'progress') {
+ this.setProgress(other[property].get_double())
+ } else if (property == 'progress-visible') {
+ this.setProgressVisible(
+ SETTINGS.get_boolean('progress-show-bar') &&
+ other[property].get_boolean(),
+ )
+ } else if (property == 'urgent') {
+ this.setUrgent(other[property].get_boolean())
+ } else {
+ // Not implemented yet
+ }
+ }
+ }
+ }
+ }
+}
export const ProgressIndicator = class {
+ constructor(source, progressManager) {
+ this._source = source
+ this._progressManager = progressManager
+ this._signalsHandler = new Utils.GlobalSignalsHandler()
- constructor(source, progressManager) {
- this._source = source;
- this._progressManager = progressManager;
- this._signalsHandler = new Utils.GlobalSignalsHandler();
+ this._sourceDestroyId = this._source.connect('destroy', () => {
+ this._signalsHandler.destroy()
+ })
- this._sourceDestroyId = this._source.connect('destroy', () => {
- this._signalsHandler.destroy();
- });
+ this._notificationBadgeLabel = new St.Label({ style_class: 'badge' })
+ this._notificationBadgeBin = new St.Bin({
+ child: this._notificationBadgeLabel,
+ y: 2,
+ x: 2,
+ })
+ this._notificationBadgeLabel.add_style_class_name('notification-badge')
+ this._notificationBadgeCount = 0
+ this._notificationBadgeBin.hide()
- this._notificationBadgeLabel = new St.Label({ style_class: 'badge' });
- this._notificationBadgeBin = new St.Bin({
- child: this._notificationBadgeLabel, y: 2, x: 2
- });
- this._notificationBadgeLabel.add_style_class_name('notification-badge');
- this._notificationBadgeCount = 0;
- this._notificationBadgeBin.hide();
+ this._source._dtpIconContainer.add_child(this._notificationBadgeBin)
+ this._source._dtpIconContainer.connect(
+ 'notify::allocation',
+ this.updateNotificationBadge.bind(this),
+ )
- this._source._dtpIconContainer.add_child(this._notificationBadgeBin);
- this._source._dtpIconContainer.connect('notify::allocation', this.updateNotificationBadge.bind(this));
+ this._progressManagerEntries = []
+ this._progressManager.lookupById(this._source.app.id).forEach((entry) => {
+ this.insertEntry(entry)
+ })
- this._progressManagerEntries = [];
- this._progressManager.lookupById(this._source.app.id).forEach(
- (entry) => {
- this.insertEntry(entry);
- }
- );
+ this._signalsHandler.add(
+ [
+ this._progressManager,
+ 'progress-entry-added',
+ this._onEntryAdded.bind(this),
+ ],
+ [
+ this._progressManager,
+ 'progress-entry-removed',
+ this._onEntryRemoved.bind(this),
+ ],
+ )
+ }
- this._signalsHandler.add([
- this._progressManager,
- 'progress-entry-added',
- this._onEntryAdded.bind(this)
- ], [
- this._progressManager,
- 'progress-entry-removed',
- this._onEntryRemoved.bind(this)
- ]);
+ destroy() {
+ this._source.disconnect(this._sourceDestroyId)
+ this._signalsHandler.destroy()
+ }
+
+ _onEntryAdded(appProgress, entry) {
+ if (!entry || !entry.appId()) return
+ if (
+ this._source &&
+ this._source.app &&
+ this._source.app.id == entry.appId()
+ ) {
+ this.insertEntry(entry)
+ }
+ }
+
+ _onEntryRemoved(appProgress, entry) {
+ if (!entry || !entry.appId()) return
+
+ if (
+ this._source &&
+ this._source.app &&
+ this._source.app.id == entry.appId()
+ ) {
+ this.removeEntry(entry)
+ }
+ }
+
+ updateNotificationBadge() {
+ this._source.updateNumberOverlay(this._notificationBadgeBin)
+ this._notificationBadgeLabel.clutter_text.ellipsize =
+ Pango.EllipsizeMode.MIDDLE
+ }
+
+ _notificationBadgeCountToText(count) {
+ if (count <= 9999) {
+ return count.toString()
+ } else if (count < 1e5) {
+ let thousands = count / 1e3
+ return thousands.toFixed(1).toString() + 'k'
+ } else if (count < 1e6) {
+ let thousands = count / 1e3
+ return thousands.toFixed(0).toString() + 'k'
+ } else if (count < 1e8) {
+ let millions = count / 1e6
+ return millions.toFixed(1).toString() + 'M'
+ } else if (count < 1e9) {
+ let millions = count / 1e6
+ return millions.toFixed(0).toString() + 'M'
+ } else {
+ let billions = count / 1e9
+ return billions.toFixed(1).toString() + 'B'
+ }
+ }
+
+ setNotificationBadge(count) {
+ this._notificationBadgeCount = count
+ let text = this._notificationBadgeCountToText(count)
+ this._notificationBadgeLabel.set_text(text)
+ }
+
+ toggleNotificationBadge(activate) {
+ if (activate && this._notificationBadgeCount > 0) {
+ this.updateNotificationBadge()
+ this._notificationBadgeBin.show()
+ } else this._notificationBadgeBin.hide()
+ }
+
+ _showProgressOverlay() {
+ if (this._progressOverlayArea) {
+ this._updateProgressOverlay()
+ return
}
- destroy() {
- this._source.disconnect(this._sourceDestroyId);
- this._signalsHandler.destroy();
+ this._progressOverlayArea = new St.DrawingArea({
+ x_expand: true,
+ y_expand: true,
+ })
+ this._progressOverlayArea.add_style_class_name('progress-bar')
+ this._progressOverlayArea.connect('repaint', () => {
+ this._drawProgressOverlay(this._progressOverlayArea)
+ })
+
+ this._source._iconContainer.add_child(this._progressOverlayArea)
+ let node = this._progressOverlayArea.get_theme_node()
+
+ let [hasColor, color] = node.lookup_color('-progress-bar-background', false)
+ if (hasColor) this._progressbar_background = color
+ else
+ this._progressbar_background = new Utils.ColorUtils.Color({
+ red: 204,
+ green: 204,
+ blue: 204,
+ alpha: 255,
+ })
+ ;[hasColor, color] = node.lookup_color('-progress-bar-border', false)
+ if (hasColor) this._progressbar_border = color
+ else
+ this._progressbar_border = new Utils.ColorUtils.Color({
+ red: 230,
+ green: 230,
+ blue: 230,
+ alpha: 255,
+ })
+
+ this._updateProgressOverlay()
+ }
+
+ _hideProgressOverlay() {
+ if (this._progressOverlayArea) this._progressOverlayArea.destroy()
+
+ this._progressOverlayArea = null
+ this._progressbar_background = null
+ this._progressbar_border = null
+ }
+
+ _updateProgressOverlay() {
+ if (this._progressOverlayArea) {
+ this._progressOverlayArea.queue_repaint()
}
+ }
- _onEntryAdded(appProgress, entry) {
- if (!entry || !entry.appId())
- return;
- if (this._source && this._source.app && this._source.app.id == entry.appId()) {
- this.insertEntry(entry);
- }
+ _drawProgressOverlay(area) {
+ let scaleFactor = Utils.getScaleFactor()
+ let [surfaceWidth, surfaceHeight] = area.get_surface_size()
+ let cr = area.get_context()
+
+ let iconSize = this._source.icon.iconSize * scaleFactor
+
+ let x = Math.floor((surfaceWidth - iconSize) / 2)
+ let y = Math.floor((surfaceHeight - iconSize) / 2)
+
+ let lineWidth = Math.floor(1.0 * scaleFactor)
+ let padding = Math.floor(iconSize * 0.05)
+ let width = iconSize - 2.0 * padding
+ let height = Math.floor(Math.min(18.0 * scaleFactor, 0.2 * iconSize))
+ x += padding
+ y += iconSize - height - padding
+
+ cr.setLineWidth(lineWidth)
+
+ // Draw the outer stroke
+ let stroke = new Cairo.LinearGradient(0, y, 0, y + height)
+ let fill = null
+ stroke.addColorStopRGBA(0.5, 0.5, 0.5, 0.5, 0.1)
+ stroke.addColorStopRGBA(0.9, 0.8, 0.8, 0.8, 0.4)
+ Utils.drawRoundedLine(
+ cr,
+ x + lineWidth / 2.0,
+ y + lineWidth / 2.0,
+ width,
+ height,
+ true,
+ true,
+ stroke,
+ fill,
+ )
+
+ // Draw the background
+ x += lineWidth
+ y += lineWidth
+ width -= 2.0 * lineWidth
+ height -= 2.0 * lineWidth
+
+ stroke = Cairo.SolidPattern.createRGBA(0.2, 0.2, 0.2, 0.9)
+ fill = new Cairo.LinearGradient(0, y, 0, y + height)
+ fill.addColorStopRGBA(0.4, 0.25, 0.25, 0.25, 1.0)
+ fill.addColorStopRGBA(0.9, 0.35, 0.35, 0.35, 1.0)
+ Utils.drawRoundedLine(
+ cr,
+ x + lineWidth / 2.0,
+ y + lineWidth / 2.0,
+ width,
+ height,
+ true,
+ true,
+ stroke,
+ fill,
+ )
+
+ // Draw the finished bar
+ x += lineWidth
+ y += lineWidth
+ width -= 2.0 * lineWidth
+ height -= 2.0 * lineWidth
+
+ let finishedWidth = Math.ceil(this._progress * width)
+
+ let bg = this._progressbar_background
+ let bd = this._progressbar_border
+
+ stroke = Cairo.SolidPattern.createRGBA(
+ bd.red / 255,
+ bd.green / 255,
+ bd.blue / 255,
+ bd.alpha / 255,
+ )
+ fill = Cairo.SolidPattern.createRGBA(
+ bg.red / 255,
+ bg.green / 255,
+ bg.blue / 255,
+ bg.alpha / 255,
+ )
+
+ if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
+ Utils.drawRoundedLine(
+ cr,
+ x + lineWidth / 2.0 + width - finishedWidth,
+ y + lineWidth / 2.0,
+ finishedWidth,
+ height,
+ true,
+ true,
+ stroke,
+ fill,
+ )
+ else
+ Utils.drawRoundedLine(
+ cr,
+ x + lineWidth / 2.0,
+ y + lineWidth / 2.0,
+ finishedWidth,
+ height,
+ true,
+ true,
+ stroke,
+ fill,
+ )
+
+ cr.$dispose()
+ }
+
+ setProgress(progress) {
+ this._progress = Math.min(Math.max(progress, 0.0), 1.0)
+ this._updateProgressOverlay()
+ }
+
+ toggleProgressOverlay(activate) {
+ if (activate) {
+ this._showProgressOverlay()
+ } else {
+ this._hideProgressOverlay()
}
+ }
- _onEntryRemoved(appProgress, entry) {
- if (!entry || !entry.appId())
- return;
+ insertEntry(appProgress) {
+ if (
+ !appProgress ||
+ this._progressManagerEntries.indexOf(appProgress) !== -1
+ )
+ return
- if (this._source && this._source.app && this._source.app.id == entry.appId()) {
- this.removeEntry(entry);
- }
+ this._progressManagerEntries.push(appProgress)
+ this._selectEntry(appProgress)
+ }
+
+ removeEntry(appProgress) {
+ if (!appProgress || this._progressManagerEntries.indexOf(appProgress) == -1)
+ return
+
+ this._progressManagerEntries.splice(
+ this._progressManagerEntries.indexOf(appProgress),
+ 1,
+ )
+
+ if (this._progressManagerEntries.length > 0) {
+ this._selectEntry(
+ this._progressManagerEntries[this._progressManagerEntries.length - 1],
+ )
+ } else {
+ this.setNotificationBadge(0)
+ this.toggleNotificationBadge(false)
+ this.setProgress(0)
+ this.toggleProgressOverlay(false)
+ this.setUrgent(false)
}
+ }
- updateNotificationBadge() {
- this._source.updateNumberOverlay(this._notificationBadgeBin);
- this._notificationBadgeLabel.clutter_text.ellipsize = Pango.EllipsizeMode.MIDDLE;
+ _selectEntry(appProgress) {
+ if (!appProgress) return
+
+ this._signalsHandler.removeWithLabel('progress-entry')
+
+ this._signalsHandler.addWithLabel(
+ 'progress-entry',
+ [
+ appProgress,
+ 'count-changed',
+ (appProgress, value) => {
+ this.setNotificationBadge(value)
+ },
+ ],
+ [
+ appProgress,
+ 'count-visible-changed',
+ (appProgress, value) => {
+ this.toggleNotificationBadge(value)
+ },
+ ],
+ [
+ appProgress,
+ 'progress-changed',
+ (appProgress, value) => {
+ this.setProgress(value)
+ },
+ ],
+ [
+ appProgress,
+ 'progress-visible-changed',
+ (appProgress, value) => {
+ this.toggleProgressOverlay(value)
+ },
+ ],
+ [
+ appProgress,
+ 'urgent-changed',
+ (appProgress, value) => {
+ this.setUrgent(value)
+ },
+ ],
+ )
+
+ this.setNotificationBadge(appProgress.count())
+ this.toggleNotificationBadge(appProgress.countVisible())
+ this.setProgress(appProgress.progress())
+ this.toggleProgressOverlay(appProgress.progressVisible())
+
+ this._isUrgent = false
+ }
+
+ setUrgent(urgent) {
+ const icon = this._source.icon._iconBin
+ if (urgent) {
+ if (!this._isUrgent) {
+ icon.set_pivot_point(0.5, 0.5)
+ this._source.iconAnimator.addAnimation(icon, 'dance')
+ this._isUrgent = true
+ }
+ } else {
+ if (this._isUrgent) {
+ this._source.iconAnimator.removeAnimation(icon, 'dance')
+ this._isUrgent = false
+ }
+ icon.rotation_angle_z = 0
}
-
- _notificationBadgeCountToText(count) {
- if (count <= 9999) {
- return count.toString();
- } else if (count < 1e5) {
- let thousands = count / 1e3;
- return thousands.toFixed(1).toString() + "k";
- } else if (count < 1e6) {
- let thousands = count / 1e3;
- return thousands.toFixed(0).toString() + "k";
- } else if (count < 1e8) {
- let millions = count / 1e6;
- return millions.toFixed(1).toString() + "M";
- } else if (count < 1e9) {
- let millions = count / 1e6;
- return millions.toFixed(0).toString() + "M";
- } else {
- let billions = count / 1e9;
- return billions.toFixed(1).toString() + "B";
- }
- }
-
- setNotificationBadge(count) {
- this._notificationBadgeCount = count;
- let text = this._notificationBadgeCountToText(count);
- this._notificationBadgeLabel.set_text(text);
- }
-
- toggleNotificationBadge(activate) {
- if (activate && this._notificationBadgeCount > 0) {
- this.updateNotificationBadge();
- this._notificationBadgeBin.show();
- }
- else
- this._notificationBadgeBin.hide();
- }
-
- _showProgressOverlay() {
- if (this._progressOverlayArea) {
- this._updateProgressOverlay();
- return;
- }
-
- this._progressOverlayArea = new St.DrawingArea({x_expand: true, y_expand: true});
- this._progressOverlayArea.add_style_class_name('progress-bar');
- this._progressOverlayArea.connect('repaint', () => {
- this._drawProgressOverlay(this._progressOverlayArea);
- });
-
- this._source._iconContainer.add_child(this._progressOverlayArea);
- let node = this._progressOverlayArea.get_theme_node();
-
- let [hasColor, color] = node.lookup_color('-progress-bar-background', false);
- if (hasColor)
- this._progressbar_background = color
- else
- this._progressbar_background = new Utils.ColorUtils.Color({red: 204, green: 204, blue: 204, alpha: 255});
-
- [hasColor, color] = node.lookup_color('-progress-bar-border', false);
- if (hasColor)
- this._progressbar_border = color;
- else
- this._progressbar_border = new Utils.ColorUtils.Color({red: 230, green: 230, blue: 230, alpha: 255});
-
- this._updateProgressOverlay();
- }
-
- _hideProgressOverlay() {
- if (this._progressOverlayArea)
- this._progressOverlayArea.destroy();
-
- this._progressOverlayArea = null;
- this._progressbar_background = null;
- this._progressbar_border = null;
- }
-
- _updateProgressOverlay() {
-
- if (this._progressOverlayArea) {
- this._progressOverlayArea.queue_repaint();
- }
- }
-
- _drawProgressOverlay(area) {
- let scaleFactor = Utils.getScaleFactor();
- let [surfaceWidth, surfaceHeight] = area.get_surface_size();
- let cr = area.get_context();
-
- let iconSize = this._source.icon.iconSize * scaleFactor;
-
- let x = Math.floor((surfaceWidth - iconSize) / 2);
- let y = Math.floor((surfaceHeight - iconSize) / 2);
-
- let lineWidth = Math.floor(1.0 * scaleFactor);
- let padding = Math.floor(iconSize * 0.05);
- let width = iconSize - 2.0*padding;
- let height = Math.floor(Math.min(18.0*scaleFactor, 0.20*iconSize));
- x += padding;
- y += iconSize - height - padding;
-
- cr.setLineWidth(lineWidth);
-
- // Draw the outer stroke
- let stroke = new Cairo.LinearGradient(0, y, 0, y + height);
- let fill = null;
- stroke.addColorStopRGBA(0.5, 0.5, 0.5, 0.5, 0.1);
- stroke.addColorStopRGBA(0.9, 0.8, 0.8, 0.8, 0.4);
- Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, width, height, true, true, stroke, fill);
-
- // Draw the background
- x += lineWidth;
- y += lineWidth;
- width -= 2.0*lineWidth;
- height -= 2.0*lineWidth;
-
- stroke = Cairo.SolidPattern.createRGBA(0.20, 0.20, 0.20, 0.9);
- fill = new Cairo.LinearGradient(0, y, 0, y + height);
- fill.addColorStopRGBA(0.4, 0.25, 0.25, 0.25, 1.0);
- fill.addColorStopRGBA(0.9, 0.35, 0.35, 0.35, 1.0);
- Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, width, height, true, true, stroke, fill);
-
- // Draw the finished bar
- x += lineWidth;
- y += lineWidth;
- width -= 2.0*lineWidth;
- height -= 2.0*lineWidth;
-
- let finishedWidth = Math.ceil(this._progress * width);
-
- let bg = this._progressbar_background;
- let bd = this._progressbar_border;
-
- stroke = Cairo.SolidPattern.createRGBA(bd.red/255, bd.green/255, bd.blue/255, bd.alpha/255);
- fill = Cairo.SolidPattern.createRGBA(bg.red/255, bg.green/255, bg.blue/255, bg.alpha/255);
-
- if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
- Utils.drawRoundedLine(cr, x + lineWidth/2.0 + width - finishedWidth, y + lineWidth/2.0, finishedWidth, height, true, true, stroke, fill);
- else
- Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, finishedWidth, height, true, true, stroke, fill);
-
- cr.$dispose();
- }
-
- setProgress(progress) {
- this._progress = Math.min(Math.max(progress, 0.0), 1.0);
- this._updateProgressOverlay();
- }
-
- toggleProgressOverlay(activate) {
- if (activate) {
- this._showProgressOverlay();
- }
- else {
- this._hideProgressOverlay();
- }
- }
-
- insertEntry(appProgress) {
- if (!appProgress || this._progressManagerEntries.indexOf(appProgress) !== -1)
- return;
-
- this._progressManagerEntries.push(appProgress);
- this._selectEntry(appProgress);
- }
-
- removeEntry(appProgress) {
- if (!appProgress || this._progressManagerEntries.indexOf(appProgress) == -1)
- return;
-
- this._progressManagerEntries.splice(this._progressManagerEntries.indexOf(appProgress), 1);
-
- if (this._progressManagerEntries.length > 0) {
- this._selectEntry(this._progressManagerEntries[this._progressManagerEntries.length-1]);
- } else {
- this.setNotificationBadge(0);
- this.toggleNotificationBadge(false);
- this.setProgress(0);
- this.toggleProgressOverlay(false);
- this.setUrgent(false);
- }
- }
-
- _selectEntry(appProgress) {
- if (!appProgress)
- return;
-
- this._signalsHandler.removeWithLabel('progress-entry');
-
- this._signalsHandler.addWithLabel('progress-entry',
- [
- appProgress,
- 'count-changed',
- (appProgress, value) => {
- this.setNotificationBadge(value);
- }
- ], [
- appProgress,
- 'count-visible-changed',
- (appProgress, value) => {
- this.toggleNotificationBadge(value);
- }
- ], [
- appProgress,
- 'progress-changed',
- (appProgress, value) => {
- this.setProgress(value);
- }
- ], [
- appProgress,
- 'progress-visible-changed',
- (appProgress, value) => {
- this.toggleProgressOverlay(value);
- }
- ], [
- appProgress,
- 'urgent-changed',
- (appProgress, value) => {
- this.setUrgent(value)
- }
- ]);
-
- this.setNotificationBadge(appProgress.count());
- this.toggleNotificationBadge(appProgress.countVisible());
- this.setProgress(appProgress.progress());
- this.toggleProgressOverlay(appProgress.progressVisible());
-
- this._isUrgent = false;
- }
-
- setUrgent(urgent) {
- const icon = this._source.icon._iconBin;
- if (urgent) {
- if (!this._isUrgent) {
- icon.set_pivot_point(0.5, 0.5);
- this._source.iconAnimator.addAnimation(icon, 'dance');
- this._isUrgent = true;
- }
- } else {
- if (this._isUrgent) {
- this._source.iconAnimator.removeAnimation(icon, 'dance');
- this._isUrgent = false;
- }
- icon.rotation_angle_z = 0;
- }
- }
-};
+ }
+}
diff --git a/proximity.js b/proximity.js
index eff1548..91d8232 100644
--- a/proximity.js
+++ b/proximity.js
@@ -15,242 +15,267 @@
* along with this program. If not, see .
*/
-import Meta from 'gi://Meta';
-import Mtk from 'gi://Mtk';
+import Meta from 'gi://Meta'
+import Mtk from 'gi://Mtk'
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+import * as Main from 'resource:///org/gnome/shell/ui/main.js'
-import * as Utils from './utils.js';
+import * as Utils from './utils.js'
//timeout intervals
-const MIN_UPDATE_MS = 200;
+const MIN_UPDATE_MS = 200
//timeout names
-const T1 = 'limitUpdateTimeout';
+const T1 = 'limitUpdateTimeout'
export const Mode = {
- ALL_WINDOWS: 0,
- FOCUSED_WINDOWS: 1,
- MAXIMIZED_WINDOWS: 2
-};
+ ALL_WINDOWS: 0,
+ FOCUSED_WINDOWS: 1,
+ MAXIMIZED_WINDOWS: 2,
+}
export class ProximityWatch {
+ constructor(actor, monitorIndex, mode, xThreshold, yThreshold, handler) {
+ this.actor = actor
+ this.monitorIndex = monitorIndex
+ this.overlap = false
+ this.mode = mode
+ this.threshold = [xThreshold, yThreshold]
+ this.handler = handler
- constructor(actor, monitorIndex, mode, xThreshold, yThreshold, handler) {
- this.actor = actor;
- this.monitorIndex = monitorIndex
- this.overlap = false;
- this.mode = mode;
- this.threshold = [xThreshold, yThreshold];
- this.handler = handler;
+ this._allocationChangedId = actor.connect('notify::allocation', () =>
+ this._updateWatchRect(),
+ )
- this._allocationChangedId = actor.connect('notify::allocation', () => this._updateWatchRect());
+ this._updateWatchRect()
+ }
- this._updateWatchRect();
- }
+ destroy() {
+ this.actor.disconnect(this._allocationChangedId)
+ }
- destroy() {
- this.actor.disconnect(this._allocationChangedId);
- }
+ _updateWatchRect() {
+ let [actorX, actorY] = this.actor.get_position()
- _updateWatchRect() {
- let [actorX, actorY] = this.actor.get_position();
-
- this.rect = new Mtk.Rectangle({
- x: actorX - this.threshold[0],
- y: actorY - this.threshold[1],
- width: this.actor.width + this.threshold[0] * 2,
- height: this.actor.height + this.threshold[1] * 2
- });
- }
-};
+ this.rect = new Mtk.Rectangle({
+ x: actorX - this.threshold[0],
+ y: actorY - this.threshold[1],
+ width: this.actor.width + this.threshold[0] * 2,
+ height: this.actor.height + this.threshold[1] * 2,
+ })
+ }
+}
export const ProximityManager = class {
+ constructor() {
+ this._counter = 1
+ this._watches = {}
+ this._focusedWindowInfo = null
- constructor() {
- this._counter = 1;
- this._watches = {};
- this._focusedWindowInfo = null;
+ this._signalsHandler = new Utils.GlobalSignalsHandler()
+ this._timeoutsHandler = new Utils.TimeoutsHandler()
- this._signalsHandler = new Utils.GlobalSignalsHandler();
- this._timeoutsHandler = new Utils.TimeoutsHandler();
+ this._bindSignals()
+ this._setFocusedWindow()
+ }
- this._bindSignals();
- this._setFocusedWindow();
+ createWatch(actor, monitorIndex, mode, xThreshold, yThreshold, handler) {
+ let watch = new ProximityWatch(
+ actor,
+ monitorIndex,
+ mode,
+ xThreshold,
+ yThreshold,
+ handler,
+ )
+
+ this._watches[this._counter] = watch
+ this.update()
+
+ return this._counter++
+ }
+
+ removeWatch(id) {
+ if (this._watches[id]) {
+ this._watches[id].destroy()
+ delete this._watches[id]
}
+ }
- createWatch(actor, monitorIndex, mode, xThreshold, yThreshold, handler) {
- let watch = new ProximityWatch(actor, monitorIndex, mode, xThreshold, yThreshold, handler);
+ update() {
+ this._queueUpdate(true)
+ }
- this._watches[this._counter] = watch;
- this.update();
-
- return this._counter++;
+ destroy() {
+ this._signalsHandler.destroy()
+ this._timeoutsHandler.destroy()
+ this._disconnectFocusedWindow()
+ Object.keys(this._watches).forEach((id) => this.removeWatch(id))
+ }
+
+ _bindSignals() {
+ this._signalsHandler.add(
+ [global.window_manager, 'switch-workspace', () => this._queueUpdate()],
+ [Main.overview, 'hidden', () => this._queueUpdate()],
+ [
+ global.display,
+ 'notify::focus-window',
+ () => {
+ this._setFocusedWindow()
+ this._queueUpdate()
+ },
+ ],
+ [global.display, 'restacked', () => this._queueUpdate()],
+ )
+ }
+
+ _setFocusedWindow() {
+ this._disconnectFocusedWindow()
+
+ let focusedWindow = global.display.focus_window
+
+ if (focusedWindow) {
+ let focusedWindowInfo = this._getFocusedWindowInfo(focusedWindow)
+
+ if (
+ focusedWindowInfo &&
+ this._checkIfHandledWindowType(focusedWindowInfo.metaWindow)
+ ) {
+ focusedWindowInfo.allocationId = focusedWindowInfo.window.connect(
+ 'notify::allocation',
+ () => this._queueUpdate(),
+ )
+ focusedWindowInfo.destroyId = focusedWindowInfo.window.connect(
+ 'destroy',
+ () => this._disconnectFocusedWindow(true),
+ )
+
+ this._focusedWindowInfo = focusedWindowInfo
+ }
}
+ }
- removeWatch(id) {
- if (this._watches[id]) {
- this._watches[id].destroy();
- delete this._watches[id];
+ _getFocusedWindowInfo(focusedWindow) {
+ let window = focusedWindow.get_compositor_private()
+ let focusedWindowInfo
+
+ if (window) {
+ focusedWindowInfo = { window: window }
+ focusedWindowInfo.metaWindow = focusedWindow
+
+ if (focusedWindow.is_attached_dialog()) {
+ let mainMetaWindow = focusedWindow.get_transient_for()
+
+ if (
+ focusedWindowInfo.metaWindow.get_frame_rect().height <
+ mainMetaWindow.get_frame_rect().height
+ ) {
+ focusedWindowInfo.window = mainMetaWindow.get_compositor_private()
+ focusedWindowInfo.metaWindow = mainMetaWindow
}
+ }
}
- update() {
- this._queueUpdate(true);
+ return focusedWindowInfo
+ }
+
+ _disconnectFocusedWindow(destroy) {
+ if (this._focusedWindowInfo && !destroy) {
+ this._focusedWindowInfo.window.disconnect(
+ this._focusedWindowInfo.allocationId,
+ )
+ this._focusedWindowInfo.window.disconnect(
+ this._focusedWindowInfo.destroyId,
+ )
}
- destroy() {
- this._signalsHandler.destroy();
- this._timeoutsHandler.destroy();
- this._disconnectFocusedWindow();
- Object.keys(this._watches).forEach(id => this.removeWatch(id));
+ this._focusedWindowInfo = null
+ }
+
+ _getHandledWindows() {
+ return Utils.getCurrentWorkspace()
+ .list_windows()
+ .filter((mw) => this._checkIfHandledWindow(mw))
+ }
+
+ _checkIfHandledWindow(metaWindow) {
+ return (
+ metaWindow &&
+ !metaWindow.minimized &&
+ !metaWindow.customJS_ding &&
+ this._checkIfHandledWindowType(metaWindow)
+ )
+ }
+
+ _checkIfHandledWindowType(metaWindow) {
+ let metaWindowType = metaWindow.get_window_type()
+
+ //https://www.roojs.org/seed/gir-1.2-gtk-3.0/seed/Meta.WindowType.html
+ return (
+ metaWindowType <= Meta.WindowType.SPLASHSCREEN &&
+ metaWindowType != Meta.WindowType.DESKTOP
+ )
+ }
+
+ _queueUpdate(noDelay) {
+ if (!noDelay && this._timeoutsHandler.getId(T1)) {
+ //limit the number of updates
+ this._pendingUpdate = true
+ return
}
- _bindSignals() {
- this._signalsHandler.add(
- [
- global.window_manager,
- 'switch-workspace',
- () => this._queueUpdate()
- ],
- [
- Main.overview,
- 'hidden',
- () => this._queueUpdate()
- ],
- [
- global.display,
- 'notify::focus-window',
- () => {
- this._setFocusedWindow();
- this._queueUpdate();
- }
- ],
- [
- global.display,
- 'restacked',
- () => this._queueUpdate()
- ]
- );
+ this._timeoutsHandler.add([T1, MIN_UPDATE_MS, () => this._endLimitUpdate()])
+
+ let metaWindows = this._getHandledWindows()
+
+ Object.keys(this._watches).forEach((id) => {
+ let watch = this._watches[id]
+ let overlap = !!this._update(watch, metaWindows)
+
+ if (overlap !== watch.overlap) {
+ watch.handler(overlap)
+ watch.overlap = overlap
+ }
+ })
+ }
+
+ _endLimitUpdate() {
+ if (this._pendingUpdate) {
+ this._pendingUpdate = false
+ this._queueUpdate()
}
+ }
- _setFocusedWindow() {
- this._disconnectFocusedWindow();
+ _update(watch, metaWindows) {
+ if (watch.mode === Mode.FOCUSED_WINDOWS)
+ return (
+ this._focusedWindowInfo &&
+ this._checkIfHandledWindow(this._focusedWindowInfo.metaWindow) &&
+ this._checkProximity(this._focusedWindowInfo.metaWindow, watch)
+ )
- let focusedWindow = global.display.focus_window;
+ if (watch.mode === Mode.MAXIMIZED_WINDOWS)
+ return metaWindows.some(
+ (mw) =>
+ mw.maximized_vertically &&
+ mw.maximized_horizontally &&
+ mw.get_monitor() == watch.monitorIndex,
+ )
- if (focusedWindow) {
- let focusedWindowInfo = this._getFocusedWindowInfo(focusedWindow);
+ //Mode.ALL_WINDOWS
+ return metaWindows.some((mw) => this._checkProximity(mw, watch))
+ }
- if (focusedWindowInfo && this._checkIfHandledWindowType(focusedWindowInfo.metaWindow)) {
- focusedWindowInfo.allocationId = focusedWindowInfo.window.connect('notify::allocation', () => this._queueUpdate());
- focusedWindowInfo.destroyId = focusedWindowInfo.window.connect('destroy', () => this._disconnectFocusedWindow(true));
-
- this._focusedWindowInfo = focusedWindowInfo;
- }
- }
- }
+ _checkProximity(metaWindow, watch) {
+ let windowRect = metaWindow.get_frame_rect()
- _getFocusedWindowInfo(focusedWindow) {
- let window = focusedWindow.get_compositor_private();
- let focusedWindowInfo;
-
- if (window) {
- focusedWindowInfo = { window: window };
- focusedWindowInfo.metaWindow = focusedWindow;
-
- if (focusedWindow.is_attached_dialog()) {
- let mainMetaWindow = focusedWindow.get_transient_for();
-
- if (focusedWindowInfo.metaWindow.get_frame_rect().height < mainMetaWindow.get_frame_rect().height) {
- focusedWindowInfo.window = mainMetaWindow.get_compositor_private();
- focusedWindowInfo.metaWindow = mainMetaWindow;
- }
- }
- }
-
- return focusedWindowInfo;
- }
-
- _disconnectFocusedWindow(destroy) {
- if (this._focusedWindowInfo && !destroy) {
- this._focusedWindowInfo.window.disconnect(this._focusedWindowInfo.allocationId);
- this._focusedWindowInfo.window.disconnect(this._focusedWindowInfo.destroyId);
- }
-
- this._focusedWindowInfo = null;
- }
-
- _getHandledWindows() {
- return Utils.getCurrentWorkspace()
- .list_windows()
- .filter(mw => this._checkIfHandledWindow(mw));
- }
-
- _checkIfHandledWindow(metaWindow) {
- return metaWindow &&
- !metaWindow.minimized &&
- !metaWindow.customJS_ding &&
- this._checkIfHandledWindowType(metaWindow);
- }
-
- _checkIfHandledWindowType(metaWindow) {
- let metaWindowType = metaWindow.get_window_type();
-
- //https://www.roojs.org/seed/gir-1.2-gtk-3.0/seed/Meta.WindowType.html
- return metaWindowType <= Meta.WindowType.SPLASHSCREEN &&
- metaWindowType != Meta.WindowType.DESKTOP;
- }
-
- _queueUpdate(noDelay) {
- if (!noDelay && this._timeoutsHandler.getId(T1)) {
- //limit the number of updates
- this._pendingUpdate = true;
- return;
- }
-
- this._timeoutsHandler.add([T1, MIN_UPDATE_MS, () => this._endLimitUpdate()]);
-
- let metaWindows = this._getHandledWindows();
-
- Object.keys(this._watches).forEach(id => {
- let watch = this._watches[id];
- let overlap = !!this._update(watch, metaWindows);
-
- if (overlap !== watch.overlap) {
- watch.handler(overlap);
- watch.overlap = overlap;
- }
- });
- }
-
- _endLimitUpdate() {
- if (this._pendingUpdate) {
- this._pendingUpdate = false;
- this._queueUpdate();
- }
- }
-
- _update(watch, metaWindows) {
- if (watch.mode === Mode.FOCUSED_WINDOWS)
- return (this._focusedWindowInfo &&
- this._checkIfHandledWindow(this._focusedWindowInfo.metaWindow) &&
- this._checkProximity(this._focusedWindowInfo.metaWindow, watch));
-
- if (watch.mode === Mode.MAXIMIZED_WINDOWS)
- return metaWindows.some(mw => mw.maximized_vertically && mw.maximized_horizontally &&
- mw.get_monitor() == watch.monitorIndex);
-
- //Mode.ALL_WINDOWS
- return metaWindows.some(mw => this._checkProximity(mw, watch));
- }
-
- _checkProximity(metaWindow, watch) {
- let windowRect = metaWindow.get_frame_rect();
-
- return windowRect.overlap(watch.rect) &&
- ((!watch.threshold[0] && !watch.threshold[1]) ||
- metaWindow.get_monitor() == watch.monitorIndex ||
- windowRect.overlap(global.display.get_monitor_geometry(watch.monitorIndex)));
- }
-};
+ return (
+ windowRect.overlap(watch.rect) &&
+ ((!watch.threshold[0] && !watch.threshold[1]) ||
+ metaWindow.get_monitor() == watch.monitorIndex ||
+ windowRect.overlap(
+ global.display.get_monitor_geometry(watch.monitorIndex),
+ ))
+ )
+ }
+}
diff --git a/taskbar.js b/taskbar.js
index 9b63cba..68bae37 100644
--- a/taskbar.js
+++ b/taskbar.js
@@ -21,34 +21,33 @@
* Some code was also adapted from the upstream Gnome Shell source code.
*/
+import Clutter from 'gi://Clutter'
+import Gio from 'gi://Gio'
+import GLib from 'gi://GLib'
+import GObject from 'gi://GObject'
+import Graphene from 'gi://Graphene'
+import Shell from 'gi://Shell'
+import St from 'gi://St'
-import Clutter from 'gi://Clutter';
-import Gio from 'gi://Gio';
-import GLib from 'gi://GLib';
-import GObject from 'gi://GObject';
-import Graphene from 'gi://Graphene';
-import Shell from 'gi://Shell';
-import St from 'gi://St';
+import * as AppFavorites from 'resource:///org/gnome/shell/ui/appFavorites.js'
+import * as Dash from 'resource:///org/gnome/shell/ui/dash.js'
+import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'
+import * as Main from 'resource:///org/gnome/shell/ui/main.js'
+import { EventEmitter } from 'resource:///org/gnome/shell/misc/signals.js'
-import * as AppFavorites from 'resource:///org/gnome/shell/ui/appFavorites.js';
-import * as Dash from 'resource:///org/gnome/shell/ui/dash.js';
-import * as DND from 'resource:///org/gnome/shell/ui/dnd.js';
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
-import {EventEmitter} from 'resource:///org/gnome/shell/misc/signals.js';
+import * as AppIcons from './appIcons.js'
+import * as PanelManager from './panelManager.js'
+import * as PanelSettings from './panelSettings.js'
+import * as Pos from './panelPositions.js'
+import * as Utils from './utils.js'
+import * as WindowPreview from './windowPreview.js'
+import { DTP_EXTENSION, SETTINGS } from './extension.js'
-import * as AppIcons from './appIcons.js';
-import * as PanelManager from './panelManager.js';
-import * as PanelSettings from './panelSettings.js';
-import * as Pos from './panelPositions.js';
-import * as Utils from './utils.js';
-import * as WindowPreview from './windowPreview.js';
-import {DTP_EXTENSION, SETTINGS} from './extension.js';
+const SearchController = Main.overview.searchController
-const SearchController = Main.overview.searchController;
-
-export const DASH_ANIMATION_TIME = .2; // Dash.DASH_ANIMATION_TIME is now private
-const DASH_ITEM_HOVER_TIMEOUT = .3; // Dash.DASH_ITEM_HOVER_TIMEOUT is now private
-export const MIN_ICON_SIZE = 4;
+export const DASH_ANIMATION_TIME = 0.2 // Dash.DASH_ANIMATION_TIME is now private
+const DASH_ITEM_HOVER_TIMEOUT = 0.3 // Dash.DASH_ITEM_HOVER_TIMEOUT is now private
+export const MIN_ICON_SIZE = 4
const T1 = 'ensureAppIconVisibilityTimeout'
const T2 = 'showLabelTimeout'
@@ -56,58 +55,62 @@ const T3 = 'resetHoverTimeout'
const T4 = 'donateAppTimeout'
let donateDummyApp = {
- hideDetails: true,
- app_info: {
- should_show: () => false,
- list_actions: () => ['opts'],
- get_action_name: (action) => action == 'opts' ? _('Donation options') : '',
- },
- connect: () => [],
- connectObject: () => [],
- get_id: () => 'dtp_donate',
- get_windows: () => [],
- can_open_new_window: () => false,
- launch_action: function(action) { action == 'opts' ? this.activate() : null },
- get_name: function() {
- return this.isActive() ? _('Thank you!') : _('Please donate :)')
- },
- create_icon_texture: function(size) {
- let iconParams = {
- icon_name: this.isActive() ? 'face-smile-big-symbolic' : 'emote-love-symbolic',
- icon_size: size
- }
-
- if (SETTINGS.get_string('appicon-style') !== 'SYMBOLIC')
- iconParams.style = `color: ${this.isActive() ? '#FFC730' : '#C71807'}`
-
- return new St.Icon(iconParams)
- },
- activate: function() {
- SETTINGS.set_string('target-prefs-page', 'donation')
-
- if (this.isActive())
- return
-
- DTP_EXTENSION.openPreferences()
- this._taskbar._timeoutsHandler.add([T4, 5000, this.forceRefresh.bind(this)])
- this.forceRefresh()
- },
- forceRefresh: function() {
- setDonateApp.call(this._taskbar)
- this._taskbar._queueRedisplay()
- },
- isActive: function() {
- return !!this._taskbar._timeoutsHandler.getId(T4)
+ hideDetails: true,
+ app_info: {
+ should_show: () => false,
+ list_actions: () => ['opts'],
+ get_action_name: (action) =>
+ action == 'opts' ? _('Donation options') : '',
+ },
+ connect: () => [],
+ connectObject: () => [],
+ get_id: () => 'dtp_donate',
+ get_windows: () => [],
+ can_open_new_window: () => false,
+ launch_action: function (action) {
+ action == 'opts' ? this.activate() : null
+ },
+ get_name: function () {
+ return this.isActive() ? _('Thank you!') : _('Please donate :)')
+ },
+ create_icon_texture: function (size) {
+ let iconParams = {
+ icon_name: this.isActive()
+ ? 'face-smile-big-symbolic'
+ : 'emote-love-symbolic',
+ icon_size: size,
}
+
+ if (SETTINGS.get_string('appicon-style') !== 'SYMBOLIC')
+ iconParams.style = `color: ${this.isActive() ? '#FFC730' : '#C71807'}`
+
+ return new St.Icon(iconParams)
+ },
+ activate: function () {
+ SETTINGS.set_string('target-prefs-page', 'donation')
+
+ if (this.isActive()) return
+
+ DTP_EXTENSION.openPreferences()
+ this._taskbar._timeoutsHandler.add([T4, 5000, this.forceRefresh.bind(this)])
+ this.forceRefresh()
+ },
+ forceRefresh: function () {
+ setDonateApp.call(this._taskbar)
+ this._taskbar._queueRedisplay()
+ },
+ isActive: function () {
+ return !!this._taskbar._timeoutsHandler.getId(T4)
+ },
}
function setDonateApp() {
- delete this._donateApp
+ delete this._donateApp
- if (!SETTINGS.get_string('hide-donate-icon-unixtime')) {
- this._donateApp = Object.create(donateDummyApp)
- this._donateApp._taskbar = this
- }
+ if (!SETTINGS.get_string('hide-donate-icon-unixtime')) {
+ this._donateApp = Object.create(donateDummyApp)
+ this._donateApp._taskbar = this
+ }
}
/**
@@ -120,46 +123,57 @@ function setDonateApp() {
*/
export function extendDashItemContainer(dashItemContainer) {
- dashItemContainer.showLabel = AppIcons.ItemShowLabel;
+ dashItemContainer.showLabel = AppIcons.ItemShowLabel
}
const iconAnimationSettings = {
- _getDictValue(key) {
- let type = SETTINGS.get_string('animate-appicon-hover-animation-type');
- return SETTINGS.get_value(key).deep_unpack()[type] || 0;
- },
+ _getDictValue(key) {
+ let type = SETTINGS.get_string('animate-appicon-hover-animation-type')
+ return SETTINGS.get_value(key).deep_unpack()[type] || 0
+ },
- get type() {
- if (!SETTINGS.get_boolean('animate-appicon-hover'))
- return "";
+ get type() {
+ if (!SETTINGS.get_boolean('animate-appicon-hover')) return ''
- return SETTINGS.get_string('animate-appicon-hover-animation-type');
- },
+ return SETTINGS.get_string('animate-appicon-hover-animation-type')
+ },
- get convexity() {
- return Math.max(0, this._getDictValue('animate-appicon-hover-animation-convexity'));
- },
+ get convexity() {
+ return Math.max(
+ 0,
+ this._getDictValue('animate-appicon-hover-animation-convexity'),
+ )
+ },
- get duration() {
- return this._getDictValue('animate-appicon-hover-animation-duration');
- },
+ get duration() {
+ return this._getDictValue('animate-appicon-hover-animation-duration')
+ },
- get extent() {
- return Math.max(1, this._getDictValue('animate-appicon-hover-animation-extent'));
- },
+ get extent() {
+ return Math.max(
+ 1,
+ this._getDictValue('animate-appicon-hover-animation-extent'),
+ )
+ },
- get rotation() {
- return this._getDictValue('animate-appicon-hover-animation-rotation');
- },
+ get rotation() {
+ return this._getDictValue('animate-appicon-hover-animation-rotation')
+ },
- get travel() {
- return Math.max(-1, this._getDictValue('animate-appicon-hover-animation-travel'));
- },
+ get travel() {
+ return Math.max(
+ -1,
+ this._getDictValue('animate-appicon-hover-animation-travel'),
+ )
+ },
- get zoom() {
- return Math.max(0.5, this._getDictValue('animate-appicon-hover-animation-zoom'));
- },
-};
+ get zoom() {
+ return Math.max(
+ 0.5,
+ this._getDictValue('animate-appicon-hover-animation-zoom'),
+ )
+ },
+}
/* This class is a fork of the upstream DashActor class (ui.dash.js)
*
@@ -167,72 +181,98 @@ const iconAnimationSettings = {
* - modified chldBox calculations for when 'show-apps-at-top' option is checked
* - handle horizontal dash
*/
-export const TaskbarActor = GObject.registerClass({
-}, class TaskbarActor extends St.Widget {
+export const TaskbarActor = GObject.registerClass(
+ {},
+ class TaskbarActor extends St.Widget {
_init(delegate) {
- this._delegate = delegate;
- this._currentBackgroundColor = 0;
- super._init({ name: 'dashtopanelTaskbar',
- layout_manager: new Clutter.BoxLayout({ orientation: Clutter.Orientation[delegate.dtpPanel.getOrientation().toUpperCase()] }),
- clip_to_allocation: true });
+ this._delegate = delegate
+ this._currentBackgroundColor = 0
+ super._init({
+ name: 'dashtopanelTaskbar',
+ layout_manager: new Clutter.BoxLayout({
+ orientation:
+ Clutter.Orientation[
+ delegate.dtpPanel.getOrientation().toUpperCase()
+ ],
+ }),
+ clip_to_allocation: true,
+ })
}
vfunc_allocate(box) {
- this.set_allocation(box);
+ this.set_allocation(box)
- let panel = this._delegate.dtpPanel;
- let availFixedSize = box[panel.fixedCoord.c2] - box[panel.fixedCoord.c1];
- let availVarSize = box[panel.varCoord.c2] - box[panel.varCoord.c1];
- let [dummy, scrollview, leftFade, rightFade] = this.get_children();
- let [, natSize] = this[panel.sizeFunc](availFixedSize);
- let childBox = new Clutter.ActorBox();
- let orientation = panel.getOrientation();
+ let panel = this._delegate.dtpPanel
+ let availFixedSize = box[panel.fixedCoord.c2] - box[panel.fixedCoord.c1]
+ let availVarSize = box[panel.varCoord.c2] - box[panel.varCoord.c1]
+ let [dummy, scrollview, leftFade, rightFade] = this.get_children()
+ let [, natSize] = this[panel.sizeFunc](availFixedSize)
+ let childBox = new Clutter.ActorBox()
+ let orientation = panel.getOrientation()
- dummy.allocate(childBox);
+ dummy.allocate(childBox)
- childBox[panel.varCoord.c1] = box[panel.varCoord.c1];
- childBox[panel.varCoord.c2] = Math.min(availVarSize, natSize);
- childBox[panel.fixedCoord.c1] = box[panel.fixedCoord.c1];
- childBox[panel.fixedCoord.c2] = box[panel.fixedCoord.c2];
+ childBox[panel.varCoord.c1] = box[panel.varCoord.c1]
+ childBox[panel.varCoord.c2] = Math.min(availVarSize, natSize)
+ childBox[panel.fixedCoord.c1] = box[panel.fixedCoord.c1]
+ childBox[panel.fixedCoord.c2] = box[panel.fixedCoord.c2]
- scrollview.allocate(childBox);
+ scrollview.allocate(childBox)
- let [value, , upper, , , pageSize] = scrollview[orientation[0] + 'adjustment'].get_values();
- upper = Math.floor(upper);
- scrollview._dtpFadeSize = upper > pageSize ? this._delegate.iconSize : 0;
+ let [value, , upper, , , pageSize] =
+ scrollview[orientation[0] + 'adjustment'].get_values()
+ upper = Math.floor(upper)
+ scrollview._dtpFadeSize = upper > pageSize ? this._delegate.iconSize : 0
- if (this._currentBackgroundColor !== panel.dynamicTransparency.currentBackgroundColor) {
- this._currentBackgroundColor = panel.dynamicTransparency.currentBackgroundColor;
- let gradientStyle = 'background-gradient-start: ' + this._currentBackgroundColor +
- 'background-gradient-direction: ' + orientation;
+ if (
+ this._currentBackgroundColor !==
+ panel.dynamicTransparency.currentBackgroundColor
+ ) {
+ this._currentBackgroundColor =
+ panel.dynamicTransparency.currentBackgroundColor
+ let gradientStyle =
+ 'background-gradient-start: ' +
+ this._currentBackgroundColor +
+ 'background-gradient-direction: ' +
+ orientation
- leftFade.set_style(gradientStyle);
- rightFade.set_style(gradientStyle);
- }
+ leftFade.set_style(gradientStyle)
+ rightFade.set_style(gradientStyle)
+ }
- childBox[panel.varCoord.c2] = childBox[panel.varCoord.c1] + (value > 0 ? scrollview._dtpFadeSize : 0);
- leftFade.allocate(childBox);
+ childBox[panel.varCoord.c2] =
+ childBox[panel.varCoord.c1] + (value > 0 ? scrollview._dtpFadeSize : 0)
+ leftFade.allocate(childBox)
- childBox[panel.varCoord.c1] = box[panel.varCoord.c2] - (value + pageSize < upper ? scrollview._dtpFadeSize : 0);
- childBox[panel.varCoord.c2] = box[panel.varCoord.c2];
- rightFade.allocate(childBox);
+ childBox[panel.varCoord.c1] =
+ box[panel.varCoord.c2] -
+ (value + pageSize < upper ? scrollview._dtpFadeSize : 0)
+ childBox[panel.varCoord.c2] = box[panel.varCoord.c2]
+ rightFade.allocate(childBox)
}
// We want to request the natural size of all our children
// as our natural width, so we chain up to StWidget (which
// then calls BoxLayout)
vfunc_get_preferred_width(forHeight) {
- let [, natWidth] = St.Widget.prototype.vfunc_get_preferred_width.call(this, forHeight);
+ let [, natWidth] = St.Widget.prototype.vfunc_get_preferred_width.call(
+ this,
+ forHeight,
+ )
- return [0, natWidth];
+ return [0, natWidth]
}
vfunc_get_preferred_height(forWidth) {
- let [, natHeight] = St.Widget.prototype.vfunc_get_preferred_height.call(this, forWidth);
+ let [, natHeight] = St.Widget.prototype.vfunc_get_preferred_height.call(
+ this,
+ forWidth,
+ )
- return [0, natHeight];
+ return [0, natHeight]
}
-});
+ },
+)
/* This class is a fork of the upstream dash class (ui.dash.js)
*
@@ -249,1380 +289,1582 @@ export const TaskbarActor = GObject.registerClass({
*/
export const Taskbar = class extends EventEmitter {
+ constructor(panel) {
+ super()
- constructor(panel) {
- super();
+ this.dtpPanel = panel
- this.dtpPanel = panel;
+ // start at smallest size due to running indicator drawing area expanding but not shrinking
+ this.iconSize = 16
- // start at smallest size due to running indicator drawing area expanding but not shrinking
- this.iconSize = 16;
+ this._shownInitially = false
- this._shownInitially = false;
+ this._signalsHandler = new Utils.GlobalSignalsHandler()
+ this._timeoutsHandler = new Utils.TimeoutsHandler()
- this._signalsHandler = new Utils.GlobalSignalsHandler();
- this._timeoutsHandler = new Utils.TimeoutsHandler();
+ this._labelShowing = false
+ this.fullScrollView = 0
- this._labelShowing = false;
- this.fullScrollView = 0;
+ let isVertical = panel.checkIfVertical()
- let isVertical = panel.checkIfVertical();
+ this._box = new St.BoxLayout({
+ vertical: isVertical,
+ clip_to_allocation: false,
+ x_align: Clutter.ActorAlign.START,
+ y_align: Clutter.ActorAlign.START,
+ })
- this._box = new St.BoxLayout({ vertical: isVertical,
- clip_to_allocation: false,
- x_align: Clutter.ActorAlign.START,
- y_align: Clutter.ActorAlign.START });
+ this._container = new TaskbarActor(this)
+ this._scrollView = new St.ScrollView({
+ name: 'dashtopanelScrollview',
+ hscrollbar_policy: St.PolicyType.NEVER,
+ vscrollbar_policy: St.PolicyType.NEVER,
+ enable_mouse_scrolling: true,
+ })
- this._container = new TaskbarActor(this);
- this._scrollView = new St.ScrollView({ name: 'dashtopanelScrollview',
- hscrollbar_policy: St.PolicyType.NEVER,
- vscrollbar_policy: St.PolicyType.NEVER,
- enable_mouse_scrolling: true });
+ this._scrollView.connect('leave-event', this._onLeaveEvent.bind(this))
+ this._scrollView.connect('motion-event', this._onMotionEvent.bind(this))
+ this._scrollView.connect('scroll-event', this._onScrollEvent.bind(this))
+ this._scrollView.add_child(this._box)
- this._scrollView.connect('leave-event', this._onLeaveEvent.bind(this));
- this._scrollView.connect('motion-event', this._onMotionEvent.bind(this));
- this._scrollView.connect('scroll-event', this._onScrollEvent.bind(this));
- this._scrollView.add_child(this._box);
+ this._showAppsIconWrapper = panel.showAppsIconWrapper
+ this._showAppsIconWrapper.connect(
+ 'menu-state-changed',
+ (showAppsIconWrapper, opened) => {
+ this._itemMenuStateChanged(showAppsIconWrapper, opened)
+ },
+ )
+ // an instance of the showAppsIcon class is encapsulated in the wrapper
+ this._showAppsIcon = this._showAppsIconWrapper.realShowAppsIcon
+ this.showAppsButton = this._showAppsIcon.toggleButton
- this._showAppsIconWrapper = panel.showAppsIconWrapper;
- this._showAppsIconWrapper.connect('menu-state-changed', (showAppsIconWrapper, opened) => {
- this._itemMenuStateChanged(showAppsIconWrapper, opened);
- });
- // an instance of the showAppsIcon class is encapsulated in the wrapper
- this._showAppsIcon = this._showAppsIconWrapper.realShowAppsIcon;
- this.showAppsButton = this._showAppsIcon.toggleButton;
+ if (isVertical) {
+ this.showAppsButton.set_width(panel.geom.w)
+ }
- if (isVertical) {
- this.showAppsButton.set_width(panel.geom.w);
- }
+ this.showAppsButton.connect(
+ 'notify::checked',
+ this._onShowAppsButtonToggled.bind(this),
+ )
- this.showAppsButton.connect('notify::checked', this._onShowAppsButtonToggled.bind(this));
+ this.showAppsButton.checked = SearchController._showAppsButton
+ ? SearchController._showAppsButton.checked
+ : false
- this.showAppsButton.checked = (SearchController._showAppsButton) ? SearchController._showAppsButton.checked : false;
+ this._showAppsIcon.childScale = 1
+ this._showAppsIcon.childOpacity = 255
+ this._showAppsIcon.icon.setIconSize(this.iconSize)
+ this._hookUpLabel(this._showAppsIcon, this._showAppsIconWrapper)
- this._showAppsIcon.childScale = 1;
- this._showAppsIcon.childOpacity = 255;
- this._showAppsIcon.icon.setIconSize(this.iconSize);
- this._hookUpLabel(this._showAppsIcon, this._showAppsIconWrapper);
+ this._container.add_child(new St.Widget({ width: 0, reactive: false }))
+ this._container.add_child(this._scrollView)
- this._container.add_child(new St.Widget({ width: 0, reactive: false }));
- this._container.add_child(this._scrollView);
+ let orientation = panel.getOrientation()
+ let fadeStyle = 'background-gradient-direction:' + orientation
+ let fade1 = new St.Widget({
+ style_class: 'scrollview-fade',
+ reactive: false,
+ })
+ let fade2 = new St.Widget({
+ style_class: 'scrollview-fade',
+ reactive: false,
+ pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
+ rotation_angle_z: 180,
+ })
- let orientation = panel.getOrientation();
- let fadeStyle = 'background-gradient-direction:' + orientation;
- let fade1 = new St.Widget({ style_class: 'scrollview-fade', reactive: false });
- let fade2 = new St.Widget({ style_class: 'scrollview-fade',
- reactive: false,
- pivot_point: new Graphene.Point({ x: .5, y: .5 }),
- rotation_angle_z: 180 });
+ fade1.set_style(fadeStyle)
+ fade2.set_style(fadeStyle)
- fade1.set_style(fadeStyle);
- fade2.set_style(fadeStyle);
+ this._container.add_child(fade1)
+ this._container.add_child(fade2)
- this._container.add_child(fade1);
- this._container.add_child(fade2);
+ this.previewMenu = new WindowPreview.PreviewMenu(panel)
+ this.previewMenu.enable()
- this.previewMenu = new WindowPreview.PreviewMenu(panel);
- this.previewMenu.enable();
+ let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL
+ this.actor = new St.Bin({
+ child: this._container,
+ y_align: Clutter.ActorAlign.START,
+ x_align: rtl ? Clutter.ActorAlign.END : Clutter.ActorAlign.START,
+ })
- let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
- this.actor = new St.Bin({
- child: this._container,
- y_align: Clutter.ActorAlign.START,
- x_align: rtl ? Clutter.ActorAlign.END : Clutter.ActorAlign.START
- });
+ const adjustment = this._scrollView[orientation[0] + 'adjustment']
- const adjustment = this._scrollView[orientation[0] + 'adjustment'];
+ this._workId = Main.initializeDeferredWork(
+ this._box,
+ this._redisplay.bind(this),
+ )
- this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this));
+ this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' })
- this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
+ this._appSystem = Shell.AppSystem.get_default()
- this._appSystem = Shell.AppSystem.get_default();
+ this.iconAnimator = new PanelManager.IconAnimator(this.dtpPanel.panel)
- this.iconAnimator = new PanelManager.IconAnimator(this.dtpPanel.panel);
+ this._signalsHandler.add(
+ [this.dtpPanel.panel, 'notify::height', () => this._queueRedisplay()],
+ [this.dtpPanel.panel, 'notify::width', () => this._queueRedisplay()],
+ [
+ this._appSystem,
+ 'installed-changed',
+ () => {
+ AppFavorites.getAppFavorites().reload()
+ this._queueRedisplay()
+ },
+ ],
+ [this._appSystem, 'app-state-changed', this._queueRedisplay.bind(this)],
+ [
+ AppFavorites.getAppFavorites(),
+ 'changed',
+ this._queueRedisplay.bind(this),
+ ],
+ [
+ global.window_manager,
+ 'switch-workspace',
+ () => this._connectWorkspaceSignals(),
+ ],
+ [
+ Utils.DisplayWrapper.getScreen(),
+ ['window-entered-monitor', 'window-left-monitor'],
+ () => {
+ if (SETTINGS.get_boolean('isolate-monitors')) {
+ this._queueRedisplay()
+ }
+ },
+ ],
+ [Main.overview, 'item-drag-begin', this._onDragBegin.bind(this)],
+ [Main.overview, 'item-drag-end', this._onDragEnd.bind(this)],
+ [Main.overview, 'item-drag-cancelled', this._onDragCancelled.bind(this)],
+ [
+ // Ensure the ShowAppsButton status is kept in sync
+ SearchController._showAppsButton,
+ 'notify::checked',
+ this._syncShowAppsButtonToggled.bind(this),
+ ],
+ [
+ SETTINGS,
+ [
+ 'changed::dot-size',
+ 'changed::show-favorites',
+ 'changed::show-running-apps',
+ 'changed::show-favorites-all-monitors',
+ 'changed::hide-donate-icon-unixtime',
+ ],
+ () => {
+ setAttributes()
+ this._redisplay()
+ },
+ ],
+ [
+ SETTINGS,
+ 'changed::group-apps',
+ () => {
+ setAttributes()
+ this._connectWorkspaceSignals()
+ },
+ ],
+ [
+ SETTINGS,
+ [
+ 'changed::appicon-style',
+ 'changed::group-apps-use-launchers',
+ 'changed::taskbar-locked',
+ ],
+ () => {
+ setAttributes()
+ this.resetAppIcons()
+ },
+ ],
+ [
+ adjustment,
+ ['notify::upper', 'notify::pageSize'],
+ () => this._onScrollSizeChange(adjustment),
+ ],
+ )
- this._signalsHandler.add(
- [
- this.dtpPanel.panel,
- 'notify::height',
- () => this._queueRedisplay()
- ],
- [
- this.dtpPanel.panel,
- 'notify::width',
- () => this._queueRedisplay()
- ],
- [
- this._appSystem,
- 'installed-changed',
- () => {
- AppFavorites.getAppFavorites().reload();
- this._queueRedisplay();
- }
- ],
- [
- this._appSystem,
- 'app-state-changed',
- this._queueRedisplay.bind(this)
- ],
- [
- AppFavorites.getAppFavorites(),
- 'changed',
- this._queueRedisplay.bind(this)
- ],
- [
- global.window_manager,
- 'switch-workspace',
- () => this._connectWorkspaceSignals()
- ],
- [
- Utils.DisplayWrapper.getScreen(),
- [
- 'window-entered-monitor',
- 'window-left-monitor'
- ],
- () => {
- if (SETTINGS.get_boolean('isolate-monitors')) {
- this._queueRedisplay();
- }
- }
- ],
- [
- Main.overview,
- 'item-drag-begin',
- this._onDragBegin.bind(this)
- ],
- [
- Main.overview,
- 'item-drag-end',
- this._onDragEnd.bind(this)
- ],
- [
- Main.overview,
- 'item-drag-cancelled',
- this._onDragCancelled.bind(this)
- ],
- [
- // Ensure the ShowAppsButton status is kept in sync
- SearchController._showAppsButton,
- 'notify::checked',
- this._syncShowAppsButtonToggled.bind(this)
- ],
- [
- SETTINGS,
- [
- 'changed::dot-size',
- 'changed::show-favorites',
- 'changed::show-running-apps',
- 'changed::show-favorites-all-monitors',
- 'changed::hide-donate-icon-unixtime'
- ],
- () => {
- setAttributes()
- this._redisplay()
- }
- ],
- [
- SETTINGS,
- 'changed::group-apps',
- () => {
- setAttributes()
- this._connectWorkspaceSignals();
- }
- ],
- [
- SETTINGS,
- [
- 'changed::appicon-style',
- 'changed::group-apps-use-launchers',
- 'changed::taskbar-locked'
- ],
- () => {
- setAttributes()
- this.resetAppIcons()
- }
- ],
- [
- adjustment,
- [
- 'notify::upper',
- 'notify::pageSize'
- ],
- () => this._onScrollSizeChange(adjustment)
+ let setAttributes = () => {
+ this.isGroupApps = SETTINGS.get_boolean('group-apps')
+ this.usingLaunchers =
+ !this.isGroupApps && SETTINGS.get_boolean('group-apps-use-launchers')
+ this.showFavorites =
+ SETTINGS.get_boolean('show-favorites') &&
+ (this.dtpPanel.isPrimary ||
+ SETTINGS.get_boolean('show-favorites-all-monitors'))
+ this.showRunningApps = SETTINGS.get_boolean('show-running-apps')
+ this.allowSplitApps =
+ this.usingLaunchers || (!this.isGroupApps && !this.showFavorites)
+
+ setDonateApp.call(this)
+ }
+
+ setAttributes()
+
+ this._onScrollSizeChange(adjustment)
+ this._connectWorkspaceSignals()
+ }
+
+ destroy() {
+ if (this._waitIdleId) {
+ GLib.source_remove(this._waitIdleId)
+ this._waitIdleId = 0
+ }
+
+ this._timeoutsHandler.destroy()
+ this.iconAnimator.destroy()
+
+ this._signalsHandler.destroy()
+ this._signalsHandler = 0
+
+ this._container.destroy()
+
+ this.previewMenu.disable()
+ this.previewMenu.destroy()
+
+ this._disconnectWorkspaceSignals()
+ }
+
+ _dropIconAnimations() {
+ this._getTaskbarIcons().forEach((item) => {
+ item.raise(0)
+ item.stretch(0)
+ })
+ }
+
+ _updateIconAnimations(pointerX, pointerY) {
+ this._iconAnimationTimestamp = Date.now()
+ let type = iconAnimationSettings.type
+
+ if (!pointerX || !pointerY) [pointerX, pointerY] = global.get_pointer()
+
+ this._getTaskbarIcons().forEach((item) => {
+ let [x, y] = item.get_transformed_position()
+ let [width, height] = item.get_transformed_size()
+ let [centerX, centerY] = [x + width / 2, y + height / 2]
+ let size = this._box.vertical ? height : width
+ let difference = this._box.vertical
+ ? pointerY - centerY
+ : pointerX - centerX
+ let distance = Math.abs(difference)
+ let maxDistance = (iconAnimationSettings.extent / 2) * size
+
+ if (type == 'PLANK') {
+ // Make the position stable for items that are far from the pointer.
+ let translation =
+ distance <= maxDistance
+ ? distance / (2 + (8 * distance) / maxDistance)
+ : // the previous expression with distance = maxDistance
+ maxDistance / 10
+
+ if (difference > 0) translation *= -1
+
+ item.stretch(translation)
+ }
+
+ if (distance <= maxDistance) {
+ let level = (maxDistance - distance) / maxDistance
+ level = Math.pow(level, iconAnimationSettings.convexity)
+ item.raise(level)
+ } else {
+ item.raise(0)
+ }
+ })
+ }
+
+ _onLeaveEvent(actor) {
+ let [stageX, stageY] = global.get_pointer()
+ let [success, x, y] = actor.transform_stage_point(stageX, stageY)
+ if (
+ success &&
+ !actor.allocation.contains(x, y) &&
+ (iconAnimationSettings.type == 'RIPPLE' ||
+ iconAnimationSettings.type == 'PLANK')
+ )
+ this._dropIconAnimations()
+
+ return Clutter.EVENT_PROPAGATE
+ }
+
+ _onMotionEvent(actor_, event) {
+ if (
+ iconAnimationSettings.type == 'RIPPLE' ||
+ iconAnimationSettings.type == 'PLANK'
+ ) {
+ let timestamp = Date.now()
+ if (
+ !this._iconAnimationTimestamp ||
+ timestamp - this._iconAnimationTimestamp >=
+ iconAnimationSettings.duration / 2
+ ) {
+ let [pointerX, pointerY] = event.get_coords()
+ this._updateIconAnimations(pointerX, pointerY)
+ }
+ }
+
+ return Clutter.EVENT_PROPAGATE
+ }
+
+ _onScrollEvent(actor, event) {
+ let orientation = this.dtpPanel.getOrientation()
+
+ // reset timeout to avid conflicts with the mousehover event
+ this._timeoutsHandler.add([T1, 0, () => (this._swiping = false)])
+
+ // Skip to avoid double events mouse
+ if (event.is_pointer_emulated()) return Clutter.EVENT_STOP
+
+ let adjustment, delta
+
+ adjustment = this._scrollView[orientation[0] + 'adjustment']
+
+ let increment = adjustment.step_increment
+
+ switch (event.get_scroll_direction()) {
+ case Clutter.ScrollDirection.UP:
+ case Clutter.ScrollDirection.LEFT:
+ delta = -increment
+ break
+ case Clutter.ScrollDirection.DOWN:
+ case Clutter.ScrollDirection.RIGHT:
+ delta = +increment
+ break
+ case Clutter.ScrollDirection.SMOOTH:
+ let [dx, dy] = event.get_scroll_delta()
+ delta = dy * increment
+ delta += dx * increment
+ break
+ }
+
+ adjustment.set_value(adjustment.get_value() + delta)
+
+ return Clutter.EVENT_STOP
+ }
+
+ _onScrollSizeChange(adjustment) {
+ // Update minimization animation target position on scrollview change.
+ this._updateAppIcons()
+
+ // When applications are ungrouped and there is some empty space on the horizontal taskbar,
+ // force a fixed label width to prevent the icons from "wiggling" when an animation runs
+ // (adding or removing an icon). When the taskbar is full, revert to a dynamic label width
+ // to allow them to resize and make room for new icons.
+ if (!this.dtpPanel.checkIfVertical() && !this.isGroupApps) {
+ let initial = this.fullScrollView
+
+ if (
+ !this.fullScrollView &&
+ Math.floor(adjustment.upper) > adjustment.page_size
+ ) {
+ this.fullScrollView = adjustment.page_size
+ } else if (adjustment.page_size < this.fullScrollView) {
+ this.fullScrollView = 0
+ }
+
+ if (initial != this.fullScrollView && !this._waitIdleId) {
+ this._waitIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
+ this._getAppIcons().forEach((a) => a.updateTitleStyle())
+ this._waitIdleId = 0
+
+ return GLib.SOURCE_REMOVE
+ })
+ }
+ }
+ }
+
+ _onDragBegin() {
+ this._dragCancelled = false
+ this._dragMonitor = {
+ dragMotion: this._onDragMotion.bind(this),
+ }
+ DND.addDragMonitor(this._dragMonitor)
+
+ if (this._box.get_n_children() == 0) {
+ this._emptyDropTarget = new Dash.EmptyDropTargetItem()
+ this._box.insert_child_at_index(this._emptyDropTarget, 0)
+ this._emptyDropTarget.show(true)
+ }
+
+ this._toggleFavoriteHighlight(true)
+ }
+
+ _onDragCancelled() {
+ this._dragCancelled = true
+
+ if (this._dragInfo) {
+ this._box.set_child_at_index(
+ this._dragInfo[1]._dashItemContainer,
+ this._dragInfo[0],
+ )
+ }
+
+ this._endDrag()
+ }
+
+ _onDragEnd() {
+ if (this._dragCancelled) return
+
+ this._endDrag()
+ }
+
+ _endDrag() {
+ if (
+ this._dragInfo &&
+ this._dragInfo[1]._dashItemContainer instanceof DragPlaceholderItem
+ ) {
+ this._box.remove_child(this._dragInfo[1]._dashItemContainer)
+ this._dragInfo[1]._dashItemContainer.destroy()
+ delete this._dragInfo[1]._dashItemContainer
+ }
+
+ this._dragInfo = null
+ this._clearEmptyDropTarget()
+ this._showAppsIcon.setDragApp(null)
+ DND.removeDragMonitor(this._dragMonitor)
+
+ this._dragMonitor = null
+ this.emit('end-drag')
+
+ this._toggleFavoriteHighlight()
+ }
+
+ _onDragMotion(dragEvent) {
+ let app = Dash.Dash.getAppFromSource(dragEvent.source)
+ if (app == null) return DND.DragMotionResult.CONTINUE
+
+ let showAppsHovered = this._showAppsIcon.contains(dragEvent.targetActor)
+
+ if (showAppsHovered) this._showAppsIcon.setDragApp(app)
+ else this._showAppsIcon.setDragApp(null)
+
+ return DND.DragMotionResult.CONTINUE
+ }
+
+ _toggleFavoriteHighlight(show) {
+ let appFavorites = AppFavorites.getAppFavorites()
+ let cssFuncName = (show ? 'add' : 'remove') + '_style_class_name'
+
+ if (this.showFavorites)
+ this._getAppIcons()
+ .filter(
+ (appIcon) =>
+ (this.usingLaunchers && appIcon.isLauncher) ||
+ (!this.usingLaunchers &&
+ appFavorites.isFavorite(appIcon.app.get_id())),
+ )
+ .forEach((fav) => fav._container[cssFuncName]('favorite'))
+ }
+
+ handleIsolatedWorkspaceSwitch() {
+ this._shownInitially = this.isGroupApps
+ this._queueRedisplay()
+ }
+
+ _connectWorkspaceSignals() {
+ this._disconnectWorkspaceSignals()
+
+ this._lastWorkspace =
+ Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace()
+
+ this._workspaceWindowAddedId = this._lastWorkspace.connect(
+ 'window-added',
+ () => this._queueRedisplay(),
+ )
+ this._workspaceWindowRemovedId = this._lastWorkspace.connect(
+ 'window-removed',
+ () => this._queueRedisplay(),
+ )
+ }
+
+ _disconnectWorkspaceSignals() {
+ if (this._lastWorkspace) {
+ this._lastWorkspace.disconnect(this._workspaceWindowAddedId)
+ this._lastWorkspace.disconnect(this._workspaceWindowRemovedId)
+
+ this._lastWorkspace = null
+ }
+ }
+
+ _queueRedisplay() {
+ Main.queueDeferredWork(this._workId)
+ }
+
+ _hookUpLabel(item, syncHandler) {
+ item.child.connect('notify::hover', () => {
+ this._syncLabel(item, syncHandler)
+ })
+
+ syncHandler.connect('sync-tooltip', () => {
+ this._syncLabel(item, syncHandler)
+ })
+ }
+
+ _createAppItem(app, window, isLauncher) {
+ let appIcon = new AppIcons.TaskbarAppIcon(
+ {
+ app,
+ window,
+ isLauncher,
+ },
+ this.dtpPanel,
+ {
+ setSizeManually: true,
+ showLabel: false,
+ isDraggable: !SETTINGS.get_boolean('taskbar-locked'),
+ },
+ this.previewMenu,
+ this.iconAnimator,
+ )
+
+ if (appIcon._draggable) {
+ appIcon._draggable.connect('drag-begin', () => {
+ appIcon.opacity = 0
+ appIcon.isDragged = 1
+ this._dropIconAnimations()
+ })
+ appIcon._draggable.connect('drag-end', () => {
+ appIcon.opacity = 255
+ delete appIcon.isDragged
+ this._updateAppIcons()
+ })
+ }
+
+ appIcon.connect('menu-state-changed', (appIcon, opened) => {
+ this._itemMenuStateChanged(item, opened)
+ })
+
+ let item = new TaskbarItemContainer()
+
+ item._dtpPanel = this.dtpPanel
+ extendDashItemContainer(item)
+
+ item.setChild(appIcon)
+ appIcon._dashItemContainer = item
+
+ appIcon.connect('notify::hover', () => {
+ if (appIcon.hover) {
+ this._timeoutsHandler.add([
+ T1,
+ 100,
+ () =>
+ Utils.ensureActorVisibleInScrollView(
+ this._scrollView,
+ appIcon,
+ this._scrollView._dtpFadeSize,
+ ),
+ ])
+
+ if (!appIcon.isDragged && iconAnimationSettings.type == 'SIMPLE')
+ appIcon.get_parent().raise(1)
+ else if (
+ !appIcon.isDragged &&
+ (iconAnimationSettings.type == 'RIPPLE' ||
+ iconAnimationSettings.type == 'PLANK')
+ )
+ this._updateIconAnimations()
+ } else {
+ this._timeoutsHandler.remove(T1)
+
+ if (!appIcon.isDragged && iconAnimationSettings.type == 'SIMPLE')
+ appIcon.get_parent().raise(0)
+ }
+ })
+
+ appIcon.connect('clicked', (actor) => {
+ Utils.ensureActorVisibleInScrollView(
+ this._scrollView,
+ actor,
+ this._scrollView._dtpFadeSize,
+ )
+ })
+
+ appIcon.connect('key-focus-in', (actor) => {
+ let [x_shift, y_shift] = Utils.ensureActorVisibleInScrollView(
+ this._scrollView,
+ actor,
+ this._scrollView._dtpFadeSize,
+ )
+
+ // This signal is triggered also by mouse click. The popup menu is opened at the original
+ // coordinates. Thus correct for the shift which is going to be applied to the scrollview.
+ if (appIcon._menu) {
+ appIcon._menu._boxPointer.xOffset = -x_shift
+ appIcon._menu._boxPointer.yOffset = -y_shift
+ }
+ })
+
+ // Override default AppIcon label_actor, now the
+ // accessible_name is set at DashItemContainer.setLabelText
+ appIcon.label_actor = null
+ item.setLabelText(app.get_name())
+
+ appIcon.icon.setIconSize(this.iconSize)
+ this._hookUpLabel(item, appIcon)
+
+ return item
+ }
+
+ // Return an array with the "proper" appIcons currently in the taskbar
+ _getAppIcons() {
+ // Only consider children which are "proper" icons and which are not
+ // animating out (which means they will be destroyed at the end of
+ // the animation)
+ return this._getTaskbarIcons().map(function (actor) {
+ return actor.child._delegate
+ })
+ }
+
+ _getTaskbarIcons(includeAnimated) {
+ return this._box.get_children().filter(function (actor) {
+ return (
+ actor.child &&
+ actor.child._delegate &&
+ actor.child._delegate.icon &&
+ (includeAnimated || !actor.animatingOut)
+ )
+ })
+ }
+
+ _updateAppIcons() {
+ let appIcons = this._getAppIcons()
+
+ appIcons
+ .filter((icon) => icon.constructor === AppIcons.TaskbarAppIcon)
+ .forEach((icon) => {
+ icon.updateIcon()
+ })
+ }
+
+ _itemMenuStateChanged(item, opened) {
+ // When the menu closes, it calls sync_hover, which means
+ // that the notify::hover handler does everything we need to.
+ if (opened) {
+ this._timeoutsHandler.remove(T2)
+
+ item.hideLabel()
+ } else {
+ // I want to listen from outside when a menu is closed. I used to
+ // add a custom signal to the appIcon, since gnome 3.8 the signal
+ // calling this callback was added upstream.
+ this.emit('menu-closed')
+
+ // The icon menu grabs the events and, once it is closed, the pointer is maybe
+ // no longer over the taskbar and the animations are not dropped.
+ if (
+ iconAnimationSettings.type == 'RIPPLE' ||
+ iconAnimationSettings.type == 'PLANK'
+ ) {
+ this._scrollView.sync_hover()
+ if (!this._scrollView.hover) this._dropIconAnimations()
+ }
+ }
+ }
+
+ _syncLabel(item, syncHandler) {
+ let shouldShow = syncHandler
+ ? syncHandler.shouldShowTooltip()
+ : item.child.get_hover()
+
+ if (shouldShow) {
+ if (!this._timeoutsHandler.getId(T2)) {
+ let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT
+
+ this._timeoutsHandler.add([
+ T2,
+ timeout,
+ () => {
+ this._labelShowing = true
+ item.showLabel()
+ },
+ ])
+
+ this._timeoutsHandler.remove(T3)
+ }
+ } else {
+ this._timeoutsHandler.remove(T2)
+
+ item.hideLabel()
+ if (this._labelShowing) {
+ this._timeoutsHandler.add([
+ T3,
+ DASH_ITEM_HOVER_TIMEOUT,
+ () => (this._labelShowing = false),
+ ])
+ }
+ }
+ }
+
+ _adjustIconSize() {
+ const thisMonitorIndex = this.dtpPanel.monitor.index
+ let panelSize = PanelSettings.getPanelSize(SETTINGS, thisMonitorIndex)
+ let availSize = panelSize - SETTINGS.get_int('appicon-padding') * 2
+ let minIconSize = MIN_ICON_SIZE + (panelSize % 2)
+
+ if (availSize == this.iconSize) return
+
+ if (availSize < minIconSize) {
+ availSize = minIconSize
+ }
+
+ // For the icon size, we only consider children which are "proper"
+ // icons and which are not animating out (which means they will be
+ // destroyed at the end of the animation)
+ let iconChildren = this._getTaskbarIcons().concat([this._showAppsIcon])
+ let scale = this.iconSize / availSize
+
+ this.iconSize = availSize
+
+ for (let i = 0; i < iconChildren.length; i++) {
+ let icon = iconChildren[i].child._delegate.icon
+
+ // Set the new size immediately, to keep the icons' sizes
+ // in sync with this.iconSize
+ icon.setIconSize(this.iconSize)
+
+ // Don't animate the icon size change when the overview
+ // is transitioning, or when initially filling
+ // the taskbar
+ if (Main.overview.animationInProgress || !this._shownInitially) continue
+
+ let [targetWidth, targetHeight] = icon.icon.get_size()
+
+ // Scale the icon's texture to the previous size and
+ // tween to the new size
+ icon.icon.set_size(icon.icon.width * scale, icon.icon.height * scale)
+
+ Utils.animate(icon.icon, {
+ width: targetWidth,
+ height: targetHeight,
+ time: DASH_ANIMATION_TIME,
+ transition: 'easeOutQuad',
+ })
+ }
+ }
+
+ sortAppsCompareFunction(appA, appB) {
+ return (
+ getAppStableSequence(appA, this.dtpPanel.monitor) -
+ getAppStableSequence(appB, this.dtpPanel.monitor)
+ )
+ }
+
+ getAppInfos() {
+ //get the user's favorite apps
+ let favoriteApps = this.showFavorites
+ ? AppFavorites.getAppFavorites().getFavorites()
+ : []
+
+ //find the apps that should be in the taskbar: the favorites first, then add the running apps
+ // When using isolation, we filter out apps that have no windows in
+ // the current workspace (this check is done in AppIcons.getInterestingWindows)
+ let runningApps = this.showRunningApps
+ ? this._getRunningApps().sort(this.sortAppsCompareFunction.bind(this))
+ : []
+ let appInfos
+
+ if (this.allowSplitApps) {
+ appInfos = this._createAppInfos(favoriteApps, [], true).concat(
+ this._createAppInfos(runningApps).filter(
+ (appInfo) => appInfo.windows.length,
+ ),
+ )
+ } else {
+ appInfos = this._createAppInfos(
+ favoriteApps.concat(
+ runningApps.filter((app) => favoriteApps.indexOf(app) < 0),
+ ),
+ ).filter(
+ (appInfo) =>
+ appInfo.windows.length || favoriteApps.indexOf(appInfo.app) >= 0,
+ )
+ }
+
+ if (this._donateApp)
+ appInfos = [
+ {
+ app: this._donateApp,
+ isLauncher: true,
+ windows: [],
+ },
+ ...appInfos,
+ ]
+
+ return appInfos
+ }
+
+ _redisplay() {
+ if (!this._signalsHandler) {
+ return
+ }
+
+ //get the currently displayed appIcons
+ let currentAppIcons = this._getTaskbarIcons()
+ let expectedAppInfos = this.getAppInfos()
+
+ //remove the appIcons which are not in the expected apps list
+ for (let i = currentAppIcons.length - 1; i > -1; --i) {
+ let appIcon = currentAppIcons[i].child._delegate
+ let appIndex = Utils.findIndex(
+ expectedAppInfos,
+ (appInfo) =>
+ appInfo.app == appIcon.app &&
+ (!this.allowSplitApps ||
+ this.isGroupApps ||
+ appInfo.windows[0] == appIcon.window) &&
+ appInfo.isLauncher == appIcon.isLauncher,
+ )
+
+ if (
+ appIndex < 0 ||
+ (appIcon.window &&
+ (this.isGroupApps ||
+ expectedAppInfos[appIndex].windows.indexOf(appIcon.window) < 0)) ||
+ (!appIcon.window &&
+ !appIcon.isLauncher &&
+ !this.isGroupApps &&
+ expectedAppInfos[appIndex].windows.length)
+ ) {
+ currentAppIcons[i][
+ this._shownInitially ? 'animateOutAndDestroy' : 'destroy'
+ ]()
+ currentAppIcons.splice(i, 1)
+ }
+ }
+
+ //if needed, reorder the existing appIcons and create the missing ones
+ let currentPosition = 0
+ for (let i = 0, l = expectedAppInfos.length; i < l; ++i) {
+ let neededAppIcons =
+ this.isGroupApps || !expectedAppInfos[i].windows.length
+ ? [
+ {
+ app: expectedAppInfos[i].app,
+ window: null,
+ isLauncher: expectedAppInfos[i].isLauncher,
+ },
]
- );
+ : expectedAppInfos[i].windows.map((window) => ({
+ app: expectedAppInfos[i].app,
+ window: window,
+ isLauncher: false,
+ }))
- let setAttributes = () => {
- this.isGroupApps = SETTINGS.get_boolean('group-apps');
- this.usingLaunchers = !this.isGroupApps && SETTINGS.get_boolean('group-apps-use-launchers');
- this.showFavorites = SETTINGS.get_boolean('show-favorites') &&
- (this.dtpPanel.isPrimary || SETTINGS.get_boolean('show-favorites-all-monitors'))
- this.showRunningApps = SETTINGS.get_boolean('show-running-apps')
- this.allowSplitApps = this.usingLaunchers || (!this.isGroupApps && !this.showFavorites)
-
- setDonateApp.call(this)
+ for (let j = 0, ll = neededAppIcons.length; j < ll; ++j) {
+ //check if the icon already exists
+ let matchingAppIconIndex = Utils.findIndex(
+ currentAppIcons,
+ (appIcon) =>
+ appIcon.child._delegate.app == neededAppIcons[j].app &&
+ appIcon.child._delegate.window == neededAppIcons[j].window,
+ )
+
+ if (
+ matchingAppIconIndex > 0 &&
+ matchingAppIconIndex != currentPosition
+ ) {
+ //moved icon, reposition it
+ this._box.remove_child(currentAppIcons[matchingAppIconIndex])
+ this._box.insert_child_at_index(
+ currentAppIcons[matchingAppIconIndex],
+ currentPosition,
+ )
+ } else if (matchingAppIconIndex < 0) {
+ //the icon doesn't exist yet, create a new one
+ let newAppIcon = this._createAppItem(
+ neededAppIcons[j].app,
+ neededAppIcons[j].window,
+ neededAppIcons[j].isLauncher,
+ )
+
+ this._box.insert_child_at_index(newAppIcon, currentPosition)
+ currentAppIcons.splice(currentPosition, 0, newAppIcon)
+
+ // Skip animations on first run when adding the initial set
+ // of items, to avoid all items zooming in at once
+ newAppIcon.show(this._shownInitially)
}
- setAttributes()
-
- this._onScrollSizeChange(adjustment);
- this._connectWorkspaceSignals();
+ ++currentPosition
+ }
}
- destroy() {
- if (this._waitIdleId) {
- GLib.source_remove(this._waitIdleId);
- this._waitIdleId = 0;
- }
+ this._adjustIconSize()
- this._timeoutsHandler.destroy();
- this.iconAnimator.destroy();
+ // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744
+ // Without it, StBoxLayout may use a stale size cache
+ this._box.queue_relayout()
- this._signalsHandler.destroy();
- this._signalsHandler = 0;
+ // This is required for icon reordering when the scrollview is used.
+ this._updateAppIcons()
- this._container.destroy();
-
- this.previewMenu.disable();
- this.previewMenu.destroy();
-
- this._disconnectWorkspaceSignals();
+ // This will update the size, and the corresponding number for each icon on the primary panel
+ if (this.dtpPanel.isPrimary) {
+ this._updateNumberOverlay()
}
- _dropIconAnimations() {
- this._getTaskbarIcons().forEach(item => {
- item.raise(0);
- item.stretch(0);
- });
+ this._shownInitially = true
+ }
+
+ _getRunningApps() {
+ let tracker = Shell.WindowTracker.get_default()
+ let windows = global.get_window_actors()
+ let apps = []
+
+ for (let i = 0, l = windows.length; i < l; ++i) {
+ let app = tracker.get_window_app(windows[i].metaWindow)
+
+ if (app && apps.indexOf(app) < 0) {
+ apps.push(app)
+ }
}
- _updateIconAnimations(pointerX, pointerY) {
- this._iconAnimationTimestamp = Date.now();
- let type = iconAnimationSettings.type;
+ return apps
+ }
- if (!pointerX || !pointerY)
- [pointerX, pointerY] = global.get_pointer();
+ _createAppInfos(apps, defaultWindows, defaultIsLauncher) {
+ if (this.allowSplitApps && !defaultIsLauncher) {
+ let separateApps = []
- this._getTaskbarIcons().forEach(item => {
- let [x, y] = item.get_transformed_position();
- let [width, height] = item.get_transformed_size();
- let [centerX, centerY] = [x + width / 2, y + height / 2];
- let size = this._box.vertical ? height : width;
- let difference = this._box.vertical ? pointerY - centerY : pointerX - centerX;
- let distance = Math.abs(difference);
- let maxDistance = (iconAnimationSettings.extent / 2) * size;
+ if (apps.length) {
+ let tracker = Shell.WindowTracker.get_default()
+ let windows = AppIcons.getInterestingWindows(
+ null,
+ this.dtpPanel.monitor,
+ ).sort(sortWindowsCompareFunction)
- if (type == 'PLANK') {
- // Make the position stable for items that are far from the pointer.
- let translation = distance <= maxDistance ?
- distance / (2 + 8 * distance / maxDistance) :
- // the previous expression with distance = maxDistance
- maxDistance / 10;
+ windows.forEach((w) => {
+ let windowApp = tracker.get_window_app(w)
- if (difference > 0)
- translation *= -1;
+ if (apps.indexOf(windowApp) >= 0)
+ separateApps.push({
+ app: windowApp,
+ isLauncher: false,
+ windows: [w],
+ })
+ })
+ }
- item.stretch(translation);
+ return separateApps
+ }
+
+ return apps.map((app) => ({
+ app: app,
+ isLauncher: defaultIsLauncher || false,
+ windows:
+ defaultWindows ||
+ AppIcons.getInterestingWindows(app, this.dtpPanel.monitor).sort(
+ sortWindowsCompareFunction,
+ ),
+ }))
+ }
+
+ // Reset the displayed apps icon to mantain the correct order
+ resetAppIcons(geometryChange) {
+ let children = this._getTaskbarIcons(true)
+
+ for (let i = 0; i < children.length; i++) {
+ let item = children[i]
+ item.destroy()
+ }
+
+ // to avoid ugly animations, just suppress them like when taskbar is first loaded.
+ this._shownInitially = false
+ this._redisplay()
+
+ if (geometryChange && this.dtpPanel.checkIfVertical()) {
+ this.previewMenu._updateClip()
+ }
+ }
+
+ _updateNumberOverlay() {
+ let seenApps = {}
+ let counter = 0
+
+ this._getAppIcons().forEach((icon) => {
+ if (!seenApps[icon.app] || this.allowSplitApps) {
+ seenApps[icon.app] = 1
+ counter++
+ }
+
+ if (counter <= 10) {
+ icon.setNumberOverlay(counter == 10 ? 0 : counter)
+ } else {
+ // No overlay after 10
+ icon.setNumberOverlay(-1)
+ }
+
+ icon.updateHotkeyNumberOverlay()
+ })
+
+ if (
+ SETTINGS.get_boolean('hot-keys') &&
+ SETTINGS.get_string('hotkeys-overlay-combo') === 'ALWAYS'
+ )
+ this.toggleNumberOverlay(true)
+ }
+
+ toggleNumberOverlay(activate) {
+ let appIcons = this._getAppIcons()
+ appIcons.forEach(function (icon) {
+ icon.toggleNumberOverlay(activate)
+ })
+ }
+
+ _clearEmptyDropTarget() {
+ if (this._emptyDropTarget) {
+ this._emptyDropTarget.animateOutAndDestroy()
+ this._emptyDropTarget = null
+ }
+ }
+
+ handleDragOver(source, actor, x, y, time) {
+ if (source == Main.xdndHandler) return DND.DragMotionResult.CONTINUE
+
+ // Don't allow favoriting of transient apps
+ if (source.app == null || source.app.is_window_backed())
+ return DND.DragMotionResult.NO_DROP
+
+ if (!this._settings.is_writable('favorite-apps'))
+ return DND.DragMotionResult.NO_DROP
+
+ let isVertical = this.dtpPanel.checkIfVertical()
+
+ if (!this._box.contains(source) && !source._dashItemContainer) {
+ //not an appIcon of the taskbar, probably from the applications view
+ source._dashItemContainer = new DragPlaceholderItem(
+ source,
+ this.iconSize,
+ isVertical,
+ )
+ this._box.insert_child_above(source._dashItemContainer, null)
+ }
+
+ let sizeProp = isVertical ? 'height' : 'width'
+ let posProp = isVertical ? 'y' : 'x'
+ let pos = isVertical ? y : x
+
+ let currentAppIcons = this._getAppIcons()
+ let sourceIndex = currentAppIcons.indexOf(source)
+ let hoveredIndex = Utils.findIndex(
+ currentAppIcons,
+ (appIcon) =>
+ pos >= appIcon._dashItemContainer[posProp] &&
+ pos <=
+ appIcon._dashItemContainer[posProp] +
+ appIcon._dashItemContainer[sizeProp],
+ )
+
+ if (!this._dragInfo) {
+ this._dragInfo = [sourceIndex, source]
+ }
+
+ if (hoveredIndex >= 0) {
+ let isLeft =
+ pos <
+ currentAppIcons[hoveredIndex]._dashItemContainer[posProp] +
+ currentAppIcons[hoveredIndex]._dashItemContainer[sizeProp] * 0.5
+ let prevIcon = currentAppIcons[hoveredIndex - 1]
+ let nextIcon = currentAppIcons[hoveredIndex + 1]
+
+ // Don't allow positioning before or after self and between icons of same app if ungrouped and showing favorites
+ if (
+ !(
+ hoveredIndex === sourceIndex ||
+ (isLeft && hoveredIndex - 1 == sourceIndex) ||
+ (!this.allowSplitApps &&
+ isLeft &&
+ hoveredIndex - 1 >= 0 &&
+ source.app != prevIcon.app &&
+ prevIcon.app == currentAppIcons[hoveredIndex].app) ||
+ (!isLeft && hoveredIndex + 1 == sourceIndex) ||
+ (!this.allowSplitApps &&
+ !isLeft &&
+ hoveredIndex + 1 < currentAppIcons.length &&
+ source.app != nextIcon.app &&
+ nextIcon.app == currentAppIcons[hoveredIndex].app)
+ )
+ ) {
+ this._box.set_child_at_index(source._dashItemContainer, hoveredIndex)
+
+ // Ensure the next and previous icon are visible when moving the icon
+ // (I assume there's room for both of them)
+ if (hoveredIndex > 1)
+ Utils.ensureActorVisibleInScrollView(
+ this._scrollView,
+ this._box.get_children()[hoveredIndex - 1],
+ this._scrollView._dtpFadeSize,
+ )
+ if (hoveredIndex < this._box.get_children().length - 1)
+ Utils.ensureActorVisibleInScrollView(
+ this._scrollView,
+ this._box.get_children()[hoveredIndex + 1],
+ this._scrollView._dtpFadeSize,
+ )
+ }
+ }
+
+ return this._dragInfo[0] !== sourceIndex
+ ? DND.DragMotionResult.MOVE_DROP
+ : DND.DragMotionResult.CONTINUE
+ }
+
+ // Draggable target interface
+ acceptDrop(source, actor, x, y, time) {
+ // Don't allow favoriting of transient apps
+ if (
+ !this._dragInfo ||
+ !source.app ||
+ source.app.is_window_backed() ||
+ !this._settings.is_writable('favorite-apps')
+ ) {
+ return false
+ }
+
+ let appIcons = this._getAppIcons()
+ let sourceIndex = appIcons.indexOf(source)
+ let usingLaunchers = !this.isGroupApps && this.usingLaunchers
+
+ // dragging the icon to its original position
+ if (this._dragInfo[0] === sourceIndex) {
+ return true
+ }
+
+ let appFavorites = AppFavorites.getAppFavorites()
+ let sourceAppId = source.app.get_id()
+ let appIsFavorite =
+ this.showFavorites && appFavorites.isFavorite(sourceAppId)
+ let replacingIndex =
+ sourceIndex + (sourceIndex > this._dragInfo[0] ? -1 : 1)
+ let favoriteIndex =
+ replacingIndex >= 0
+ ? appFavorites.getFavorites().indexOf(appIcons[replacingIndex].app)
+ : 0
+ let sameApps = this.allowSplitApps
+ ? []
+ : appIcons.filter((a) => a != source && a.app == source.app)
+ let favoritesCount = 0
+ let position = 0
+ let interestingWindows = {}
+ let getAppWindows = (app) => {
+ if (!interestingWindows[app]) {
+ interestingWindows[app] = AppIcons.getInterestingWindows(
+ app,
+ this.dtpPanel.monitor,
+ )
+ }
+
+ let appWindows = interestingWindows[app] //prevents "reference to undefined property Symbol.toPrimitive" warning
+ return appWindows
+ }
+
+ if (
+ sameApps.length &&
+ (!appIcons[sourceIndex - 1] ||
+ appIcons[sourceIndex - 1].app !== source.app) &&
+ (!appIcons[sourceIndex + 1] ||
+ appIcons[sourceIndex + 1].app !== source.app)
+ ) {
+ appIcons.splice(appIcons.indexOf(sameApps[0]), sameApps.length)
+ Array.prototype.splice.apply(
+ appIcons,
+ [sourceIndex + 1, 0].concat(sameApps),
+ )
+ }
+
+ for (let i = 0, l = appIcons.length; i < l; ++i) {
+ let windows = []
+
+ if (!usingLaunchers || (!source.isLauncher && !appIcons[i].isLauncher)) {
+ windows = appIcons[i].window
+ ? [appIcons[i].window]
+ : getAppWindows(appIcons[i].app)
+ }
+
+ windows.forEach((w) => (w._dtpPosition = position++))
+
+ if (
+ this.showFavorites &&
+ ((usingLaunchers && appIcons[i].isLauncher) ||
+ (!usingLaunchers &&
+ appFavorites.isFavorite(appIcons[i].app.get_id())))
+ ) {
+ ++favoritesCount
+ }
+ }
+
+ if (sourceIndex < favoritesCount) {
+ if (appIsFavorite) {
+ appFavorites.moveFavoriteToPos(sourceAppId, favoriteIndex)
+ } else {
+ appFavorites.addFavoriteAtPos(sourceAppId, favoriteIndex)
+ }
+ } else if (
+ appIsFavorite &&
+ this.showFavorites &&
+ (!usingLaunchers || source.isLauncher)
+ ) {
+ appFavorites.removeFavorite(sourceAppId)
+ }
+
+ appFavorites.emit('changed')
+
+ return true
+ }
+
+ _onShowAppsButtonToggled() {
+ // Sync the status of the default appButtons. Only if the two statuses are
+ // different, that means the user interacted with the extension provided
+ // application button, cutomize the behaviour. Otherwise the shell has changed the
+ // status (due to the _syncShowAppsButtonToggled function below) and it
+ // has already performed the desired action.
+ let selector = SearchController
+
+ if (
+ selector._showAppsButton &&
+ selector._showAppsButton.checked !== this.showAppsButton.checked
+ ) {
+ // find visible view
+
+ if (this.showAppsButton.checked) {
+ if (SETTINGS.get_boolean('show-apps-override-escape')) {
+ //override escape key to return to the desktop when entering the overview using the showapps button
+ SearchController._onStageKeyPress = function (actor, event) {
+ if (
+ Main.modalCount == 1 &&
+ event.get_key_symbol() === Clutter.KEY_Escape
+ ) {
+ this._searchActive ? this.reset() : Main.overview.hide()
+
+ return Clutter.EVENT_STOP
}
- if (distance <= maxDistance) {
- let level = (maxDistance - distance) / maxDistance;
- level = Math.pow(level, iconAnimationSettings.convexity);
- item.raise(level);
- } else {
- item.raise(0);
- }
- });
- }
+ return Object.getPrototypeOf(this)._onStageKeyPress.call(
+ this,
+ actor,
+ event,
+ )
+ }
- _onLeaveEvent(actor) {
- let [stageX, stageY] = global.get_pointer();
- let [success, x, y] = actor.transform_stage_point(stageX, stageY);
- if (success && !actor.allocation.contains(x, y) && (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK'))
- this._dropIconAnimations();
-
- return Clutter.EVENT_PROPAGATE;
- }
-
- _onMotionEvent(actor_, event) {
- if (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK') {
- let timestamp = Date.now();
- if (!this._iconAnimationTimestamp ||
- (timestamp - this._iconAnimationTimestamp >= iconAnimationSettings.duration / 2)) {
- let [pointerX, pointerY] = event.get_coords();
- this._updateIconAnimations(pointerX, pointerY);
- }
+ let overviewHiddenId = Main.overview.connect('hidden', () => {
+ Main.overview.disconnect(overviewHiddenId)
+ delete SearchController._onStageKeyPress
+ })
}
- return Clutter.EVENT_PROPAGATE;
- }
-
- _onScrollEvent(actor, event) {
-
- let orientation = this.dtpPanel.getOrientation();
-
- // reset timeout to avid conflicts with the mousehover event
- this._timeoutsHandler.add([T1, 0,
- () => this._swiping = false
- ]);
-
- // Skip to avoid double events mouse
- if (event.is_pointer_emulated())
- return Clutter.EVENT_STOP;
-
- let adjustment, delta;
-
- adjustment = this._scrollView[orientation[0] + 'adjustment'];
-
- let increment = adjustment.step_increment;
-
- switch ( event.get_scroll_direction() ) {
- case Clutter.ScrollDirection.UP:
- case Clutter.ScrollDirection.LEFT:
- delta = -increment;
- break;
- case Clutter.ScrollDirection.DOWN:
- case Clutter.ScrollDirection.RIGHT:
- delta = +increment;
- break;
- case Clutter.ScrollDirection.SMOOTH:
- let [dx, dy] = event.get_scroll_delta();
- delta = dy*increment;
- delta += dx*increment;
- break;
-
+ // force exiting overview if needed
+ if (!Main.overview._shown) {
+ this.forcedOverview = true
}
- adjustment.set_value(adjustment.get_value() + delta);
+ //temporarily use as primary the monitor on which the showapps btn was clicked, this is
+ //restored by the panel when exiting the overview
+ this.dtpPanel.panelManager.setFocusedMonitor(this.dtpPanel.monitor)
- return Clutter.EVENT_STOP;
-
- }
-
- _onScrollSizeChange(adjustment) {
- // Update minimization animation target position on scrollview change.
- this._updateAppIcons();
-
- // When applications are ungrouped and there is some empty space on the horizontal taskbar,
- // force a fixed label width to prevent the icons from "wiggling" when an animation runs
- // (adding or removing an icon). When the taskbar is full, revert to a dynamic label width
- // to allow them to resize and make room for new icons.
- if (!this.dtpPanel.checkIfVertical() && !this.isGroupApps) {
- let initial = this.fullScrollView;
-
- if (!this.fullScrollView && Math.floor(adjustment.upper) > adjustment.page_size) {
- this.fullScrollView = adjustment.page_size;
- } else if (adjustment.page_size < this.fullScrollView) {
- this.fullScrollView = 0;
- }
-
- if (initial != this.fullScrollView && !this._waitIdleId) {
- this._waitIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
- this._getAppIcons().forEach(a => a.updateTitleStyle())
- this._waitIdleId = 0;
-
- return GLib.SOURCE_REMOVE;
- });
- }
- }
- }
-
- _onDragBegin() {
- this._dragCancelled = false;
- this._dragMonitor = {
- dragMotion: this._onDragMotion.bind(this)
- };
- DND.addDragMonitor(this._dragMonitor);
-
- if (this._box.get_n_children() == 0) {
- this._emptyDropTarget = new Dash.EmptyDropTargetItem();
- this._box.insert_child_at_index(this._emptyDropTarget, 0);
- this._emptyDropTarget.show(true);
- }
-
- this._toggleFavoriteHighlight(true);
- }
-
- _onDragCancelled() {
- this._dragCancelled = true;
-
- if (this._dragInfo) {
- this._box.set_child_at_index(this._dragInfo[1]._dashItemContainer, this._dragInfo[0]);
- }
-
- this._endDrag();
- }
-
- _onDragEnd() {
- if (this._dragCancelled)
- return;
-
- this._endDrag();
- }
-
- _endDrag() {
- if (this._dragInfo && this._dragInfo[1]._dashItemContainer instanceof DragPlaceholderItem) {
- this._box.remove_child(this._dragInfo[1]._dashItemContainer);
- this._dragInfo[1]._dashItemContainer.destroy();
- delete this._dragInfo[1]._dashItemContainer;
- }
-
- this._dragInfo = null;
- this._clearEmptyDropTarget();
- this._showAppsIcon.setDragApp(null);
- DND.removeDragMonitor(this._dragMonitor);
-
- this._dragMonitor = null;
- this.emit('end-drag');
-
- this._toggleFavoriteHighlight();
- }
-
- _onDragMotion(dragEvent) {
- let app = Dash.Dash.getAppFromSource(dragEvent.source);
- if (app == null)
- return DND.DragMotionResult.CONTINUE;
-
- let showAppsHovered = this._showAppsIcon.contains(dragEvent.targetActor);
-
- if (showAppsHovered)
- this._showAppsIcon.setDragApp(app);
- else
- this._showAppsIcon.setDragApp(null);
-
- return DND.DragMotionResult.CONTINUE;
- }
-
- _toggleFavoriteHighlight(show) {
- let appFavorites = AppFavorites.getAppFavorites();
- let cssFuncName = (show ? 'add' : 'remove') + '_style_class_name';
-
- if (this.showFavorites)
- this._getAppIcons().filter(appIcon => (this.usingLaunchers && appIcon.isLauncher) ||
- (!this.usingLaunchers && appFavorites.isFavorite(appIcon.app.get_id())))
- .forEach(fav => fav._container[cssFuncName]('favorite'));
- }
-
- handleIsolatedWorkspaceSwitch() {
- this._shownInitially = this.isGroupApps;
- this._queueRedisplay();
- }
-
- _connectWorkspaceSignals() {
- this._disconnectWorkspaceSignals();
-
- this._lastWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace();
-
- this._workspaceWindowAddedId = this._lastWorkspace.connect('window-added', () => this._queueRedisplay());
- this._workspaceWindowRemovedId = this._lastWorkspace.connect('window-removed', () => this._queueRedisplay());
- }
-
- _disconnectWorkspaceSignals() {
- if (this._lastWorkspace) {
- this._lastWorkspace.disconnect(this._workspaceWindowAddedId);
- this._lastWorkspace.disconnect(this._workspaceWindowRemovedId);
-
- this._lastWorkspace = null;
- }
- }
-
- _queueRedisplay() {
- Main.queueDeferredWork(this._workId);
- }
-
- _hookUpLabel(item, syncHandler) {
- item.child.connect('notify::hover', () => {
- this._syncLabel(item, syncHandler);
- });
-
- syncHandler.connect('sync-tooltip', () => {
- this._syncLabel(item, syncHandler);
- });
- }
-
- _createAppItem(app, window, isLauncher) {
- let appIcon = new AppIcons.TaskbarAppIcon(
- {
- app,
- window,
- isLauncher
- },
- this.dtpPanel,
- {
- setSizeManually: true,
- showLabel: false,
- isDraggable: !SETTINGS.get_boolean('taskbar-locked'),
- },
- this.previewMenu,
- this.iconAnimator
- );
-
- if (appIcon._draggable) {
- appIcon._draggable.connect('drag-begin',
- () => {
- appIcon.opacity = 0;
- appIcon.isDragged = 1;
- this._dropIconAnimations();
- });
- appIcon._draggable.connect('drag-end',
- () => {
- appIcon.opacity = 255;
- delete appIcon.isDragged;
- this._updateAppIcons();
- });
- }
-
- appIcon.connect('menu-state-changed',
- (appIcon, opened) => {
- this._itemMenuStateChanged(item, opened);
- });
-
- let item = new TaskbarItemContainer();
-
- item._dtpPanel = this.dtpPanel
- extendDashItemContainer(item);
-
- item.setChild(appIcon);
- appIcon._dashItemContainer = item;
-
- appIcon.connect('notify::hover', () => {
- if (appIcon.hover){
- this._timeoutsHandler.add([T1, 100,
- () => Utils.ensureActorVisibleInScrollView(this._scrollView, appIcon, this._scrollView._dtpFadeSize)
- ])
-
- if (!appIcon.isDragged && iconAnimationSettings.type == 'SIMPLE')
- appIcon.get_parent().raise(1);
- else if (!appIcon.isDragged && (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK'))
- this._updateIconAnimations();
- } else {
- this._timeoutsHandler.remove(T1)
-
- if (!appIcon.isDragged && iconAnimationSettings.type == 'SIMPLE')
- appIcon.get_parent().raise(0);
- }
- });
-
- appIcon.connect('clicked',
- (actor) => {
- Utils.ensureActorVisibleInScrollView(this._scrollView, actor, this._scrollView._dtpFadeSize);
- });
-
- appIcon.connect('key-focus-in', (actor) => {
- let [x_shift, y_shift] = Utils.ensureActorVisibleInScrollView(this._scrollView, actor, this._scrollView._dtpFadeSize);
-
- // This signal is triggered also by mouse click. The popup menu is opened at the original
- // coordinates. Thus correct for the shift which is going to be applied to the scrollview.
- if (appIcon._menu) {
- appIcon._menu._boxPointer.xOffset = -x_shift;
- appIcon._menu._boxPointer.yOffset = -y_shift;
- }
- });
-
- // Override default AppIcon label_actor, now the
- // accessible_name is set at DashItemContainer.setLabelText
- appIcon.label_actor = null;
- item.setLabelText(app.get_name());
-
- appIcon.icon.setIconSize(this.iconSize);
- this._hookUpLabel(item, appIcon);
-
- return item;
- }
-
- // Return an array with the "proper" appIcons currently in the taskbar
- _getAppIcons() {
- // Only consider children which are "proper" icons and which are not
- // animating out (which means they will be destroyed at the end of
- // the animation)
- return this._getTaskbarIcons().map(function(actor){
- return actor.child._delegate;
- });
- }
-
- _getTaskbarIcons(includeAnimated) {
- return this._box.get_children().filter(function(actor) {
- return actor.child &&
- actor.child._delegate &&
- actor.child._delegate.icon &&
- (includeAnimated || !actor.animatingOut);
- });
- }
-
- _updateAppIcons() {
- let appIcons = this._getAppIcons();
-
- appIcons.filter(icon => icon.constructor === AppIcons.TaskbarAppIcon).forEach(icon => {
- icon.updateIcon();
- });
- }
-
- _itemMenuStateChanged(item, opened) {
- // When the menu closes, it calls sync_hover, which means
- // that the notify::hover handler does everything we need to.
- if (opened) {
- this._timeoutsHandler.remove(T2)
-
- item.hideLabel();
+ // Finally show the overview
+ selector._showAppsButton.checked = true
+ Main.overview.show(2 /*APP_GRID*/)
+ } else {
+ if (this.forcedOverview) {
+ // force exiting overview if needed
+ Main.overview.hide()
} else {
- // I want to listen from outside when a menu is closed. I used to
- // add a custom signal to the appIcon, since gnome 3.8 the signal
- // calling this callback was added upstream.
- this.emit('menu-closed');
-
- // The icon menu grabs the events and, once it is closed, the pointer is maybe
- // no longer over the taskbar and the animations are not dropped.
- if (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK') {
- this._scrollView.sync_hover();
- if (!this._scrollView.hover)
- this._dropIconAnimations();
- }
+ selector._showAppsButton.checked = false
}
+
+ this.forcedOverview = false
+ }
}
+ }
- _syncLabel(item, syncHandler) {
- let shouldShow = syncHandler ? syncHandler.shouldShowTooltip() : item.child.get_hover();
+ _syncShowAppsButtonToggled() {
+ let status = SearchController._showAppsButton.checked
+ if (this.showAppsButton.checked !== status)
+ this.showAppsButton.checked = status
+ }
- if (shouldShow) {
- if (!this._timeoutsHandler.getId(T2)) {
- let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
+ showShowAppsButton() {
+ this.showAppsButton.visible = true
+ this.showAppsButton.set_width(-1)
+ this.showAppsButton.set_height(-1)
+ }
- this._timeoutsHandler.add([T2, timeout,
- () => {
- this._labelShowing = true;
- item.showLabel();
- }
- ]);
+ popupFocusedAppSecondaryMenu() {
+ let appIcons = this._getAppIcons()
+ let tracker = Shell.WindowTracker.get_default()
- this._timeoutsHandler.remove(T3)
- }
- } else {
- this._timeoutsHandler.remove(T2)
+ for (let i in appIcons) {
+ if (appIcons[i].app == tracker.focus_app) {
+ let appIcon = appIcons[i]
+ if (appIcon._menu && appIcon._menu.isOpen) appIcon._menu.close()
+ else appIcon.popupMenu()
- item.hideLabel();
- if (this._labelShowing) {
- this._timeoutsHandler.add([T3, DASH_ITEM_HOVER_TIMEOUT,
- () => this._labelShowing = false
- ]);
- }
- }
+ appIcon.sync_hover()
+ break
+ }
}
+ }
+}
- _adjustIconSize() {
- const thisMonitorIndex = this.dtpPanel.monitor.index;
- let panelSize = PanelSettings.getPanelSize(SETTINGS, thisMonitorIndex);
- let availSize = panelSize - SETTINGS.get_int('appicon-padding') * 2;
- let minIconSize = MIN_ICON_SIZE + panelSize % 2;
-
- if (availSize == this.iconSize)
- return;
-
- if (availSize < minIconSize) {
- availSize = minIconSize;
- }
-
- // For the icon size, we only consider children which are "proper"
- // icons and which are not animating out (which means they will be
- // destroyed at the end of the animation)
- let iconChildren = this._getTaskbarIcons().concat([this._showAppsIcon]);
- let scale = this.iconSize / availSize;
-
- this.iconSize = availSize;
-
- for (let i = 0; i < iconChildren.length; i++) {
- let icon = iconChildren[i].child._delegate.icon;
-
- // Set the new size immediately, to keep the icons' sizes
- // in sync with this.iconSize
- icon.setIconSize(this.iconSize);
-
- // Don't animate the icon size change when the overview
- // is transitioning, or when initially filling
- // the taskbar
- if (Main.overview.animationInProgress ||
- !this._shownInitially)
- continue;
-
- let [targetWidth, targetHeight] = icon.icon.get_size();
-
- // Scale the icon's texture to the previous size and
- // tween to the new size
- icon.icon.set_size(icon.icon.width * scale, icon.icon.height * scale);
-
- Utils.animate(icon.icon,
- { width: targetWidth,
- height: targetHeight,
- time: DASH_ANIMATION_TIME,
- transition: 'easeOutQuad',
- });
- }
- }
-
- sortAppsCompareFunction(appA, appB) {
- return getAppStableSequence(appA, this.dtpPanel.monitor) -
- getAppStableSequence(appB, this.dtpPanel.monitor);
- }
-
- getAppInfos() {
- //get the user's favorite apps
- let favoriteApps = this.showFavorites ? AppFavorites.getAppFavorites().getFavorites() : [];
-
- //find the apps that should be in the taskbar: the favorites first, then add the running apps
- // When using isolation, we filter out apps that have no windows in
- // the current workspace (this check is done in AppIcons.getInterestingWindows)
- let runningApps = this.showRunningApps ? this._getRunningApps().sort(this.sortAppsCompareFunction.bind(this)) : [];
- let appInfos
-
- if (this.allowSplitApps) {
- appInfos = this._createAppInfos(favoriteApps, [], true)
- .concat(this._createAppInfos(runningApps)
- .filter(appInfo => appInfo.windows.length));
- } else {
- appInfos = this._createAppInfos(favoriteApps.concat(runningApps.filter(app => favoriteApps.indexOf(app) < 0)))
- .filter(appInfo => appInfo.windows.length || favoriteApps.indexOf(appInfo.app) >= 0);
- }
-
- if (this._donateApp)
- appInfos = [
- {
- app: this._donateApp,
- isLauncher: true,
- windows: [],
- },
- ...appInfos
- ]
-
- return appInfos
- }
-
- _redisplay() {
- if (!this._signalsHandler) {
- return;
- }
-
- //get the currently displayed appIcons
- let currentAppIcons = this._getTaskbarIcons();
- let expectedAppInfos = this.getAppInfos();
-
- //remove the appIcons which are not in the expected apps list
- for (let i = currentAppIcons.length - 1; i > -1; --i) {
- let appIcon = currentAppIcons[i].child._delegate;
- let appIndex = Utils.findIndex(expectedAppInfos, appInfo => appInfo.app == appIcon.app &&
- (!this.allowSplitApps || this.isGroupApps || appInfo.windows[0] == appIcon.window) &&
- appInfo.isLauncher == appIcon.isLauncher);
-
- if (appIndex < 0 ||
- (appIcon.window && (this.isGroupApps || expectedAppInfos[appIndex].windows.indexOf(appIcon.window) < 0)) ||
- (!appIcon.window && !appIcon.isLauncher &&
- !this.isGroupApps && expectedAppInfos[appIndex].windows.length)) {
- currentAppIcons[i][this._shownInitially ? 'animateOutAndDestroy' : 'destroy']();
- currentAppIcons.splice(i, 1);
- }
- }
-
- //if needed, reorder the existing appIcons and create the missing ones
- let currentPosition = 0;
- for (let i = 0, l = expectedAppInfos.length; i < l; ++i) {
- let neededAppIcons = this.isGroupApps || !expectedAppInfos[i].windows.length ?
- [{ app: expectedAppInfos[i].app, window: null, isLauncher: expectedAppInfos[i].isLauncher }] :
- expectedAppInfos[i].windows.map(window => ({ app: expectedAppInfos[i].app, window: window, isLauncher: false }));
-
- for (let j = 0, ll = neededAppIcons.length; j < ll; ++j) {
- //check if the icon already exists
- let matchingAppIconIndex = Utils.findIndex(currentAppIcons, appIcon => appIcon.child._delegate.app == neededAppIcons[j].app &&
- appIcon.child._delegate.window == neededAppIcons[j].window);
-
- if (matchingAppIconIndex > 0 && matchingAppIconIndex != currentPosition) {
- //moved icon, reposition it
- this._box.remove_child(currentAppIcons[matchingAppIconIndex]);
- this._box.insert_child_at_index(currentAppIcons[matchingAppIconIndex], currentPosition);
- } else if (matchingAppIconIndex < 0) {
- //the icon doesn't exist yet, create a new one
- let newAppIcon = this._createAppItem(neededAppIcons[j].app, neededAppIcons[j].window, neededAppIcons[j].isLauncher);
-
- this._box.insert_child_at_index(newAppIcon, currentPosition);
- currentAppIcons.splice(currentPosition, 0, newAppIcon);
-
- // Skip animations on first run when adding the initial set
- // of items, to avoid all items zooming in at once
- newAppIcon.show(this._shownInitially);
- }
-
- ++currentPosition;
- }
- }
-
- this._adjustIconSize();
-
- // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744
- // Without it, StBoxLayout may use a stale size cache
- this._box.queue_relayout();
-
- // This is required for icon reordering when the scrollview is used.
- this._updateAppIcons();
-
- // This will update the size, and the corresponding number for each icon on the primary panel
- if (this.dtpPanel.isPrimary) {
- this._updateNumberOverlay();
- }
-
- this._shownInitially = true;
- }
-
- _getRunningApps() {
- let tracker = Shell.WindowTracker.get_default();
- let windows = global.get_window_actors();
- let apps = [];
-
- for (let i = 0, l = windows.length; i < l; ++i) {
- let app = tracker.get_window_app(windows[i].metaWindow);
-
- if (app && apps.indexOf(app) < 0) {
- apps.push(app);
- }
- }
-
- return apps;
- }
-
- _createAppInfos(apps, defaultWindows, defaultIsLauncher) {
- if (this.allowSplitApps && !defaultIsLauncher) {
- let separateApps = []
-
- if (apps.length) {
- let tracker = Shell.WindowTracker.get_default();
- let windows = AppIcons.getInterestingWindows(null, this.dtpPanel.monitor)
- .sort(sortWindowsCompareFunction)
-
- windows.forEach(w => {
- let windowApp = tracker.get_window_app(w)
-
- if (apps.indexOf(windowApp) >= 0)
- separateApps.push({
- app: windowApp,
- isLauncher: false,
- windows: [w]
- })
- })
- }
-
- return separateApps
- }
-
- return apps.map(app => ({
- app: app,
- isLauncher: defaultIsLauncher || false,
- windows: defaultWindows || AppIcons.getInterestingWindows(app, this.dtpPanel.monitor)
- .sort(sortWindowsCompareFunction)
- }));
- }
-
- // Reset the displayed apps icon to mantain the correct order
- resetAppIcons (geometryChange) {
- let children = this._getTaskbarIcons(true);
-
- for (let i = 0; i < children.length; i++) {
- let item = children[i];
- item.destroy();
- }
-
- // to avoid ugly animations, just suppress them like when taskbar is first loaded.
- this._shownInitially = false;
- this._redisplay();
-
- if (geometryChange && this.dtpPanel.checkIfVertical()) {
- this.previewMenu._updateClip();
- }
- }
-
- _updateNumberOverlay() {
- let seenApps = {};
- let counter = 0;
-
- this._getAppIcons().forEach(icon => {
- if (!seenApps[icon.app] || this.allowSplitApps) {
- seenApps[icon.app] = 1;
- counter++;
- }
-
- if (counter <= 10) {
- icon.setNumberOverlay(counter == 10 ? 0 : counter);
- } else {
- // No overlay after 10
- icon.setNumberOverlay(-1);
- }
-
- icon.updateHotkeyNumberOverlay();
- });
-
- if (SETTINGS.get_boolean('hot-keys') &&
- SETTINGS.get_string('hotkeys-overlay-combo') === 'ALWAYS')
- this.toggleNumberOverlay(true);
- }
-
- toggleNumberOverlay(activate) {
- let appIcons = this._getAppIcons();
- appIcons.forEach(function(icon) {
- icon.toggleNumberOverlay(activate);
- });
- }
-
- _clearEmptyDropTarget() {
- if (this._emptyDropTarget) {
- this._emptyDropTarget.animateOutAndDestroy();
- this._emptyDropTarget = null;
- }
- }
-
- handleDragOver(source, actor, x, y, time) {
- if (source == Main.xdndHandler)
- return DND.DragMotionResult.CONTINUE;
-
- // Don't allow favoriting of transient apps
- if (source.app == null || source.app.is_window_backed())
- return DND.DragMotionResult.NO_DROP;
-
- if (!this._settings.is_writable('favorite-apps'))
- return DND.DragMotionResult.NO_DROP;
-
- let isVertical = this.dtpPanel.checkIfVertical();
-
- if (!this._box.contains(source) && !source._dashItemContainer) {
- //not an appIcon of the taskbar, probably from the applications view
- source._dashItemContainer = new DragPlaceholderItem(source, this.iconSize, isVertical);
- this._box.insert_child_above(source._dashItemContainer, null);
- }
-
- let sizeProp = isVertical ? 'height' : 'width';
- let posProp = isVertical ? 'y' : 'x';
- let pos = isVertical ? y : x;
-
- let currentAppIcons = this._getAppIcons();
- let sourceIndex = currentAppIcons.indexOf(source);
- let hoveredIndex = Utils.findIndex(currentAppIcons,
- appIcon => pos >= appIcon._dashItemContainer[posProp] &&
- pos <= (appIcon._dashItemContainer[posProp] + appIcon._dashItemContainer[sizeProp]));
-
- if (!this._dragInfo) {
- this._dragInfo = [sourceIndex, source];
- }
-
- if (hoveredIndex >= 0) {
- let isLeft = pos < currentAppIcons[hoveredIndex]._dashItemContainer[posProp] + currentAppIcons[hoveredIndex]._dashItemContainer[sizeProp] * .5;
- let prevIcon = currentAppIcons[hoveredIndex - 1]
- let nextIcon = currentAppIcons[hoveredIndex + 1]
-
- // Don't allow positioning before or after self and between icons of same app if ungrouped and showing favorites
- if (!(hoveredIndex === sourceIndex ||
- (isLeft && hoveredIndex - 1 == sourceIndex) ||
- (!this.allowSplitApps && isLeft && hoveredIndex - 1 >= 0 && source.app != prevIcon.app &&
- prevIcon.app == currentAppIcons[hoveredIndex].app) ||
- (!isLeft && hoveredIndex + 1 == sourceIndex) ||
- (!this.allowSplitApps && !isLeft && hoveredIndex + 1 < currentAppIcons.length && source.app != nextIcon.app &&
- nextIcon.app == currentAppIcons[hoveredIndex].app))) {
- this._box.set_child_at_index(source._dashItemContainer, hoveredIndex);
-
- // Ensure the next and previous icon are visible when moving the icon
- // (I assume there's room for both of them)
- if (hoveredIndex > 1)
- Utils.ensureActorVisibleInScrollView(this._scrollView, this._box.get_children()[hoveredIndex-1], this._scrollView._dtpFadeSize);
- if (hoveredIndex < this._box.get_children().length-1)
- Utils.ensureActorVisibleInScrollView(this._scrollView, this._box.get_children()[hoveredIndex+1], this._scrollView._dtpFadeSize);
- }
- }
-
- return this._dragInfo[0] !== sourceIndex ? DND.DragMotionResult.MOVE_DROP : DND.DragMotionResult.CONTINUE;
- }
-
- // Draggable target interface
- acceptDrop (source, actor, x, y, time) {
- // Don't allow favoriting of transient apps
- if (!this._dragInfo || !source.app || source.app.is_window_backed() ||
- !this._settings.is_writable('favorite-apps')) {
- return false;
- }
-
- let appIcons = this._getAppIcons();
- let sourceIndex = appIcons.indexOf(source);
- let usingLaunchers = !this.isGroupApps && this.usingLaunchers;
-
- // dragging the icon to its original position
- if (this._dragInfo[0] === sourceIndex) {
- return true;
- }
-
- let appFavorites = AppFavorites.getAppFavorites();
- let sourceAppId = source.app.get_id();
- let appIsFavorite = this.showFavorites && appFavorites.isFavorite(sourceAppId);
- let replacingIndex = sourceIndex + (sourceIndex > this._dragInfo[0] ? -1 : 1);
- let favoriteIndex = replacingIndex >= 0 ? appFavorites.getFavorites().indexOf(appIcons[replacingIndex].app) : 0;
- let sameApps = this.allowSplitApps ? [] : appIcons.filter(a => a != source && a.app == source.app);
- let favoritesCount = 0;
- let position = 0;
- let interestingWindows = {};
- let getAppWindows = app => {
- if (!interestingWindows[app]) {
- interestingWindows[app] = AppIcons.getInterestingWindows(app, this.dtpPanel.monitor);
- }
-
- let appWindows = interestingWindows[app]; //prevents "reference to undefined property Symbol.toPrimitive" warning
- return appWindows;
- };
-
- if (sameApps.length &&
- ((!appIcons[sourceIndex - 1] || appIcons[sourceIndex - 1].app !== source.app) &&
- (!appIcons[sourceIndex + 1] || appIcons[sourceIndex + 1].app !== source.app))) {
- appIcons.splice(appIcons.indexOf(sameApps[0]), sameApps.length);
- Array.prototype.splice.apply(appIcons, [sourceIndex + 1, 0].concat(sameApps));
- }
-
- for (let i = 0, l = appIcons.length; i < l; ++i) {
- let windows = [];
-
- if (!usingLaunchers || (!source.isLauncher && !appIcons[i].isLauncher)) {
- windows = appIcons[i].window ? [appIcons[i].window] : getAppWindows(appIcons[i].app);
- }
-
- windows.forEach(w => w._dtpPosition = position++);
-
- if (this.showFavorites &&
- ((usingLaunchers && appIcons[i].isLauncher) ||
- (!usingLaunchers && appFavorites.isFavorite(appIcons[i].app.get_id())))) {
- ++favoritesCount;
- }
- }
-
- if (sourceIndex < favoritesCount) {
- if (appIsFavorite) {
- appFavorites.moveFavoriteToPos(sourceAppId, favoriteIndex);
- } else {
- appFavorites.addFavoriteAtPos(sourceAppId, favoriteIndex);
- }
- } else if (appIsFavorite && this.showFavorites && (!usingLaunchers || source.isLauncher)) {
- appFavorites.removeFavorite(sourceAppId);
- }
-
- appFavorites.emit('changed');
-
- return true;
- }
-
- _onShowAppsButtonToggled() {
- // Sync the status of the default appButtons. Only if the two statuses are
- // different, that means the user interacted with the extension provided
- // application button, cutomize the behaviour. Otherwise the shell has changed the
- // status (due to the _syncShowAppsButtonToggled function below) and it
- // has already performed the desired action.
- let selector = SearchController;
-
- if (selector._showAppsButton &&
- selector._showAppsButton.checked !== this.showAppsButton.checked) {
- // find visible view
-
- if (this.showAppsButton.checked) {
- if (SETTINGS.get_boolean('show-apps-override-escape')) {
- //override escape key to return to the desktop when entering the overview using the showapps button
- SearchController._onStageKeyPress = function(actor, event) {
- if (Main.modalCount == 1 && event.get_key_symbol() === Clutter.KEY_Escape) {
- this._searchActive ? this.reset() : Main.overview.hide();
-
- return Clutter.EVENT_STOP;
- }
-
- return Object.getPrototypeOf(this)._onStageKeyPress.call(this, actor, event);
- };
-
- let overviewHiddenId = Main.overview.connect('hidden', () => {
- Main.overview.disconnect(overviewHiddenId);
- delete SearchController._onStageKeyPress;
- });
- }
-
- // force exiting overview if needed
- if (!Main.overview._shown) {
- this.forcedOverview = true;
- }
-
- //temporarily use as primary the monitor on which the showapps btn was clicked, this is
- //restored by the panel when exiting the overview
- this.dtpPanel.panelManager.setFocusedMonitor(this.dtpPanel.monitor);
-
- // Finally show the overview
- selector._showAppsButton.checked = true;
- Main.overview.show(2 /*APP_GRID*/);
- }
- else {
- if (this.forcedOverview) {
- // force exiting overview if needed
- Main.overview.hide();
- } else {
- selector._showAppsButton.checked = false;
- }
-
- this.forcedOverview = false;
- }
- }
- }
-
- _syncShowAppsButtonToggled() {
- let status = SearchController._showAppsButton.checked;
- if (this.showAppsButton.checked !== status)
- this.showAppsButton.checked = status;
- }
-
- showShowAppsButton() {
- this.showAppsButton.visible = true;
- this.showAppsButton.set_width(-1);
- this.showAppsButton.set_height(-1);
- }
-
- popupFocusedAppSecondaryMenu() {
- let appIcons = this._getAppIcons();
- let tracker = Shell.WindowTracker.get_default();
-
- for(let i in appIcons) {
- if(appIcons[i].app == tracker.focus_app) {
- let appIcon = appIcons[i];
- if(appIcon._menu && appIcon._menu.isOpen)
- appIcon._menu.close();
- else
- appIcon.popupMenu();
-
- appIcon.sync_hover();
- break;
- }
- }
- }
-};
-
-export const TaskbarItemContainer = GObject.registerClass({
-
-}, class TaskbarItemContainer extends Dash.DashItemContainer {
-
+export const TaskbarItemContainer = GObject.registerClass(
+ {},
+ class TaskbarItemContainer extends Dash.DashItemContainer {
_init() {
- super._init()
- this.x_expand = this.y_expand = false
+ super._init()
+ this.x_expand = this.y_expand = false
}
vfunc_allocate(box) {
- if (this.child == null)
- return;
+ if (this.child == null) return
- this.set_allocation(box);
+ this.set_allocation(box)
- let availWidth = box.x2 - box.x1;
- let availHeight = box.y2 - box.y1;
- let [minChildWidth, minChildHeight, natChildWidth, natChildHeight] = this.child.get_preferred_size();
- let [childScaleX, childScaleY] = this.child.get_scale();
+ let availWidth = box.x2 - box.x1
+ let availHeight = box.y2 - box.y1
+ let [minChildWidth, minChildHeight, natChildWidth, natChildHeight] =
+ this.child.get_preferred_size()
+ let [childScaleX, childScaleY] = this.child.get_scale()
- let childWidth = Math.min(natChildWidth * childScaleX, availWidth);
- let childHeight = Math.min(natChildHeight * childScaleY, availHeight);
- let childBox = new Clutter.ActorBox();
+ let childWidth = Math.min(natChildWidth * childScaleX, availWidth)
+ let childHeight = Math.min(natChildHeight * childScaleY, availHeight)
+ let childBox = new Clutter.ActorBox()
- childBox.x1 = (availWidth - childWidth) / 2;
- childBox.y1 = (availHeight - childHeight) / 2;
- childBox.x2 = childBox.x1 + childWidth;
- childBox.y2 = childBox.y1 + childHeight;
+ childBox.x1 = (availWidth - childWidth) / 2
+ childBox.y1 = (availHeight - childHeight) / 2
+ childBox.x2 = childBox.x1 + childWidth
+ childBox.y2 = childBox.y1 + childHeight
- this.child.allocate(childBox);
+ this.child.allocate(childBox)
}
// In case appIcon is removed from the taskbar while it is hovered,
// restore opacity before dashItemContainer.animateOutAndDestroy does the destroy animation.
animateOutAndDestroy() {
- if (this._raisedClone) {
- this._raisedClone.source.opacity = 255;
- this._raisedClone.destroy();
- }
+ if (this._raisedClone) {
+ this._raisedClone.source.opacity = 255
+ this._raisedClone.destroy()
+ }
- super.animateOutAndDestroy();
+ super.animateOutAndDestroy()
}
// For ItemShowLabel
_getIconAnimationOffset() {
- if (!SETTINGS.get_boolean('animate-appicon-hover'))
- return 0;
+ if (!SETTINGS.get_boolean('animate-appicon-hover')) return 0
- let travel = iconAnimationSettings.travel;
- let zoom = iconAnimationSettings.zoom;
- return this._dtpPanel.dtpSize * Math.max(0, travel + (zoom - 1) / 2);
+ let travel = iconAnimationSettings.travel
+ let zoom = iconAnimationSettings.zoom
+ return this._dtpPanel.dtpSize * Math.max(0, travel + (zoom - 1) / 2)
}
_updateCloneContainerPosition(cloneContainer) {
- let [stageX, stageY] = this.get_transformed_position();
+ let [stageX, stageY] = this.get_transformed_position()
- cloneContainer.set_position(
- stageX - this._dtpPanel.panelBox.translation_x - this.translation_x,
- stageY - this._dtpPanel.panelBox.translation_y - this.translation_y
- );
+ cloneContainer.set_position(
+ stageX - this._dtpPanel.panelBox.translation_x - this.translation_x,
+ stageY - this._dtpPanel.panelBox.translation_y - this.translation_y,
+ )
}
_createRaisedClone() {
- let [width, height] = this.get_transformed_size();
+ let [width, height] = this.get_transformed_size()
- // "clone" of this child (appIcon actor)
- let cloneButton = this.child._delegate.getCloneButton();
+ // "clone" of this child (appIcon actor)
+ let cloneButton = this.child._delegate.getCloneButton()
- // "clone" of this (taskbarItemContainer)
- let cloneContainer = new St.Bin({
- child: cloneButton,
- width: width, height: height,
- reactive: false,
- });
+ // "clone" of this (taskbarItemContainer)
+ let cloneContainer = new St.Bin({
+ child: cloneButton,
+ width: width,
+ height: height,
+ reactive: false,
+ })
- this._updateCloneContainerPosition(cloneContainer);
+ this._updateCloneContainerPosition(cloneContainer)
- // For the stretch animation
- let boundProperty = this._dtpPanel.checkIfVertical() ? 'translation_y' : 'translation_x';
- this.bind_property(boundProperty, cloneContainer, boundProperty, GObject.BindingFlags.SYNC_CREATE);
+ // For the stretch animation
+ let boundProperty = this._dtpPanel.checkIfVertical()
+ ? 'translation_y'
+ : 'translation_x'
+ this.bind_property(
+ boundProperty,
+ cloneContainer,
+ boundProperty,
+ GObject.BindingFlags.SYNC_CREATE,
+ )
+ // The clone follows its source when the taskbar is scrolled.
+ let taskbarScrollView = this.get_parent().get_parent()
+ let adjustment = this._dtpPanel.checkIfVertical()
+ ? taskbarScrollView.get_vadjustment()
+ : taskbarScrollView.get_hadjustment()
+ let adjustmentChangedId = adjustment.connect('notify::value', () =>
+ this._updateCloneContainerPosition(cloneContainer),
+ )
- // The clone follows its source when the taskbar is scrolled.
- let taskbarScrollView = this.get_parent().get_parent();
- let adjustment = this._dtpPanel.checkIfVertical() ? taskbarScrollView.get_vadjustment() : taskbarScrollView.get_hadjustment();
- let adjustmentChangedId = adjustment.connect('notify::value', () => this._updateCloneContainerPosition(cloneContainer));
+ // Update clone position when an item is added to / removed from the taskbar.
+ let taskbarBox = this.get_parent()
+ let taskbarBoxAllocationChangedId = taskbarBox.connect(
+ 'notify::allocation',
+ () => this._updateCloneContainerPosition(cloneContainer),
+ )
- // Update clone position when an item is added to / removed from the taskbar.
- let taskbarBox = this.get_parent();
- let taskbarBoxAllocationChangedId = taskbarBox.connect('notify::allocation', () => this._updateCloneContainerPosition(cloneContainer));
+ // The clone itself
+ this._raisedClone = cloneButton.child
+ this._raisedClone.connect('destroy', () => {
+ adjustment.disconnect(adjustmentChangedId)
+ taskbarBox.disconnect(taskbarBoxAllocationChangedId)
+ GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
+ cloneContainer.destroy()
+ return GLib.SOURCE_REMOVE
+ })
+ delete this._raisedClone
+ })
- // The clone itself
- this._raisedClone = cloneButton.child;
- this._raisedClone.connect('destroy', () => {
- adjustment.disconnect(adjustmentChangedId);
- taskbarBox.disconnect(taskbarBoxAllocationChangedId);
- GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
- cloneContainer.destroy();
- return GLib.SOURCE_REMOVE;
- });
- delete this._raisedClone;
- });
-
- this._raisedClone.source.opacity = 0;
- Main.uiGroup.add_child(cloneContainer);
+ this._raisedClone.source.opacity = 0
+ Main.uiGroup.add_child(cloneContainer)
}
// Animate the clone.
// AppIcon actors cannot go outside the taskbar so the animation is done with a clone.
// If level is zero, the clone is dropped and destroyed.
raise(level) {
- if (this._raisedClone)
- Utils.stopAnimations(this._raisedClone);
- else if (level)
- this._createRaisedClone();
- else
- return;
+ if (this._raisedClone) Utils.stopAnimations(this._raisedClone)
+ else if (level) this._createRaisedClone()
+ else return
- let panelPosition = this._dtpPanel.getPosition();
- let panelElementPositions = this._dtpPanel.panelManager.panelsElementPositions[this._dtpPanel.monitor.index] || Pos.defaults;
- let taskbarPosition = panelElementPositions.filter(pos => pos.element == 'taskbar')[0].position;
+ let panelPosition = this._dtpPanel.getPosition()
+ let panelElementPositions =
+ this._dtpPanel.panelManager.panelsElementPositions[
+ this._dtpPanel.monitor.index
+ ] || Pos.defaults
+ let taskbarPosition = panelElementPositions.filter(
+ (pos) => pos.element == 'taskbar',
+ )[0].position
- let vertical = panelPosition == St.Side.LEFT || panelPosition == St.Side.RIGHT;
- let translationDirection = panelPosition == St.Side.TOP || panelPosition == St.Side.LEFT ? 1 : -1;
- let rotationDirection;
- if (panelPosition == St.Side.LEFT || taskbarPosition == Pos.STACKED_TL)
- rotationDirection = -1;
- else if (panelPosition == St.Side.RIGHT || taskbarPosition == Pos.STACKED_BR)
- rotationDirection = 1;
- else {
- let items = this.get_parent().get_children();
- let index = items.indexOf(this);
- rotationDirection = (index - (items.length - 1) / 2) / ((items.length - 1) / 2);
- }
+ let vertical =
+ panelPosition == St.Side.LEFT || panelPosition == St.Side.RIGHT
+ let translationDirection =
+ panelPosition == St.Side.TOP || panelPosition == St.Side.LEFT ? 1 : -1
+ let rotationDirection
+ if (panelPosition == St.Side.LEFT || taskbarPosition == Pos.STACKED_TL)
+ rotationDirection = -1
+ else if (
+ panelPosition == St.Side.RIGHT ||
+ taskbarPosition == Pos.STACKED_BR
+ )
+ rotationDirection = 1
+ else {
+ let items = this.get_parent().get_children()
+ let index = items.indexOf(this)
+ rotationDirection =
+ (index - (items.length - 1) / 2) / ((items.length - 1) / 2)
+ }
- let duration = iconAnimationSettings.duration / 1000;
- let rotation = iconAnimationSettings.rotation;
- let travel = iconAnimationSettings.travel;
- let zoom = iconAnimationSettings.zoom;
+ let duration = iconAnimationSettings.duration / 1000
+ let rotation = iconAnimationSettings.rotation
+ let travel = iconAnimationSettings.travel
+ let zoom = iconAnimationSettings.zoom
- // level is about 1 for the icon that is hovered, less for others.
- // time depends on the translation to do.
- let [width, height] = this._raisedClone.source.get_transformed_size();
- let translationMax = (vertical ? width : height) * (travel + (zoom - 1) / 2);
- let translationEnd = translationMax * level;
- let translationDone = vertical ? this._raisedClone.translation_x : this._raisedClone.translation_y;
- let translationTodo = Math.sign(travel)*Math.abs(translationEnd - translationDone);
- let scale = 1 + (zoom - 1) * level;
- let rotationAngleZ = rotationDirection * rotation * level;
- let time = Math.abs(duration * translationTodo / translationMax);
+ // level is about 1 for the icon that is hovered, less for others.
+ // time depends on the translation to do.
+ let [width, height] = this._raisedClone.source.get_transformed_size()
+ let translationMax =
+ (vertical ? width : height) * (travel + (zoom - 1) / 2)
+ let translationEnd = translationMax * level
+ let translationDone = vertical
+ ? this._raisedClone.translation_x
+ : this._raisedClone.translation_y
+ let translationTodo =
+ Math.sign(travel) * Math.abs(translationEnd - translationDone)
+ let scale = 1 + (zoom - 1) * level
+ let rotationAngleZ = rotationDirection * rotation * level
+ let time = Math.abs((duration * translationTodo) / translationMax)
- let options = {
- scale_x: scale, scale_y: scale,
- rotation_angle_z: rotationAngleZ,
- time: time,
- transition: 'easeOutQuad',
- onComplete: () => {
- if (!level) {
- this._raisedClone.source.opacity = 255;
- this._raisedClone.destroy();
- delete this._raisedClone;
- }
- }
- };
- options[vertical ? 'translation_x' : 'translation_y'] = translationDirection * translationEnd;
+ let options = {
+ scale_x: scale,
+ scale_y: scale,
+ rotation_angle_z: rotationAngleZ,
+ time: time,
+ transition: 'easeOutQuad',
+ onComplete: () => {
+ if (!level) {
+ this._raisedClone.source.opacity = 255
+ this._raisedClone.destroy()
+ delete this._raisedClone
+ }
+ },
+ }
+ options[vertical ? 'translation_x' : 'translation_y'] =
+ translationDirection * translationEnd
- Utils.animate(this._raisedClone, options);
+ Utils.animate(this._raisedClone, options)
}
// Animate this and cloneContainer, since cloneContainer translation is bound to this.
stretch(translation) {
- let duration = iconAnimationSettings.duration / 1000;
- let zoom = iconAnimationSettings.zoom;
- let animatedProperty = this._dtpPanel.checkIfVertical() ? 'translation_y' : 'translation_x';
- let isShowing = this.opacity != 255 || this.child.opacity != 255;
+ let duration = iconAnimationSettings.duration / 1000
+ let zoom = iconAnimationSettings.zoom
+ let animatedProperty = this._dtpPanel.checkIfVertical()
+ ? 'translation_y'
+ : 'translation_x'
+ let isShowing = this.opacity != 255 || this.child.opacity != 255
- if (isShowing) {
- // Do no stop the animation initiated in DashItemContainer.show.
- this[animatedProperty] = zoom * translation;
- } else {
- let options = {
- time: duration,
- transition: 'easeOutQuad',
- };
- options[animatedProperty] = zoom * translation;
-
- Utils.stopAnimations(this);
- Utils.animate(this, options);
+ if (isShowing) {
+ // Do no stop the animation initiated in DashItemContainer.show.
+ this[animatedProperty] = zoom * translation
+ } else {
+ let options = {
+ time: duration,
+ transition: 'easeOutQuad',
}
+ options[animatedProperty] = zoom * translation
+
+ Utils.stopAnimations(this)
+ Utils.animate(this, options)
+ }
}
-});
-
-const DragPlaceholderItem = GObject.registerClass({
-}, class DragPlaceholderItem extends St.Widget {
+ },
+)
+const DragPlaceholderItem = GObject.registerClass(
+ {},
+ class DragPlaceholderItem extends St.Widget {
_init(appIcon, iconSize, isVertical) {
- super._init({ style: AppIcons.getIconContainerStyle(isVertical), layout_manager: new Clutter.BinLayout() });
+ super._init({
+ style: AppIcons.getIconContainerStyle(isVertical),
+ layout_manager: new Clutter.BinLayout(),
+ })
- this.child = { _delegate: appIcon };
+ this.child = { _delegate: appIcon }
- this._clone = new Clutter.Clone({
- source: appIcon.icon._iconBin,
- width: iconSize,
- height: iconSize
- });
+ this._clone = new Clutter.Clone({
+ source: appIcon.icon._iconBin,
+ width: iconSize,
+ height: iconSize,
+ })
- this.add_child(this._clone);
+ this.add_child(this._clone)
}
destroy() {
- this._clone.destroy();
- super.destroy();
+ this._clone.destroy()
+ super.destroy()
}
-});
+ },
+)
export function getAppStableSequence(app, monitor) {
- let windows = AppIcons.getInterestingWindows(app, monitor);
+ let windows = AppIcons.getInterestingWindows(app, monitor)
- return windows.reduce((prevWindow, window) => {
- return Math.min(prevWindow, getWindowStableSequence(window));
- }, Infinity);
+ return windows.reduce((prevWindow, window) => {
+ return Math.min(prevWindow, getWindowStableSequence(window))
+ }, Infinity)
}
export function sortWindowsCompareFunction(windowA, windowB) {
- return getWindowStableSequence(windowA) - getWindowStableSequence(windowB);
+ return getWindowStableSequence(windowA) - getWindowStableSequence(windowB)
}
export function getWindowStableSequence(window) {
- return ('_dtpPosition' in window ? window._dtpPosition : window.get_stable_sequence());
+ return '_dtpPosition' in window
+ ? window._dtpPosition
+ : window.get_stable_sequence()
}
diff --git a/transparency.js b/transparency.js
index 25ff00f..19da558 100644
--- a/transparency.js
+++ b/transparency.js
@@ -15,238 +15,254 @@
* along with this program. If not, see .
*/
-import GdkPixbuf from 'gi://GdkPixbuf';
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
-import St from 'gi://St';
+import GdkPixbuf from 'gi://GdkPixbuf'
+import * as Main from 'resource:///org/gnome/shell/ui/main.js'
+import St from 'gi://St'
-import * as Proximity from './proximity.js';
-import * as Utils from './utils.js';
-import {SETTINGS} from './extension.js';
+import * as Proximity from './proximity.js'
+import * as Utils from './utils.js'
+import { SETTINGS } from './extension.js'
export const DynamicTransparency = class {
+ constructor(dtpPanel) {
+ this._dtpPanel = dtpPanel
+ this._proximityManager = dtpPanel.panelManager.proximityManager
+ this._proximityWatchId = 0
+ this.currentBackgroundColor = 0
- constructor(dtpPanel) {
- this._dtpPanel = dtpPanel;
- this._proximityManager = dtpPanel.panelManager.proximityManager;
- this._proximityWatchId = 0;
- this.currentBackgroundColor = 0;
+ this._initialPanelStyle = dtpPanel.panel.get_style()
- this._initialPanelStyle = dtpPanel.panel.get_style();
+ this._signalsHandler = new Utils.GlobalSignalsHandler()
+ this._bindSignals()
- this._signalsHandler = new Utils.GlobalSignalsHandler();
- this._bindSignals();
+ this._updateAnimationDuration()
+ this._updateAllAndSet()
+ this._updateProximityWatch()
+ }
- this._updateAnimationDuration();
- this._updateAllAndSet();
- this._updateProximityWatch();
+ destroy() {
+ this._signalsHandler.destroy()
+ this._proximityManager.removeWatch(this._proximityWatchId)
+
+ this._dtpPanel.panel.set_style(this._initialPanelStyle)
+ }
+
+ updateExternalStyle() {
+ this._updateComplementaryStyles()
+ this._setBackground()
+ }
+
+ _bindSignals() {
+ this._signalsHandler.add(
+ [Utils.getStageTheme(), 'changed', () => this._updateAllAndSet()],
+ [Main.overview, ['showing', 'hiding'], () => this._updateAlphaAndSet()],
+ [
+ SETTINGS,
+ ['changed::trans-use-custom-bg', 'changed::trans-bg-color'],
+ () => this._updateColorAndSet(),
+ ],
+ [
+ SETTINGS,
+ [
+ 'changed::trans-use-custom-opacity',
+ 'changed::trans-panel-opacity',
+ 'changed::trans-bg-color',
+ 'changed::trans-dynamic-anim-target',
+ 'changed::trans-use-dynamic-opacity',
+ ],
+ () => this._updateAlphaAndSet(),
+ ],
+ [
+ SETTINGS,
+ [
+ 'changed::trans-use-custom-gradient',
+ 'changed::trans-gradient-top-color',
+ 'changed::trans-gradient-bottom-color',
+ 'changed::trans-gradient-top-opacity',
+ 'changed::trans-gradient-bottom-opacity',
+ ],
+ () => this._updateGradientAndSet(),
+ ],
+ [
+ SETTINGS,
+ [
+ 'changed::trans-dynamic-behavior',
+ 'changed::trans-use-dynamic-opacity',
+ 'changed::trans-dynamic-distance',
+ ],
+ () => this._updateProximityWatch(),
+ ],
+ [
+ SETTINGS,
+ 'changed::trans-dynamic-anim-time',
+ () => this._updateAnimationDuration(),
+ ],
+ )
+ }
+
+ _updateProximityWatch() {
+ this._proximityManager.removeWatch(this._proximityWatchId)
+
+ if (SETTINGS.get_boolean('trans-use-dynamic-opacity')) {
+ let isVertical = this._dtpPanel.checkIfVertical()
+ let threshold = SETTINGS.get_int('trans-dynamic-distance')
+
+ this._windowOverlap = false
+ this._updateAlphaAndSet()
+
+ this._proximityWatchId = this._proximityManager.createWatch(
+ this._dtpPanel.panelBox.get_parent(),
+ this._dtpPanel.monitor.index,
+ Proximity.Mode[SETTINGS.get_string('trans-dynamic-behavior')],
+ isVertical ? threshold : 0,
+ isVertical ? 0 : threshold,
+ (overlap) => {
+ this._windowOverlap = overlap
+ this._updateAlphaAndSet()
+ },
+ )
+ }
+ }
+
+ _updateAnimationDuration() {
+ this.animationDuration =
+ SETTINGS.get_int('trans-dynamic-anim-time') * 0.001 + 's;'
+ }
+
+ _updateAllAndSet() {
+ let themeBackground = this._getThemeBackground(true)
+
+ this._updateColor(themeBackground)
+ this._updateAlpha(themeBackground)
+ this._updateComplementaryStyles()
+ this._updateGradient()
+ this._setBackground()
+ this._setGradient()
+ }
+
+ _updateColorAndSet() {
+ this._updateColor()
+ this._setBackground()
+ }
+
+ _updateAlphaAndSet() {
+ this._updateAlpha()
+ this._setBackground()
+ }
+
+ _updateGradientAndSet() {
+ this._updateGradient()
+ this._setGradient()
+ }
+
+ _updateComplementaryStyles() {
+ let panelThemeNode = this._dtpPanel.panel.get_theme_node()
+
+ this._complementaryStyles =
+ 'border-radius: ' + panelThemeNode.get_border_radius(0) + 'px;'
+ }
+
+ _updateColor(themeBackground) {
+ this.backgroundColorRgb = SETTINGS.get_boolean('trans-use-custom-bg')
+ ? SETTINGS.get_string('trans-bg-color')
+ : themeBackground || this._getThemeBackground()
+ }
+
+ _updateAlpha(themeBackground) {
+ if (
+ this._windowOverlap &&
+ !Main.overview.visibleTarget &&
+ SETTINGS.get_boolean('trans-use-dynamic-opacity')
+ ) {
+ this.alpha = SETTINGS.get_double('trans-dynamic-anim-target')
+ } else {
+ this.alpha = SETTINGS.get_boolean('trans-use-custom-opacity')
+ ? SETTINGS.get_double('trans-panel-opacity')
+ : (themeBackground || this._getThemeBackground()).alpha * 0.003921569 // 1 / 255 = 0.003921569
+ }
+ }
+
+ _updateGradient() {
+ this._gradientStyle = ''
+
+ if (SETTINGS.get_boolean('trans-use-custom-gradient')) {
+ this._gradientStyle +=
+ 'background-gradient-direction: ' +
+ (this._dtpPanel.checkIfVertical() ? 'horizontal;' : 'vertical;') +
+ 'background-gradient-start: ' +
+ Utils.getrgbaColor(
+ SETTINGS.get_string('trans-gradient-top-color'),
+ SETTINGS.get_double('trans-gradient-top-opacity'),
+ ) +
+ 'background-gradient-end: ' +
+ Utils.getrgbaColor(
+ SETTINGS.get_string('trans-gradient-bottom-color'),
+ SETTINGS.get_double('trans-gradient-bottom-opacity'),
+ )
+ }
+ }
+
+ _setBackground() {
+ this.currentBackgroundColor = Utils.getrgbaColor(
+ this.backgroundColorRgb,
+ this.alpha,
+ )
+
+ let transition = 'transition-duration:' + this.animationDuration
+
+ this._dtpPanel.set_style(
+ 'background-color: ' +
+ this.currentBackgroundColor +
+ transition +
+ this._complementaryStyles,
+ )
+ }
+
+ _setGradient() {
+ this._dtpPanel.panel.set_style(
+ 'background: none; ' +
+ 'border-image: none; ' +
+ 'background-image: none; ' +
+ this._gradientStyle +
+ 'transition-duration:' +
+ this.animationDuration,
+ )
+ }
+
+ _getThemeBackground(reload) {
+ if (reload || !this._themeBackground) {
+ let fakePanel = new St.Bin({ name: 'panel' })
+ Main.uiGroup.add_child(fakePanel)
+ let fakeTheme = fakePanel.get_theme_node()
+ this._themeBackground =
+ this._getBackgroundImageColor(fakeTheme) ||
+ fakeTheme.get_background_color()
+ Main.uiGroup.remove_child(fakePanel)
}
- destroy() {
- this._signalsHandler.destroy();
- this._proximityManager.removeWatch(this._proximityWatchId);
+ return this._themeBackground
+ }
- this._dtpPanel.panel.set_style(this._initialPanelStyle);
- }
+ _getBackgroundImageColor(theme) {
+ let bg = null
- updateExternalStyle() {
- this._updateComplementaryStyles();
- this._setBackground();
- }
+ try {
+ let imageFile =
+ theme.get_background_image() || theme.get_border_image().get_file()
- _bindSignals() {
- this._signalsHandler.add(
- [
- Utils.getStageTheme(),
- 'changed',
- () => this._updateAllAndSet()
- ],
- [
- Main.overview,
- [
- 'showing',
- 'hiding'
- ],
- () => this._updateAlphaAndSet()
- ],
- [
- SETTINGS,
- [
- 'changed::trans-use-custom-bg',
- 'changed::trans-bg-color'
- ],
- () => this._updateColorAndSet()
- ],
- [
- SETTINGS,
- [
- 'changed::trans-use-custom-opacity',
- 'changed::trans-panel-opacity',
- 'changed::trans-bg-color',
- 'changed::trans-dynamic-anim-target',
- 'changed::trans-use-dynamic-opacity'
- ],
- () => this._updateAlphaAndSet()
- ],
- [
- SETTINGS,
- [
- 'changed::trans-use-custom-gradient',
- 'changed::trans-gradient-top-color',
- 'changed::trans-gradient-bottom-color',
- 'changed::trans-gradient-top-opacity',
- 'changed::trans-gradient-bottom-opacity'
- ],
- () => this._updateGradientAndSet()
- ],
- [
- SETTINGS,
- [
- 'changed::trans-dynamic-behavior',
- 'changed::trans-use-dynamic-opacity',
- 'changed::trans-dynamic-distance'
- ],
- () => this._updateProximityWatch()
- ],
- [
- SETTINGS,
- 'changed::trans-dynamic-anim-time',
- () => this._updateAnimationDuration()
- ]
- );
- }
+ if (imageFile) {
+ let imageBuf = GdkPixbuf.Pixbuf.new_from_file(imageFile.get_path())
+ let pixels = imageBuf.get_pixels()
- _updateProximityWatch() {
- this._proximityManager.removeWatch(this._proximityWatchId);
-
- if (SETTINGS.get_boolean('trans-use-dynamic-opacity')) {
- let isVertical = this._dtpPanel.checkIfVertical();
- let threshold = SETTINGS.get_int('trans-dynamic-distance');
-
- this._windowOverlap = false;
- this._updateAlphaAndSet()
-
- this._proximityWatchId = this._proximityManager.createWatch(
- this._dtpPanel.panelBox.get_parent(),
- this._dtpPanel.monitor.index,
- Proximity.Mode[SETTINGS.get_string('trans-dynamic-behavior')],
- isVertical ? threshold : 0,
- isVertical ? 0 : threshold,
- overlap => {
- this._windowOverlap = overlap;
- this._updateAlphaAndSet();
- }
- );
+ bg = {
+ red: pixels[0],
+ green: pixels[1],
+ blue: pixels[2],
+ alpha: pixels[3],
}
- }
+ }
+ } catch (error) {}
- _updateAnimationDuration() {
- this.animationDuration = (SETTINGS.get_int('trans-dynamic-anim-time') * 0.001) + 's;';
- }
-
- _updateAllAndSet() {
- let themeBackground = this._getThemeBackground(true);
-
- this._updateColor(themeBackground);
- this._updateAlpha(themeBackground);
- this._updateComplementaryStyles();
- this._updateGradient();
- this._setBackground();
- this._setGradient();
- }
-
- _updateColorAndSet() {
- this._updateColor();
- this._setBackground();
- }
-
- _updateAlphaAndSet() {
- this._updateAlpha();
- this._setBackground();
- }
-
- _updateGradientAndSet() {
- this._updateGradient();
- this._setGradient();
- }
-
- _updateComplementaryStyles() {
- let panelThemeNode = this._dtpPanel.panel.get_theme_node();
-
- this._complementaryStyles = 'border-radius: ' + panelThemeNode.get_border_radius(0) + 'px;';
- }
-
- _updateColor(themeBackground) {
- this.backgroundColorRgb = SETTINGS.get_boolean('trans-use-custom-bg') ?
- SETTINGS.get_string('trans-bg-color') :
- (themeBackground || this._getThemeBackground());
- }
-
- _updateAlpha(themeBackground) {
- if (this._windowOverlap && !Main.overview.visibleTarget && SETTINGS.get_boolean('trans-use-dynamic-opacity')) {
- this.alpha = SETTINGS.get_double('trans-dynamic-anim-target');
- } else {
- this.alpha = SETTINGS.get_boolean('trans-use-custom-opacity') ?
- SETTINGS.get_double('trans-panel-opacity') :
- (themeBackground || this._getThemeBackground()).alpha * 0.003921569; // 1 / 255 = 0.003921569
- }
- }
-
- _updateGradient() {
- this._gradientStyle = '';
-
- if (SETTINGS.get_boolean('trans-use-custom-gradient')) {
- this._gradientStyle += 'background-gradient-direction: ' + (this._dtpPanel.checkIfVertical() ? 'horizontal;' : 'vertical;') +
- 'background-gradient-start: ' + Utils.getrgbaColor(SETTINGS.get_string('trans-gradient-top-color'),
- SETTINGS.get_double('trans-gradient-top-opacity')) +
- 'background-gradient-end: ' + Utils.getrgbaColor(SETTINGS.get_string('trans-gradient-bottom-color'),
- SETTINGS.get_double('trans-gradient-bottom-opacity'));
- }
- }
-
- _setBackground() {
- this.currentBackgroundColor = Utils.getrgbaColor(this.backgroundColorRgb, this.alpha);
-
- let transition = 'transition-duration:' + this.animationDuration;
-
- this._dtpPanel.set_style('background-color: ' + this.currentBackgroundColor + transition + this._complementaryStyles);
- }
-
- _setGradient() {
- this._dtpPanel.panel.set_style(
- 'background: none; ' +
- 'border-image: none; ' +
- 'background-image: none; ' +
- this._gradientStyle +
- 'transition-duration:' + this.animationDuration
- );
- }
-
- _getThemeBackground(reload) {
- if (reload || !this._themeBackground) {
- let fakePanel = new St.Bin({ name: 'panel' });
- Main.uiGroup.add_child(fakePanel);
- let fakeTheme = fakePanel.get_theme_node()
- this._themeBackground = this._getBackgroundImageColor(fakeTheme) || fakeTheme.get_background_color();
- Main.uiGroup.remove_child(fakePanel);
- }
-
- return this._themeBackground;
- }
-
- _getBackgroundImageColor(theme) {
- let bg = null;
-
- try {
- let imageFile = theme.get_background_image() || theme.get_border_image().get_file();
-
- if (imageFile) {
- let imageBuf = GdkPixbuf.Pixbuf.new_from_file(imageFile.get_path());
- let pixels = imageBuf.get_pixels();
-
- bg = { red: pixels[0], green: pixels[1], blue: pixels[2], alpha: pixels[3] };
- }
- } catch (error) {}
-
- return bg;
- }
+ return bg
+ }
}
diff --git a/utils.js b/utils.js
index df67ad9..b7bd090 100644
--- a/utils.js
+++ b/utils.js
@@ -21,869 +21,894 @@
* Some code was also adapted from the upstream Gnome Shell source code.
*/
-import Clutter from 'gi://Clutter';
-import Cogl from 'gi://Cogl';
-import GdkPixbuf from 'gi://GdkPixbuf';
-import Gio from 'gi://Gio';
-import GLib from 'gi://GLib';
-import Graphene from 'gi://Graphene';
-import Meta from 'gi://Meta';
-import Shell from 'gi://Shell';
-import St from 'gi://St';
-import * as Util from 'resource:///org/gnome/shell/misc/util.js';
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
-import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js';
+import Clutter from 'gi://Clutter'
+import Cogl from 'gi://Cogl'
+import GdkPixbuf from 'gi://GdkPixbuf'
+import Gio from 'gi://Gio'
+import GLib from 'gi://GLib'
+import Graphene from 'gi://Graphene'
+import Meta from 'gi://Meta'
+import Shell from 'gi://Shell'
+import St from 'gi://St'
+import * as Util from 'resource:///org/gnome/shell/misc/util.js'
+import * as Main from 'resource:///org/gnome/shell/ui/main.js'
+import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'
-const SCROLL_TIME = Util.SCROLL_TIME / (Util.SCROLL_TIME > 1 ? 1000 : 1);
+const SCROLL_TIME = Util.SCROLL_TIME / (Util.SCROLL_TIME > 1 ? 1000 : 1)
// simplify global signals and function injections handling
// abstract class
-export const BasicHandler = class {
+export const BasicHandler = class {
+ constructor() {
+ this._storage = new Object()
+ }
- constructor() {
- this._storage = new Object();
+ add(/*unlimited 3-long array arguments*/) {
+ // convert arguments object to array, concatenate with generic
+ let args = [].concat('generic', [].slice.call(arguments))
+ // call addWithLabel with ags as if they were passed arguments
+ this.addWithLabel.apply(this, args)
+ }
+
+ destroy() {
+ for (let label in this._storage) this.removeWithLabel(label)
+ }
+
+ addWithLabel(label /* plus unlimited 3-long array arguments*/) {
+ if (this._storage[label] == undefined) this._storage[label] = new Array()
+
+ // skip first element of the arguments
+ for (let i = 1; i < arguments.length; i++) {
+ let item = this._storage[label]
+ let handlers = this._create(arguments[i])
+
+ for (let j = 0, l = handlers.length; j < l; ++j) {
+ item.push(handlers[j])
+ }
}
+ }
- add(/*unlimited 3-long array arguments*/){
+ removeWithLabel(label) {
+ if (this._storage[label]) {
+ for (let i = 0; i < this._storage[label].length; i++) {
+ this._remove(this._storage[label][i])
+ }
- // convert arguments object to array, concatenate with generic
- let args = [].concat('generic', [].slice.call(arguments));
- // call addWithLabel with ags as if they were passed arguments
- this.addWithLabel.apply(this, args);
+ delete this._storage[label]
}
+ }
- destroy() {
- for( let label in this._storage )
- this.removeWithLabel(label);
- }
+ /* Virtual methods to be implemented by subclass */
+ // create single element to be stored in the storage structure
+ _create(item) {
+ throw new Error('no implementation of _create in ' + this)
+ }
- addWithLabel( label /* plus unlimited 3-long array arguments*/) {
-
- if(this._storage[label] == undefined)
- this._storage[label] = new Array();
-
- // skip first element of the arguments
- for( let i = 1; i < arguments.length; i++ ) {
- let item = this._storage[label];
- let handlers = this._create(arguments[i]);
-
- for (let j = 0, l = handlers.length; j < l; ++j) {
- item.push(handlers[j]);
- }
- }
-
- }
-
- removeWithLabel(label){
-
- if(this._storage[label]) {
- for( let i = 0; i < this._storage[label].length; i++ ) {
- this._remove(this._storage[label][i]);
- }
-
- delete this._storage[label];
- }
- }
-
- /* Virtual methods to be implemented by subclass */
- // create single element to be stored in the storage structure
- _create(item){
- throw new Error('no implementation of _create in ' + this);
- }
-
- // correctly delete single element
- _remove(item){
- throw new Error('no implementation of _remove in ' + this);
- }
+ // correctly delete single element
+ _remove(item) {
+ throw new Error('no implementation of _remove in ' + this)
+ }
}
// Manage global signals
export const GlobalSignalsHandler = class extends BasicHandler {
+ _create(item) {
+ let handlers = []
- _create(item) {
- let handlers = [];
+ item[1] = [].concat(item[1])
- item[1] = [].concat(item[1]);
+ for (let i = 0, l = item[1].length; i < l; ++i) {
+ let object = item[0]
+ let event = item[1][i]
+ let callback = item[2]
+ try {
+ let id = object.connect(event, callback)
- for (let i = 0, l = item[1].length; i < l; ++i) {
- let object = item[0];
- let event = item[1][i];
- let callback = item[2]
- try {
- let id = object.connect(event, callback);
-
- handlers.push([object, id]);
- } catch (e)
- {
-
- }
- }
-
- return handlers;
+ handlers.push([object, id])
+ } catch (e) {}
}
- _remove(item){
- item[0].disconnect(item[1]);
- }
-};
+ return handlers
+ }
+
+ _remove(item) {
+ item[0].disconnect(item[1])
+ }
+}
/**
* Manage function injection: both instances and prototype can be overridden
* and restored
*/
export const InjectionsHandler = class extends BasicHandler {
+ _create(item) {
+ let object = item[0]
+ let name = item[1]
+ let injectedFunction = item[2]
+ let original = object[name]
- _create(item) {
- let object = item[0];
- let name = item[1];
- let injectedFunction = item[2];
- let original = object[name];
+ object[name] = injectedFunction
+ return [[object, name, injectedFunction, original]]
+ }
- object[name] = injectedFunction;
- return [[object, name, injectedFunction, original]];
- }
-
- _remove(item) {
- let object = item[0];
- let name = item[1];
- let original = item[3];
- object[name] = original;
- }
-};
+ _remove(item) {
+ let object = item[0]
+ let name = item[1]
+ let original = item[3]
+ object[name] = original
+ }
+}
/**
* Manage timeouts: the added timeouts have their id reset on completion
*/
export const TimeoutsHandler = class extends BasicHandler {
+ _create(item) {
+ let name = item[0]
+ let delay = item[1]
+ let timeoutHandler = item[2]
- _create(item) {
- let name = item[0];
- let delay = item[1];
- let timeoutHandler = item[2];
+ this._remove(item)
- this._remove(item);
+ this[name] = GLib.timeout_add(GLib.PRIORITY_DEFAULT, delay, () => {
+ this[name] = 0
+ timeoutHandler()
- this[name] = GLib.timeout_add(GLib.PRIORITY_DEFAULT, delay, () => {
- this[name] = 0;
- timeoutHandler();
+ return GLib.SOURCE_REMOVE
+ })
- return GLib.SOURCE_REMOVE;
- });
+ return [[name]]
+ }
- return [[name]];
+ remove(name) {
+ this._remove([name])
+ }
+
+ _remove(item) {
+ let name = item[0]
+
+ if (this[name]) {
+ GLib.Source.remove(this[name])
+ this[name] = 0
}
+ }
- remove(name) {
- this._remove([name])
- }
-
- _remove(item) {
- let name = item[0];
-
- if (this[name]) {
- GLib.Source.remove(this[name]);
- this[name] = 0;
- }
- }
-
- getId(name) {
- return this[name] ? this[name] : 0;
- }
-};
+ getId(name) {
+ return this[name] ? this[name] : 0
+ }
+}
// This is wrapper to maintain compatibility with GNOME-Shell 3.30+ as well as
// previous versions.
export const DisplayWrapper = {
- getScreen() {
- return global.screen || global.display;
- },
+ getScreen() {
+ return global.screen || global.display
+ },
- getWorkspaceManager() {
- return global.screen || global.workspace_manager;
- },
+ getWorkspaceManager() {
+ return global.screen || global.workspace_manager
+ },
- getMonitorManager() {
- return global.screen || global.backend.get_monitor_manager();
- }
-};
+ getMonitorManager() {
+ return global.screen || global.backend.get_monitor_manager()
+ },
+}
let unredirectEnabled = true
export const setDisplayUnredirect = (enable) => {
- if (enable && !unredirectEnabled)
- Meta.enable_unredirect_for_display(global.display);
- else if (!enable && unredirectEnabled)
- Meta.disable_unredirect_for_display(global.display);
+ if (enable && !unredirectEnabled)
+ Meta.enable_unredirect_for_display(global.display)
+ else if (!enable && unredirectEnabled)
+ Meta.disable_unredirect_for_display(global.display)
- unredirectEnabled = enable;
-};
-
-export const getSystemMenuInfo = function() {
- return {
- name: 'quickSettings',
- constructor: Main.panel.statusArea.quickSettings.constructor
- };
+ unredirectEnabled = enable
}
-export const getCurrentWorkspace = function() {
- return DisplayWrapper.getWorkspaceManager().get_active_workspace();
-};
+export const getSystemMenuInfo = function () {
+ return {
+ name: 'quickSettings',
+ constructor: Main.panel.statusArea.quickSettings.constructor,
+ }
+}
-export const getWorkspaceByIndex = function(index) {
- return DisplayWrapper.getWorkspaceManager().get_workspace_by_index(index);
-};
+export const getCurrentWorkspace = function () {
+ return DisplayWrapper.getWorkspaceManager().get_active_workspace()
+}
-export const getWorkspaceCount = function() {
- return DisplayWrapper.getWorkspaceManager().n_workspaces;
-};
+export const getWorkspaceByIndex = function (index) {
+ return DisplayWrapper.getWorkspaceManager().get_workspace_by_index(index)
+}
-export const getStageTheme = function() {
- return St.ThemeContext.get_for_stage(global.stage);
-};
+export const getWorkspaceCount = function () {
+ return DisplayWrapper.getWorkspaceManager().n_workspaces
+}
-export const getScaleFactor = function() {
- return getStageTheme().scale_factor || 1;
-};
+export const getStageTheme = function () {
+ return St.ThemeContext.get_for_stage(global.stage)
+}
-export const findIndex = function(array, predicate) {
- if (array) {
- if (Array.prototype.findIndex) {
- return array.findIndex(predicate);
- }
+export const getScaleFactor = function () {
+ return getStageTheme().scale_factor || 1
+}
- for (let i = 0, l = array.length; i < l; ++i) {
- if (predicate(array[i])) {
- return i;
- }
- }
+export const findIndex = function (array, predicate) {
+ if (array) {
+ if (Array.prototype.findIndex) {
+ return array.findIndex(predicate)
}
- return -1;
-};
-
-export const find = function(array, predicate) {
- let index = findIndex(array, predicate);
-
- if (index > -1) {
- return array[index];
+ for (let i = 0, l = array.length; i < l; ++i) {
+ if (predicate(array[i])) {
+ return i
+ }
}
-};
+ }
-export const mergeObjects = function(main, bck) {
- for (const prop in bck) {
- if (!main.hasOwnProperty(prop) && bck.hasOwnProperty(prop)) {
- main[prop] = bck[prop];
- }
+ return -1
+}
+
+export const find = function (array, predicate) {
+ let index = findIndex(array, predicate)
+
+ if (index > -1) {
+ return array[index]
+ }
+}
+
+export const mergeObjects = function (main, bck) {
+ for (const prop in bck) {
+ if (!main.hasOwnProperty(prop) && bck.hasOwnProperty(prop)) {
+ main[prop] = bck[prop]
}
+ }
- return main;
-};
+ return main
+}
export const getTrackedActorData = (actor) => {
- let trackedIndex = Main.layoutManager._findActor(actor);
-
- if (trackedIndex >= 0)
- return Main.layoutManager._trackedActors[trackedIndex]
+ let trackedIndex = Main.layoutManager._findActor(actor)
+
+ if (trackedIndex >= 0) return Main.layoutManager._trackedActors[trackedIndex]
}
-export const getTransformedAllocation = function(actor) {
- let extents = actor.get_transformed_extents();
- let topLeft = extents.get_top_left();
- let bottomRight = extents.get_bottom_right();
+export const getTransformedAllocation = function (actor) {
+ let extents = actor.get_transformed_extents()
+ let topLeft = extents.get_top_left()
+ let bottomRight = extents.get_bottom_right()
- return { x1: topLeft.x, x2: bottomRight.x, y1: topLeft.y, y2: bottomRight.y };
-};
-
-export const setClip = function(actor, x, y, width, height) {
- actor.set_clip(0, 0, width, height);
- actor.set_position(x, y);
- actor.set_size(width, height);
-};
-
-export const addKeybinding = function(key, settings, handler, modes) {
- if (!Main.wm._allowedKeybindings[key]) {
- Main.wm.addKeybinding(
- key,
- settings,
- Meta.KeyBindingFlags.NONE,
- modes || (Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW),
- handler
- );
- }
-};
-
-export const removeKeybinding = function(key) {
- if (Main.wm._allowedKeybindings[key]) {
- Main.wm.removeKeybinding(key);
- }
-};
-
-export const getrgbColor = function(color) {
- color = typeof color === 'string' ? ColorUtils.color_from_string(color)[1] : color;
-
- return { red: color.red, green: color.green, blue: color.blue };
-};
-
-export const getrgbaColor = function(color, alpha, offset) {
- if (alpha <= 0) {
- return 'transparent; ';
- }
-
- let rgb = getrgbColor(color);
-
- if (offset) {
- ['red', 'green', 'blue'].forEach(k => {
- rgb[k] = Math.min(255, Math.max(0, rgb[k] + offset));
-
- if (rgb[k] == color[k]) {
- rgb[k] = Math.min(255, Math.max(0, rgb[k] - offset));
- }
- });
- }
-
- return 'rgba(' + rgb.red + ',' + rgb.green + ',' + rgb.blue + ',' + (Math.floor(alpha * 100) * 0.01) + '); ' ;
-};
-
-export const checkIfColorIsBright = function(color) {
- let rgb = getrgbColor(color);
- let brightness = 0.2126 * rgb.red + 0.7152 * rgb.green + 0.0722 * rgb.blue;
-
- return brightness > 128;
-};
-
-export const getMouseScrollDirection = function(event) {
- let direction;
-
- switch (event.get_scroll_direction()) {
- case Clutter.ScrollDirection.UP:
- case Clutter.ScrollDirection.LEFT:
- direction = 'up';
- break;
- case Clutter.ScrollDirection.DOWN:
- case Clutter.ScrollDirection.RIGHT:
- direction = 'down';
- break;
- }
-
- return direction;
-};
-
-export const checkIfWindowHasTransient = function(window) {
- let hasTransient;
-
- window.foreach_transient(t => !(hasTransient = true));
-
- return hasTransient;
-};
-
-export const activateSiblingWindow = function(windows, direction, startWindow) {
- let windowIndex = windows.indexOf(global.display.focus_window);
- let nextWindowIndex = windowIndex < 0 ?
- startWindow ? windows.indexOf(startWindow) : 0 :
- windowIndex + (direction == 'up' ? -1 : 1);
-
- if (nextWindowIndex == windows.length) {
- nextWindowIndex = 0;
- } else if (nextWindowIndex < 0) {
- nextWindowIndex = windows.length - 1;
- }
-
- if (windowIndex != nextWindowIndex) {
- Main.activateWindow(windows[nextWindowIndex]);
- }
-};
-
-export const animateWindowOpacity = function(window, tweenOpts) {
- //there currently is a mutter bug with the windowactor opacity, starting with 3.34
- //https://gitlab.gnome.org/GNOME/mutter/issues/836
-
- //since 3.36, a workaround is to use the windowactor's child for the fade animation
- //this leaves a "shadow" on the desktop, so the windowactor needs to be hidden
- //when the animation is complete
- let visible = tweenOpts.opacity > 0;
- let windowActor = window;
- let initialOpacity = window.opacity;
-
- window = windowActor.get_first_child() || windowActor;
-
- if (!windowActor.visible && visible) {
- window.opacity = 0;
- windowActor.visible = visible;
- tweenOpts.opacity = Math.min(initialOpacity, tweenOpts.opacity);
- }
-
- if (!visible) {
- tweenOpts.onComplete = () => {
- windowActor.visible = visible;
- window.opacity = initialOpacity;
- };
- }
-
- animate(window, tweenOpts);
-};
-
-export const animate = function(actor, options) {
- //the original animations used Tweener instead of Clutter animations, so we
- //use "time" and "delay" properties defined in seconds, as opposed to Clutter
- //animations "duration" and "delay" which are defined in milliseconds
- if (options.delay) {
- options.delay = options.delay * 1000;
- }
-
- options.duration = options.time * 1000;
- delete options.time;
-
- if (options.transition) {
- //map Tweener easing equations to Clutter animation modes
- options.mode = {
- 'easeInCubic': Clutter.AnimationMode.EASE_IN_CUBIC,
- 'easeInOutCubic': Clutter.AnimationMode.EASE_IN_OUT_CUBIC,
- 'easeInOutQuad': Clutter.AnimationMode.EASE_IN_OUT_QUAD,
- 'easeOutQuad': Clutter.AnimationMode.EASE_OUT_QUAD
- }[options.transition] || Clutter.AnimationMode.LINEAR;
-
- delete options.transition;
- }
-
- let params = [options];
-
- if ('value' in options && actor instanceof St.Adjustment) {
- params.unshift(options.value);
- delete options.value;
- }
-
- actor.ease.apply(actor, params);
+ return { x1: topLeft.x, x2: bottomRight.x, y1: topLeft.y, y2: bottomRight.y }
}
-export const isAnimating = function(actor, prop) {
- return !!actor.get_transition(prop);
+export const setClip = function (actor, x, y, width, height) {
+ actor.set_clip(0, 0, width, height)
+ actor.set_position(x, y)
+ actor.set_size(width, height)
}
-export const stopAnimations = function(actor) {
- actor.remove_all_transitions();
+export const addKeybinding = function (key, settings, handler, modes) {
+ if (!Main.wm._allowedKeybindings[key]) {
+ Main.wm.addKeybinding(
+ key,
+ settings,
+ Meta.KeyBindingFlags.NONE,
+ modes || Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW,
+ handler,
+ )
+ }
}
-export const getIndicators = function(delegate) {
- if (delegate instanceof St.BoxLayout) {
- return delegate;
+export const removeKeybinding = function (key) {
+ if (Main.wm._allowedKeybindings[key]) {
+ Main.wm.removeKeybinding(key)
+ }
+}
+
+export const getrgbColor = function (color) {
+ color =
+ typeof color === 'string' ? ColorUtils.color_from_string(color)[1] : color
+
+ return { red: color.red, green: color.green, blue: color.blue }
+}
+
+export const getrgbaColor = function (color, alpha, offset) {
+ if (alpha <= 0) {
+ return 'transparent; '
+ }
+
+ let rgb = getrgbColor(color)
+
+ if (offset) {
+ ;['red', 'green', 'blue'].forEach((k) => {
+ rgb[k] = Math.min(255, Math.max(0, rgb[k] + offset))
+
+ if (rgb[k] == color[k]) {
+ rgb[k] = Math.min(255, Math.max(0, rgb[k] - offset))
+ }
+ })
+ }
+
+ return (
+ 'rgba(' +
+ rgb.red +
+ ',' +
+ rgb.green +
+ ',' +
+ rgb.blue +
+ ',' +
+ Math.floor(alpha * 100) * 0.01 +
+ '); '
+ )
+}
+
+export const checkIfColorIsBright = function (color) {
+ let rgb = getrgbColor(color)
+ let brightness = 0.2126 * rgb.red + 0.7152 * rgb.green + 0.0722 * rgb.blue
+
+ return brightness > 128
+}
+
+export const getMouseScrollDirection = function (event) {
+ let direction
+
+ switch (event.get_scroll_direction()) {
+ case Clutter.ScrollDirection.UP:
+ case Clutter.ScrollDirection.LEFT:
+ direction = 'up'
+ break
+ case Clutter.ScrollDirection.DOWN:
+ case Clutter.ScrollDirection.RIGHT:
+ direction = 'down'
+ break
+ }
+
+ return direction
+}
+
+export const checkIfWindowHasTransient = function (window) {
+ let hasTransient
+
+ window.foreach_transient((t) => !(hasTransient = true))
+
+ return hasTransient
+}
+
+export const activateSiblingWindow = function (
+ windows,
+ direction,
+ startWindow,
+) {
+ let windowIndex = windows.indexOf(global.display.focus_window)
+ let nextWindowIndex =
+ windowIndex < 0
+ ? startWindow
+ ? windows.indexOf(startWindow)
+ : 0
+ : windowIndex + (direction == 'up' ? -1 : 1)
+
+ if (nextWindowIndex == windows.length) {
+ nextWindowIndex = 0
+ } else if (nextWindowIndex < 0) {
+ nextWindowIndex = windows.length - 1
+ }
+
+ if (windowIndex != nextWindowIndex) {
+ Main.activateWindow(windows[nextWindowIndex])
+ }
+}
+
+export const animateWindowOpacity = function (window, tweenOpts) {
+ //there currently is a mutter bug with the windowactor opacity, starting with 3.34
+ //https://gitlab.gnome.org/GNOME/mutter/issues/836
+
+ //since 3.36, a workaround is to use the windowactor's child for the fade animation
+ //this leaves a "shadow" on the desktop, so the windowactor needs to be hidden
+ //when the animation is complete
+ let visible = tweenOpts.opacity > 0
+ let windowActor = window
+ let initialOpacity = window.opacity
+
+ window = windowActor.get_first_child() || windowActor
+
+ if (!windowActor.visible && visible) {
+ window.opacity = 0
+ windowActor.visible = visible
+ tweenOpts.opacity = Math.min(initialOpacity, tweenOpts.opacity)
+ }
+
+ if (!visible) {
+ tweenOpts.onComplete = () => {
+ windowActor.visible = visible
+ window.opacity = initialOpacity
+ }
+ }
+
+ animate(window, tweenOpts)
+}
+
+export const animate = function (actor, options) {
+ //the original animations used Tweener instead of Clutter animations, so we
+ //use "time" and "delay" properties defined in seconds, as opposed to Clutter
+ //animations "duration" and "delay" which are defined in milliseconds
+ if (options.delay) {
+ options.delay = options.delay * 1000
+ }
+
+ options.duration = options.time * 1000
+ delete options.time
+
+ if (options.transition) {
+ //map Tweener easing equations to Clutter animation modes
+ options.mode =
+ {
+ easeInCubic: Clutter.AnimationMode.EASE_IN_CUBIC,
+ easeInOutCubic: Clutter.AnimationMode.EASE_IN_OUT_CUBIC,
+ easeInOutQuad: Clutter.AnimationMode.EASE_IN_OUT_QUAD,
+ easeOutQuad: Clutter.AnimationMode.EASE_OUT_QUAD,
+ }[options.transition] || Clutter.AnimationMode.LINEAR
+
+ delete options.transition
+ }
+
+ let params = [options]
+
+ if ('value' in options && actor instanceof St.Adjustment) {
+ params.unshift(options.value)
+ delete options.value
+ }
+
+ actor.ease.apply(actor, params)
+}
+
+export const isAnimating = function (actor, prop) {
+ return !!actor.get_transition(prop)
+}
+
+export const stopAnimations = function (actor) {
+ actor.remove_all_transitions()
+}
+
+export const getIndicators = function (delegate) {
+ if (delegate instanceof St.BoxLayout) {
+ return delegate
+ }
+
+ return delegate.indicators
+}
+
+export const getPoint = function (coords) {
+ return new Graphene.Point(coords)
+}
+
+export const notify = function (text, iconName, action, isTransient) {
+ let source = new MessageTray.SystemNotificationSource()
+ let notification = new MessageTray.Notification(source, 'Dash to Panel', text)
+ let notifyFunc = source.showNotification || source.notify
+
+ if (iconName) {
+ source.createIcon = function () {
+ return new St.Icon({ icon_name: iconName })
+ }
+ }
+
+ if (action) {
+ if (!(action instanceof Array)) {
+ action = [action]
}
- return delegate.indicators;
+ action.forEach((a) => notification.addAction(a.text, a.func))
+ }
+
+ Main.messageTray.add(source)
+
+ notification.setTransient(isTransient)
+ notifyFunc.call(source, notification)
}
-export const getPoint = function(coords) {
- return new Graphene.Point(coords);
-}
-
-export const notify = function(text, iconName, action, isTransient) {
- let source = new MessageTray.SystemNotificationSource();
- let notification = new MessageTray.Notification(source, 'Dash to Panel', text);
- let notifyFunc = source.showNotification || source.notify;
-
- if (iconName) {
- source.createIcon = function() {
- return new St.Icon({ icon_name: iconName });
- };
- }
-
- if (action) {
- if (!(action instanceof Array)) {
- action = [action];
- }
-
- action.forEach(a => notification.addAction(a.text, a.func));
- }
-
- Main.messageTray.add(source);
-
- notification.setTransient(isTransient);
- notifyFunc.call(source, notification);
-};
-
/*
* This is a copy of the same function in utils.js, but also adjust horizontal scrolling
* and perform few further cheks on the current value to avoid changing the values when
* it would be clamp to the current one in any case.
* Return the amount of shift applied
-*/
-export const ensureActorVisibleInScrollView = function(scrollView, actor, fadeSize, onComplete) {
- const vadjustment = scrollView.vadjustment;
- const hadjustment = scrollView.hadjustment;
- let [vvalue, vlower, vupper, vstepIncrement, vpageIncrement, vpageSize] = vadjustment.get_values();
- let [hvalue, hlower, hupper, hstepIncrement, hpageIncrement, hpageSize] = hadjustment.get_values();
+ */
+export const ensureActorVisibleInScrollView = function (
+ scrollView,
+ actor,
+ fadeSize,
+ onComplete,
+) {
+ const vadjustment = scrollView.vadjustment
+ const hadjustment = scrollView.hadjustment
+ let [vvalue, vlower, vupper, vstepIncrement, vpageIncrement, vpageSize] =
+ vadjustment.get_values()
+ let [hvalue, hlower, hupper, hstepIncrement, hpageIncrement, hpageSize] =
+ hadjustment.get_values()
- let [hvalue0, vvalue0] = [hvalue, vvalue];
+ let [hvalue0, vvalue0] = [hvalue, vvalue]
- let voffset = fadeSize;
- let hoffset = fadeSize;
-
- let box = actor.get_allocation_box();
- let y1 = box.y1, y2 = box.y2, x1 = box.x1, x2 = box.x2;
+ let voffset = fadeSize
+ let hoffset = fadeSize
- let parent = actor.get_parent();
- while (parent != scrollView) {
- if (!parent)
- throw new Error("actor not in scroll view");
+ let box = actor.get_allocation_box()
+ let y1 = box.y1,
+ y2 = box.y2,
+ x1 = box.x1,
+ x2 = box.x2
- let box = parent.get_allocation_box();
- y1 += box.y1;
- y2 += box.y1;
- x1 += box.x1;
- x2 += box.x1;
- parent = parent.get_parent();
- }
+ let parent = actor.get_parent()
+ while (parent != scrollView) {
+ if (!parent) throw new Error('actor not in scroll view')
- if (y1 < vvalue + voffset)
- vvalue = Math.max(0, y1 - voffset);
- else if (vvalue < vupper - vpageSize && y2 > vvalue + vpageSize - voffset)
- vvalue = Math.min(vupper -vpageSize, y2 + voffset - vpageSize);
+ let box = parent.get_allocation_box()
+ y1 += box.y1
+ y2 += box.y1
+ x1 += box.x1
+ x2 += box.x1
+ parent = parent.get_parent()
+ }
- if (x1 < hvalue + hoffset)
- hvalue = Math.max(0, x1 - hoffset);
- else if (hvalue < hupper - hpageSize && x2 > hvalue + hpageSize - hoffset)
- hvalue = Math.min(hupper - hpageSize, x2 + hoffset - hpageSize);
+ if (y1 < vvalue + voffset) vvalue = Math.max(0, y1 - voffset)
+ else if (vvalue < vupper - vpageSize && y2 > vvalue + vpageSize - voffset)
+ vvalue = Math.min(vupper - vpageSize, y2 + voffset - vpageSize)
- let tweenOpts = {
- time: SCROLL_TIME,
- onComplete: onComplete || (() => {}),
- transition: 'easeOutQuad'
- };
+ if (x1 < hvalue + hoffset) hvalue = Math.max(0, x1 - hoffset)
+ else if (hvalue < hupper - hpageSize && x2 > hvalue + hpageSize - hoffset)
+ hvalue = Math.min(hupper - hpageSize, x2 + hoffset - hpageSize)
- if (vvalue !== vvalue0) {
- animate(vadjustment, mergeObjects(tweenOpts, { value: vvalue }));
- }
+ let tweenOpts = {
+ time: SCROLL_TIME,
+ onComplete: onComplete || (() => {}),
+ transition: 'easeOutQuad',
+ }
- if (hvalue !== hvalue0) {
- animate(hadjustment, mergeObjects(tweenOpts, { value: hvalue }));
- }
+ if (vvalue !== vvalue0) {
+ animate(vadjustment, mergeObjects(tweenOpts, { value: vvalue }))
+ }
- return [hvalue- hvalue0, vvalue - vvalue0];
+ if (hvalue !== hvalue0) {
+ animate(hadjustment, mergeObjects(tweenOpts, { value: hvalue }))
+ }
+
+ return [hvalue - hvalue0, vvalue - vvalue0]
}
-
+
/**
* ColorUtils is adapted from https://github.com/micheleg/dash-to-dock
*/
let colorNs = Clutter.Color ? Clutter : Cogl
export const ColorUtils = {
- color_from_string: colorNs.color_from_string,
- Color: colorNs.Color,
+ color_from_string: colorNs.color_from_string,
+ Color: colorNs.Color,
- colorLuminance(r, g, b, dlum) {
- // Darken or brighten color by a fraction dlum
- // Each rgb value is modified by the same fraction.
- // Return "#rrggbb" strin
+ colorLuminance(r, g, b, dlum) {
+ // Darken or brighten color by a fraction dlum
+ // Each rgb value is modified by the same fraction.
+ // Return "#rrggbb" strin
- let rgbString = '#';
+ let rgbString = '#'
- rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(r*(1+dlum), 0), 255)), 2);
- rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(g*(1+dlum), 0), 255)), 2);
- rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(b*(1+dlum), 0), 255)), 2);
+ rgbString += ColorUtils._decimalToHex(
+ Math.round(Math.min(Math.max(r * (1 + dlum), 0), 255)),
+ 2,
+ )
+ rgbString += ColorUtils._decimalToHex(
+ Math.round(Math.min(Math.max(g * (1 + dlum), 0), 255)),
+ 2,
+ )
+ rgbString += ColorUtils._decimalToHex(
+ Math.round(Math.min(Math.max(b * (1 + dlum), 0), 255)),
+ 2,
+ )
- return rgbString;
- },
+ return rgbString
+ },
- _decimalToHex(d, padding) {
- // Convert decimal to an hexadecimal string adding the desired padding
+ _decimalToHex(d, padding) {
+ // Convert decimal to an hexadecimal string adding the desired padding
- let hex = d.toString(16);
- while (hex.length < padding)
- hex = '0'+ hex;
- return hex;
- },
+ let hex = d.toString(16)
+ while (hex.length < padding) hex = '0' + hex
+ return hex
+ },
- HSVtoRGB(h, s, v) {
- // Convert hsv ([0-1, 0-1, 0-1]) to rgb ([0-255, 0-255, 0-255]).
- // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV
- // here with h = [0,1] instead of [0, 360]
- // Accept either (h,s,v) independently or {h:h, s:s, v:v} object.
- // Return {r:r, g:g, b:b} object.
+ HSVtoRGB(h, s, v) {
+ // Convert hsv ([0-1, 0-1, 0-1]) to rgb ([0-255, 0-255, 0-255]).
+ // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV
+ // here with h = [0,1] instead of [0, 360]
+ // Accept either (h,s,v) independently or {h:h, s:s, v:v} object.
+ // Return {r:r, g:g, b:b} object.
- if (arguments.length === 1) {
- s = h.s;
- v = h.v;
- h = h.h;
- }
-
- let r,g,b;
- let c = v*s;
- let h1 = h*6;
- let x = c*(1 - Math.abs(h1 % 2 - 1));
- let m = v - c;
-
- if (h1 <=1)
- r = c + m, g = x + m, b = m;
- else if (h1 <=2)
- r = x + m, g = c + m, b = m;
- else if (h1 <=3)
- r = m, g = c + m, b = x + m;
- else if (h1 <=4)
- r = m, g = x + m, b = c + m;
- else if (h1 <=5)
- r = x + m, g = m, b = c + m;
- else
- r = c + m, g = m, b = x + m;
-
- return {
- r: Math.round(r * 255),
- g: Math.round(g * 255),
- b: Math.round(b * 255)
- };
- },
-
- RGBtoHSV(r, g, b) {
- // Convert rgb ([0-255, 0-255, 0-255]) to hsv ([0-1, 0-1, 0-1]).
- // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV
- // here with h = [0,1] instead of [0, 360]
- // Accept either (r,g,b) independently or {r:r, g:g, b:b} object.
- // Return {h:h, s:s, v:v} object.
-
- if (arguments.length === 1) {
- r = r.r;
- g = r.g;
- b = r.b;
- }
-
- let h,s,v;
-
- let M = Math.max(r, g, b);
- let m = Math.min(r, g, b);
- let c = M - m;
-
- if (c == 0)
- h = 0;
- else if (M == r)
- h = ((g-b)/c) % 6;
- else if (M == g)
- h = (b-r)/c + 2;
- else
- h = (r-g)/c + 4;
-
- h = h/6;
- v = M/255;
- if (M !== 0)
- s = c/M;
- else
- s = 0;
-
- return {h: h, s: s, v: v};
+ if (arguments.length === 1) {
+ s = h.s
+ v = h.v
+ h = h.h
}
-};
+
+ let r, g, b
+ let c = v * s
+ let h1 = h * 6
+ let x = c * (1 - Math.abs((h1 % 2) - 1))
+ let m = v - c
+
+ if (h1 <= 1) (r = c + m), (g = x + m), (b = m)
+ else if (h1 <= 2) (r = x + m), (g = c + m), (b = m)
+ else if (h1 <= 3) (r = m), (g = c + m), (b = x + m)
+ else if (h1 <= 4) (r = m), (g = x + m), (b = c + m)
+ else if (h1 <= 5) (r = x + m), (g = m), (b = c + m)
+ else (r = c + m), (g = m), (b = x + m)
+
+ return {
+ r: Math.round(r * 255),
+ g: Math.round(g * 255),
+ b: Math.round(b * 255),
+ }
+ },
+
+ RGBtoHSV(r, g, b) {
+ // Convert rgb ([0-255, 0-255, 0-255]) to hsv ([0-1, 0-1, 0-1]).
+ // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV
+ // here with h = [0,1] instead of [0, 360]
+ // Accept either (r,g,b) independently or {r:r, g:g, b:b} object.
+ // Return {h:h, s:s, v:v} object.
+
+ if (arguments.length === 1) {
+ r = r.r
+ g = r.g
+ b = r.b
+ }
+
+ let h, s, v
+
+ let M = Math.max(r, g, b)
+ let m = Math.min(r, g, b)
+ let c = M - m
+
+ if (c == 0) h = 0
+ else if (M == r) h = ((g - b) / c) % 6
+ else if (M == g) h = (b - r) / c + 2
+ else h = (r - g) / c + 4
+
+ h = h / 6
+ v = M / 255
+ if (M !== 0) s = c / M
+ else s = 0
+
+ return { h: h, s: s, v: v }
+ },
+}
/**
* DominantColorExtractor is adapted from https://github.com/micheleg/dash-to-dock
*/
-let themeLoader = null;
-let iconCacheMap = new Map();
-const MAX_CACHED_ITEMS = 1000;
-const BATCH_SIZE_TO_DELETE = 50;
-const DOMINANT_COLOR_ICON_SIZE = 64;
+let themeLoader = null
+let iconCacheMap = new Map()
+const MAX_CACHED_ITEMS = 1000
+const BATCH_SIZE_TO_DELETE = 50
+const DOMINANT_COLOR_ICON_SIZE = 64
export const DominantColorExtractor = class {
+ constructor(app) {
+ this._app = app
+ }
- constructor(app){
- this._app = app;
+ /**
+ * Try to get the pixel buffer for the current icon, if not fail gracefully
+ */
+ _getIconPixBuf() {
+ let iconTexture = this._app.create_icon_texture(16)
+
+ if (themeLoader === null) {
+ themeLoader = new St.IconTheme()
}
- /**
- * Try to get the pixel buffer for the current icon, if not fail gracefully
- */
- _getIconPixBuf() {
- let iconTexture = this._app.create_icon_texture(16);
-
- if (themeLoader === null) {
- themeLoader = new St.IconTheme();
- }
-
- // Unable to load the icon texture, use fallback
- if (iconTexture instanceof St.Icon === false) {
- return null;
- }
-
- iconTexture = iconTexture.get_gicon();
-
- // Unable to load the icon texture, use fallback
- if (iconTexture === null) {
- return null;
- }
-
- if (iconTexture instanceof Gio.FileIcon) {
- // Use GdkPixBuf to load the pixel buffer from the provided file path
- return GdkPixbuf.Pixbuf.new_from_file(iconTexture.get_file().get_path());
- }
-
- // Get the pixel buffer from the icon theme
- if (iconTexture instanceof Gio.ThemedIcon) {
- let icon_info = themeLoader.lookup_icon(iconTexture.get_names()[0],
- DOMINANT_COLOR_ICON_SIZE, 0);
-
- if (icon_info !== null) {
- return icon_info.load_icon();
- }
- }
-
- return null;
+ // Unable to load the icon texture, use fallback
+ if (iconTexture instanceof St.Icon === false) {
+ return null
}
- /**
- * The backlight color choosing algorithm was mostly ported to javascript from the
- * Unity7 C++ source of Canonicals:
- * https://bazaar.launchpad.net/~unity-team/unity/trunk/view/head:/launcher/LauncherIcon.cpp
- * so it more or less works the same way.
- */
- _getColorPalette() {
- if (iconCacheMap.get(this._app.get_id())) {
- // We already know the answer
- return iconCacheMap.get(this._app.get_id());
- }
+ iconTexture = iconTexture.get_gicon()
- let pixBuf = this._getIconPixBuf();
- if (pixBuf == null)
- return null;
-
- let pixels = pixBuf.get_pixels(),
- offset = 0;
-
- let total = 0,
- rTotal = 0,
- gTotal = 0,
- bTotal = 0;
-
- let resample_y = 1,
- resample_x = 1;
-
- // Resampling of large icons
- // We resample icons larger than twice the desired size, as the resampling
- // to a size s
- // DOMINANT_COLOR_ICON_SIZE < s < 2*DOMINANT_COLOR_ICON_SIZE,
- // most of the case exactly DOMINANT_COLOR_ICON_SIZE as the icon size is tipycally
- // a multiple of it.
- let width = pixBuf.get_width();
- let height = pixBuf.get_height();
-
- // Resample
- if (height >= 2* DOMINANT_COLOR_ICON_SIZE)
- resample_y = Math.floor(height/DOMINANT_COLOR_ICON_SIZE);
-
- if (width >= 2* DOMINANT_COLOR_ICON_SIZE)
- resample_x = Math.floor(width/DOMINANT_COLOR_ICON_SIZE);
-
- if (resample_x !==1 || resample_y !== 1)
- pixels = this._resamplePixels(pixels, resample_x, resample_y);
-
- // computing the limit outside the for (where it would be repeated at each iteration)
- // for performance reasons
- let limit = pixels.length;
- for (let offset = 0; offset < limit; offset+=4) {
- let r = pixels[offset],
- g = pixels[offset + 1],
- b = pixels[offset + 2],
- a = pixels[offset + 3];
-
- let saturation = (Math.max(r,g, b) - Math.min(r,g, b));
- let relevance = 0.1 * 255 * 255 + 0.9 * a * saturation;
-
- rTotal += r * relevance;
- gTotal += g * relevance;
- bTotal += b * relevance;
-
- total += relevance;
- }
-
- total = total * 255;
-
- let r = rTotal / total,
- g = gTotal / total,
- b = bTotal / total;
-
- let hsv = ColorUtils.RGBtoHSV(r * 255, g * 255, b * 255);
-
- if (hsv.s > 0.15)
- hsv.s = 0.65;
- hsv.v = 0.90;
-
- let rgb = ColorUtils.HSVtoRGB(hsv.h, hsv.s, hsv.v);
-
- // Cache the result.
- let backgroundColor = {
- lighter: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, 0.2),
- original: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, 0),
- darker: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, -0.5)
- };
-
- if (iconCacheMap.size >= MAX_CACHED_ITEMS) {
- //delete oldest cached values (which are in order of insertions)
- let ctr=0;
- for (let key of iconCacheMap.keys()) {
- if (++ctr > BATCH_SIZE_TO_DELETE)
- break;
- iconCacheMap.delete(key);
- }
- }
-
- iconCacheMap.set(this._app.get_id(), backgroundColor);
-
- return backgroundColor;
+ // Unable to load the icon texture, use fallback
+ if (iconTexture === null) {
+ return null
}
- /**
- * Downsample large icons before scanning for the backlight color to
- * improve performance.
- *
- * @param pixBuf
- * @param pixels
- * @param resampleX
- * @param resampleY
- *
- * @return [];
- */
- _resamplePixels(pixels, resampleX, resampleY) {
- let resampledPixels = [];
- // computing the limit outside the for (where it would be repeated at each iteration)
- // for performance reasons
- let limit = pixels.length / (resampleX * resampleY) / 4;
- for (let i = 0; i < limit; i++) {
- let pixel = i * resampleX * resampleY;
-
- resampledPixels.push(pixels[pixel * 4]);
- resampledPixels.push(pixels[pixel * 4 + 1]);
- resampledPixels.push(pixels[pixel * 4 + 2]);
- resampledPixels.push(pixels[pixel * 4 + 3]);
- }
-
- return resampledPixels;
+ if (iconTexture instanceof Gio.FileIcon) {
+ // Use GdkPixBuf to load the pixel buffer from the provided file path
+ return GdkPixbuf.Pixbuf.new_from_file(iconTexture.get_file().get_path())
}
-};
+ // Get the pixel buffer from the icon theme
+ if (iconTexture instanceof Gio.ThemedIcon) {
+ let icon_info = themeLoader.lookup_icon(
+ iconTexture.get_names()[0],
+ DOMINANT_COLOR_ICON_SIZE,
+ 0,
+ )
-export const drawRoundedLine = function(cr, x, y, width, height, isRoundLeft, isRoundRight, stroke, fill) {
- if (height > width) {
- y += Math.floor((height - width) / 2.0);
- height = width;
+ if (icon_info !== null) {
+ return icon_info.load_icon()
+ }
}
-
- height = 2.0 * Math.floor(height / 2.0);
-
- const leftRadius = isRoundLeft ? height / 2.0 : 0.0;
- const rightRadius = isRoundRight ? height / 2.0 : 0.0;
-
- cr.moveTo(x + width - rightRadius, y);
- cr.lineTo(x + leftRadius, y);
- if (isRoundLeft)
- cr.arcNegative(x + leftRadius, y + leftRadius, leftRadius, -Math.PI/2, Math.PI/2);
- else
- cr.lineTo(x, y + height);
- cr.lineTo(x + width - rightRadius, y + height);
- if (isRoundRight)
- cr.arcNegative(x + width - rightRadius, y + rightRadius, rightRadius, Math.PI/2, -Math.PI/2);
- else
- cr.lineTo(x + width, y);
- cr.closePath();
-
- if (fill != null) {
- cr.setSource(fill);
- cr.fillPreserve();
+
+ return null
+ }
+
+ /**
+ * The backlight color choosing algorithm was mostly ported to javascript from the
+ * Unity7 C++ source of Canonicals:
+ * https://bazaar.launchpad.net/~unity-team/unity/trunk/view/head:/launcher/LauncherIcon.cpp
+ * so it more or less works the same way.
+ */
+ _getColorPalette() {
+ if (iconCacheMap.get(this._app.get_id())) {
+ // We already know the answer
+ return iconCacheMap.get(this._app.get_id())
}
- if (stroke != null)
- cr.setSource(stroke);
- cr.stroke();
+
+ let pixBuf = this._getIconPixBuf()
+ if (pixBuf == null) return null
+
+ let pixels = pixBuf.get_pixels(),
+ offset = 0
+
+ let total = 0,
+ rTotal = 0,
+ gTotal = 0,
+ bTotal = 0
+
+ let resample_y = 1,
+ resample_x = 1
+
+ // Resampling of large icons
+ // We resample icons larger than twice the desired size, as the resampling
+ // to a size s
+ // DOMINANT_COLOR_ICON_SIZE < s < 2*DOMINANT_COLOR_ICON_SIZE,
+ // most of the case exactly DOMINANT_COLOR_ICON_SIZE as the icon size is tipycally
+ // a multiple of it.
+ let width = pixBuf.get_width()
+ let height = pixBuf.get_height()
+
+ // Resample
+ if (height >= 2 * DOMINANT_COLOR_ICON_SIZE)
+ resample_y = Math.floor(height / DOMINANT_COLOR_ICON_SIZE)
+
+ if (width >= 2 * DOMINANT_COLOR_ICON_SIZE)
+ resample_x = Math.floor(width / DOMINANT_COLOR_ICON_SIZE)
+
+ if (resample_x !== 1 || resample_y !== 1)
+ pixels = this._resamplePixels(pixels, resample_x, resample_y)
+
+ // computing the limit outside the for (where it would be repeated at each iteration)
+ // for performance reasons
+ let limit = pixels.length
+ for (let offset = 0; offset < limit; offset += 4) {
+ let r = pixels[offset],
+ g = pixels[offset + 1],
+ b = pixels[offset + 2],
+ a = pixels[offset + 3]
+
+ let saturation = Math.max(r, g, b) - Math.min(r, g, b)
+ let relevance = 0.1 * 255 * 255 + 0.9 * a * saturation
+
+ rTotal += r * relevance
+ gTotal += g * relevance
+ bTotal += b * relevance
+
+ total += relevance
+ }
+
+ total = total * 255
+
+ let r = rTotal / total,
+ g = gTotal / total,
+ b = bTotal / total
+
+ let hsv = ColorUtils.RGBtoHSV(r * 255, g * 255, b * 255)
+
+ if (hsv.s > 0.15) hsv.s = 0.65
+ hsv.v = 0.9
+
+ let rgb = ColorUtils.HSVtoRGB(hsv.h, hsv.s, hsv.v)
+
+ // Cache the result.
+ let backgroundColor = {
+ lighter: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, 0.2),
+ original: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, 0),
+ darker: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, -0.5),
+ }
+
+ if (iconCacheMap.size >= MAX_CACHED_ITEMS) {
+ //delete oldest cached values (which are in order of insertions)
+ let ctr = 0
+ for (let key of iconCacheMap.keys()) {
+ if (++ctr > BATCH_SIZE_TO_DELETE) break
+ iconCacheMap.delete(key)
+ }
+ }
+
+ iconCacheMap.set(this._app.get_id(), backgroundColor)
+
+ return backgroundColor
+ }
+
+ /**
+ * Downsample large icons before scanning for the backlight color to
+ * improve performance.
+ *
+ * @param pixBuf
+ * @param pixels
+ * @param resampleX
+ * @param resampleY
+ *
+ * @return [];
+ */
+ _resamplePixels(pixels, resampleX, resampleY) {
+ let resampledPixels = []
+ // computing the limit outside the for (where it would be repeated at each iteration)
+ // for performance reasons
+ let limit = pixels.length / (resampleX * resampleY) / 4
+ for (let i = 0; i < limit; i++) {
+ let pixel = i * resampleX * resampleY
+
+ resampledPixels.push(pixels[pixel * 4])
+ resampledPixels.push(pixels[pixel * 4 + 1])
+ resampledPixels.push(pixels[pixel * 4 + 2])
+ resampledPixels.push(pixels[pixel * 4 + 3])
+ }
+
+ return resampledPixels
+ }
+}
+
+export const drawRoundedLine = function (
+ cr,
+ x,
+ y,
+ width,
+ height,
+ isRoundLeft,
+ isRoundRight,
+ stroke,
+ fill,
+) {
+ if (height > width) {
+ y += Math.floor((height - width) / 2.0)
+ height = width
+ }
+
+ height = 2.0 * Math.floor(height / 2.0)
+
+ const leftRadius = isRoundLeft ? height / 2.0 : 0.0
+ const rightRadius = isRoundRight ? height / 2.0 : 0.0
+
+ cr.moveTo(x + width - rightRadius, y)
+ cr.lineTo(x + leftRadius, y)
+ if (isRoundLeft)
+ cr.arcNegative(
+ x + leftRadius,
+ y + leftRadius,
+ leftRadius,
+ -Math.PI / 2,
+ Math.PI / 2,
+ )
+ else cr.lineTo(x, y + height)
+ cr.lineTo(x + width - rightRadius, y + height)
+ if (isRoundRight)
+ cr.arcNegative(
+ x + width - rightRadius,
+ y + rightRadius,
+ rightRadius,
+ Math.PI / 2,
+ -Math.PI / 2,
+ )
+ else cr.lineTo(x + width, y)
+ cr.closePath()
+
+ if (fill != null) {
+ cr.setSource(fill)
+ cr.fillPreserve()
+ }
+ if (stroke != null) cr.setSource(stroke)
+ cr.stroke()
}
diff --git a/windowPreview.js b/windowPreview.js
index cbbdf1a..3773cb0 100644
--- a/windowPreview.js
+++ b/windowPreview.js
@@ -15,1138 +15,1380 @@
* along with this program. If not, see .
*/
-import GObject from 'gi://GObject';
-import Clutter from 'gi://Clutter';
-import GLib from 'gi://GLib';
-import Graphene from 'gi://Graphene';
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
-import Meta from 'gi://Meta';
-import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
-import St from 'gi://St';
+import GObject from 'gi://GObject'
+import Clutter from 'gi://Clutter'
+import GLib from 'gi://GLib'
+import Graphene from 'gi://Graphene'
+import * as Main from 'resource:///org/gnome/shell/ui/main.js'
+import Meta from 'gi://Meta'
+import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'
+import St from 'gi://St'
-import * as Taskbar from './taskbar.js';
-import * as Utils from './utils.js';
-import {SETTINGS, DESKTOPSETTINGS} from './extension.js';
-import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js';
+import * as Taskbar from './taskbar.js'
+import * as Utils from './utils.js'
+import { SETTINGS, DESKTOPSETTINGS } from './extension.js'
+import { gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js'
//timeout intervals
-const ENSURE_VISIBLE_MS = 200;
+const ENSURE_VISIBLE_MS = 200
//timeout names
-const T1 = 'openMenuTimeout';
-const T2 = 'closeMenuTimeout';
-const T3 = 'peekTimeout';
-const T4 = 'ensureVisibleTimeout';
+const T1 = 'openMenuTimeout'
+const T2 = 'closeMenuTimeout'
+const T3 = 'peekTimeout'
+const T4 = 'ensureVisibleTimeout'
-const MAX_TRANSLATION = 40;
-const HEADER_HEIGHT = 38;
-const MAX_CLOSE_BUTTON_SIZE = 30;
-const MIN_DIMENSION = 100;
-const FOCUSED_COLOR_OFFSET = 24;
-const HEADER_COLOR_OFFSET = -12;
-const FADE_SIZE = 36;
-const PEEK_INDEX_PROP = '_dtpPeekInitialIndex';
+const MAX_TRANSLATION = 40
+const HEADER_HEIGHT = 38
+const MAX_CLOSE_BUTTON_SIZE = 30
+const MIN_DIMENSION = 100
+const FOCUSED_COLOR_OFFSET = 24
+const HEADER_COLOR_OFFSET = -12
+const FADE_SIZE = 36
+const PEEK_INDEX_PROP = '_dtpPeekInitialIndex'
-let headerHeight = 0;
-let alphaBg = 0;
-let isLeftButtons = false;
-let isTopHeader = true;
-let isManualStyling = false;
-let scaleFactor = 1;
-let animationTime = 0;
-let aspectRatio = {};
-
-export const PreviewMenu = GObject.registerClass({
- Signals: { 'open-state-changed': {} }
-}, class PreviewMenu extends St.Widget {
+let headerHeight = 0
+let alphaBg = 0
+let isLeftButtons = false
+let isTopHeader = true
+let isManualStyling = false
+let scaleFactor = 1
+let animationTime = 0
+let aspectRatio = {}
+export const PreviewMenu = GObject.registerClass(
+ {
+ Signals: { 'open-state-changed': {} },
+ },
+ class PreviewMenu extends St.Widget {
_init(panel) {
- super._init({ layout_manager: new Clutter.BinLayout() });
+ super._init({ layout_manager: new Clutter.BinLayout() })
- let geom = panel.geom;
- this.panel = panel;
- this.currentAppIcon = null;
- this._focusedPreview = null;
- this._peekedWindow = null;
- this.allowCloseWindow = true;
- this.peekInitialWorkspaceIndex = -1;
- this.opened = false;
- this.isVertical = geom.position == St.Side.LEFT || geom.position == St.Side.RIGHT;
- this._translationProp = 'translation_' + (this.isVertical ? 'x' : 'y');
- this._translationDirection = (geom.position == St.Side.TOP || geom.position == St.Side.LEFT ? -1 : 1);
- this._translationOffset = Math.min(panel.dtpSize, MAX_TRANSLATION) * this._translationDirection;
+ let geom = panel.geom
+ this.panel = panel
+ this.currentAppIcon = null
+ this._focusedPreview = null
+ this._peekedWindow = null
+ this.allowCloseWindow = true
+ this.peekInitialWorkspaceIndex = -1
+ this.opened = false
+ this.isVertical =
+ geom.position == St.Side.LEFT || geom.position == St.Side.RIGHT
+ this._translationProp = 'translation_' + (this.isVertical ? 'x' : 'y')
+ this._translationDirection =
+ geom.position == St.Side.TOP || geom.position == St.Side.LEFT ? -1 : 1
+ this._translationOffset =
+ Math.min(panel.dtpSize, MAX_TRANSLATION) * this._translationDirection
- this.menu = new St.Widget({
- name: 'preview-menu',
- layout_manager: new Clutter.BinLayout(),
- reactive: true,
- track_hover: true,
- x_expand: true,
- y_expand: true,
- x_align: Clutter.ActorAlign[geom.position != St.Side.RIGHT ? 'START' : 'END'],
- y_align: Clutter.ActorAlign[geom.position != St.Side.BOTTOM ? 'START' : 'END']
- });
- this._box = new St.BoxLayout({ vertical: this.isVertical });
- this._scrollView = new St.ScrollView({
- name: 'dashtopanelPreviewScrollview',
- hscrollbar_policy: St.PolicyType.NEVER,
- vscrollbar_policy: St.PolicyType.NEVER,
- enable_mouse_scrolling: true,
- y_expand: !this.isVertical
- });
+ this.menu = new St.Widget({
+ name: 'preview-menu',
+ layout_manager: new Clutter.BinLayout(),
+ reactive: true,
+ track_hover: true,
+ x_expand: true,
+ y_expand: true,
+ x_align:
+ Clutter.ActorAlign[geom.position != St.Side.RIGHT ? 'START' : 'END'],
+ y_align:
+ Clutter.ActorAlign[geom.position != St.Side.BOTTOM ? 'START' : 'END'],
+ })
+ this._box = new St.BoxLayout({ vertical: this.isVertical })
+ this._scrollView = new St.ScrollView({
+ name: 'dashtopanelPreviewScrollview',
+ hscrollbar_policy: St.PolicyType.NEVER,
+ vscrollbar_policy: St.PolicyType.NEVER,
+ enable_mouse_scrolling: true,
+ y_expand: !this.isVertical,
+ })
- this._scrollView.add_child(this._box);
- this.menu.add_child(this._scrollView);
- this.add_child(this.menu);
+ this._scrollView.add_child(this._box)
+ this.menu.add_child(this._scrollView)
+ this.add_child(this.menu)
}
enable() {
- this._timeoutsHandler = new Utils.TimeoutsHandler();
- this._signalsHandler = new Utils.GlobalSignalsHandler();
+ this._timeoutsHandler = new Utils.TimeoutsHandler()
+ this._signalsHandler = new Utils.GlobalSignalsHandler()
- Main.layoutManager.addChrome(this, { affectsInputRegion: false });
- Main.layoutManager.trackChrome(this.menu, { affectsInputRegion: true });
-
- this._resetHiddenState();
- this._refreshGlobals();
- this._updateClip();
- this.menu.set_position(1, 1);
+ Main.layoutManager.addChrome(this, { affectsInputRegion: false })
+ Main.layoutManager.trackChrome(this.menu, { affectsInputRegion: true })
- this._signalsHandler.add(
- [
- this.menu,
- 'notify::hover',
- () => this._onHoverChanged()
- ],
- [
- this._scrollView,
- 'scroll-event',
- this._onScrollEvent.bind(this)
- ],
- [
- this.panel.panelBox,
- 'style-changed',
- () => this._updateClip()
- ],
- [
- Utils.DisplayWrapper.getScreen(),
- 'in-fullscreen-changed',
- () => {
- if (global.display.focus_window && global.display.focus_window.is_fullscreen()) {
- this.close(true);
- }
- }
- ],
- [
- SETTINGS,
- [
- 'changed::panel-sizes',
- 'changed::window-preview-size',
- 'changed::window-preview-padding',
- 'changed::window-preview-show-title'
- ],
- () => {
- this._refreshGlobals();
- this._updateClip();
- }
- ]
- );
+ this._resetHiddenState()
+ this._refreshGlobals()
+ this._updateClip()
+ this.menu.set_position(1, 1)
+
+ this._signalsHandler.add(
+ [this.menu, 'notify::hover', () => this._onHoverChanged()],
+ [this._scrollView, 'scroll-event', this._onScrollEvent.bind(this)],
+ [this.panel.panelBox, 'style-changed', () => this._updateClip()],
+ [
+ Utils.DisplayWrapper.getScreen(),
+ 'in-fullscreen-changed',
+ () => {
+ if (
+ global.display.focus_window &&
+ global.display.focus_window.is_fullscreen()
+ ) {
+ this.close(true)
+ }
+ },
+ ],
+ [
+ SETTINGS,
+ [
+ 'changed::panel-sizes',
+ 'changed::window-preview-size',
+ 'changed::window-preview-padding',
+ 'changed::window-preview-show-title',
+ ],
+ () => {
+ this._refreshGlobals()
+ this._updateClip()
+ },
+ ],
+ )
}
disable() {
- this._timeoutsHandler.destroy();
- this._signalsHandler.destroy();
+ this._timeoutsHandler.destroy()
+ this._signalsHandler.destroy()
- this.close(true);
+ this.close(true)
- Main.layoutManager.untrackChrome(this.menu);
- Main.layoutManager.removeChrome(this);
+ Main.layoutManager.untrackChrome(this.menu)
+ Main.layoutManager.removeChrome(this)
}
requestOpen(appIcon) {
- let timeout = SETTINGS.get_int('show-window-previews-timeout');
+ let timeout = SETTINGS.get_int('show-window-previews-timeout')
- if (this.opened) {
- timeout = Math.min(100, timeout);
- }
+ if (this.opened) {
+ timeout = Math.min(100, timeout)
+ }
- this._endOpenCloseTimeouts();
- this._timeoutsHandler.add([T1, timeout, () => this.open(appIcon)]);
+ this._endOpenCloseTimeouts()
+ this._timeoutsHandler.add([T1, timeout, () => this.open(appIcon)])
}
requestClose() {
- this._endOpenCloseTimeouts();
- this._addCloseTimeout();
+ this._endOpenCloseTimeouts()
+ this._addCloseTimeout()
}
open(appIcon, preventCloseWindow) {
- if (this.currentAppIcon != appIcon) {
- this.currentAppIcon = appIcon;
- this.allowCloseWindow = !preventCloseWindow;
+ if (this.currentAppIcon != appIcon) {
+ this.currentAppIcon = appIcon
+ this.allowCloseWindow = !preventCloseWindow
- if (!this.opened) {
- this._refreshGlobals();
-
- this.set_height(this.clipHeight);
- this.show();
-
- setStyle(this.menu, 'background: ' + Utils.getrgbaColor(this.panel.dynamicTransparency.backgroundColorRgb, alphaBg));
- }
+ if (!this.opened) {
+ this._refreshGlobals()
- this._mergeWindows(appIcon);
- this._updatePosition();
- this._animateOpenOrClose(true);
+ this.set_height(this.clipHeight)
+ this.show()
- this._setReactive(true);
- this._setOpenedState(true);
+ setStyle(
+ this.menu,
+ 'background: ' +
+ Utils.getrgbaColor(
+ this.panel.dynamicTransparency.backgroundColorRgb,
+ alphaBg,
+ ),
+ )
}
+
+ this._mergeWindows(appIcon)
+ this._updatePosition()
+ this._animateOpenOrClose(true)
+
+ this._setReactive(true)
+ this._setOpenedState(true)
+ }
}
close(immediate) {
- this._endOpenCloseTimeouts();
- this._removeFocus();
- this._endPeek();
-
- if (immediate) {
- Utils.stopAnimations(this.menu);
- this._resetHiddenState();
- } else {
- this._animateOpenOrClose(false, () => this._resetHiddenState());
- }
+ this._endOpenCloseTimeouts()
+ this._removeFocus()
+ this._endPeek()
- this._setReactive(false);
- this.currentAppIcon = null;
+ if (immediate) {
+ Utils.stopAnimations(this.menu)
+ this._resetHiddenState()
+ } else {
+ this._animateOpenOrClose(false, () => this._resetHiddenState())
+ }
+
+ this._setReactive(false)
+ this.currentAppIcon = null
}
update(appIcon, windows) {
- if (this.currentAppIcon == appIcon) {
- if (windows && !windows.length) {
- this.close();
- } else {
- this._addAndRemoveWindows(windows);
- this._updatePosition();
- }
+ if (this.currentAppIcon == appIcon) {
+ if (windows && !windows.length) {
+ this.close()
+ } else {
+ this._addAndRemoveWindows(windows)
+ this._updatePosition()
}
+ }
}
updatePosition() {
- this._updatePosition();
+ this._updatePosition()
}
focusNext() {
- let previews = this._box.get_children();
- let currentIndex = this._focusedPreview ? previews.indexOf(this._focusedPreview) : -1;
- let nextIndex = currentIndex + 1;
-
- nextIndex = previews[nextIndex] ? nextIndex : 0;
+ let previews = this._box.get_children()
+ let currentIndex = this._focusedPreview
+ ? previews.indexOf(this._focusedPreview)
+ : -1
+ let nextIndex = currentIndex + 1
- if (previews[nextIndex]) {
- this._removeFocus();
- previews[nextIndex].setFocus(true);
- this._focusedPreview = previews[nextIndex];
- }
+ nextIndex = previews[nextIndex] ? nextIndex : 0
- return nextIndex;
+ if (previews[nextIndex]) {
+ this._removeFocus()
+ previews[nextIndex].setFocus(true)
+ this._focusedPreview = previews[nextIndex]
+ }
+
+ return nextIndex
}
activateFocused() {
- if (this.opened && this._focusedPreview) {
- this._focusedPreview.activate();
- }
+ if (this.opened && this._focusedPreview) {
+ this._focusedPreview.activate()
+ }
}
requestPeek(window) {
- this._timeoutsHandler.remove(T3);
+ this._timeoutsHandler.remove(T3)
- if (SETTINGS.get_boolean('peek-mode')) {
- if (this.peekInitialWorkspaceIndex < 0) {
- this._timeoutsHandler.add([T3, SETTINGS.get_int('enter-peek-mode-timeout'), () => this._peek(window)]);
- } else {
- this._peek(window);
- }
+ if (SETTINGS.get_boolean('peek-mode')) {
+ if (this.peekInitialWorkspaceIndex < 0) {
+ this._timeoutsHandler.add([
+ T3,
+ SETTINGS.get_int('enter-peek-mode-timeout'),
+ () => this._peek(window),
+ ])
+ } else {
+ this._peek(window)
}
+ }
}
endPeekHere() {
- this._endPeek(true);
+ this._endPeek(true)
}
ensureVisible(preview) {
- let [ , upper, pageSize] = this._getScrollAdjustmentValues();
-
- if (upper > pageSize) {
- this._timeoutsHandler.add([
- T4,
- ENSURE_VISIBLE_MS,
- () => Utils.ensureActorVisibleInScrollView(this._scrollView, preview, MIN_DIMENSION, () => this._updateScrollFade())
- ]);
- }
+ let [, upper, pageSize] = this._getScrollAdjustmentValues()
+
+ if (upper > pageSize) {
+ this._timeoutsHandler.add([
+ T4,
+ ENSURE_VISIBLE_MS,
+ () =>
+ Utils.ensureActorVisibleInScrollView(
+ this._scrollView,
+ preview,
+ MIN_DIMENSION,
+ () => this._updateScrollFade(),
+ ),
+ ])
+ }
}
getCurrentAppIcon() {
- return this.currentAppIcon;
+ return this.currentAppIcon
}
_setReactive(reactive) {
- this._box.get_children().forEach(c => c.reactive = reactive);
- this.menu.reactive = reactive;
+ this._box.get_children().forEach((c) => (c.reactive = reactive))
+ this.menu.reactive = reactive
}
_setOpenedState(opened) {
- this.opened = opened;
- this.emit('open-state-changed');
+ this.opened = opened
+ this.emit('open-state-changed')
}
_resetHiddenState() {
- this.hide();
- this.set_height(0);
- this._setOpenedState(false);
- this.menu.opacity = 0;
- this.menu[this._translationProp] = this._translationOffset;
- this._box.get_children().forEach(c => c.destroy());
+ this.hide()
+ this.set_height(0)
+ this._setOpenedState(false)
+ this.menu.opacity = 0
+ this.menu[this._translationProp] = this._translationOffset
+ this._box.get_children().forEach((c) => c.destroy())
}
_removeFocus() {
- if (this._focusedPreview) {
- this._focusedPreview.setFocus(false);
- this._focusedPreview = null;
- }
+ if (this._focusedPreview) {
+ this._focusedPreview.setFocus(false)
+ this._focusedPreview = null
+ }
}
_mergeWindows(appIcon, windows) {
- windows = windows || (appIcon.window ? [appIcon.window] : appIcon.getAppIconInterestingWindows());
- windows.sort(Taskbar.sortWindowsCompareFunction);
-
- let currentPreviews = this._box.get_children();
- let l = Math.max(windows.length, currentPreviews.length);
+ windows =
+ windows ||
+ (appIcon.window
+ ? [appIcon.window]
+ : appIcon.getAppIconInterestingWindows())
+ windows.sort(Taskbar.sortWindowsCompareFunction)
- for (let i = 0; i < l; ++i) {
- if (currentPreviews[i] && windows[i]) {
- currentPreviews[i].assignWindow(windows[i], this.opened);
- } else if (!currentPreviews[i]) {
- this._addNewPreview(windows[i]);
- } else if (!windows[i]) {
- currentPreviews[i][!this.opened ? 'destroy' : 'animateOut']();
- }
+ let currentPreviews = this._box.get_children()
+ let l = Math.max(windows.length, currentPreviews.length)
+
+ for (let i = 0; i < l; ++i) {
+ if (currentPreviews[i] && windows[i]) {
+ currentPreviews[i].assignWindow(windows[i], this.opened)
+ } else if (!currentPreviews[i]) {
+ this._addNewPreview(windows[i])
+ } else if (!windows[i]) {
+ currentPreviews[i][!this.opened ? 'destroy' : 'animateOut']()
}
+ }
}
_addAndRemoveWindows(windows) {
- let currentPreviews = this._box.get_children();
+ let currentPreviews = this._box.get_children()
- windows.sort(Taskbar.sortWindowsCompareFunction);
+ windows.sort(Taskbar.sortWindowsCompareFunction)
- for (let i = 0, l = windows.length; i < l; ++i) {
- let currentIndex = Utils.findIndex(currentPreviews, c => c.window == windows[i]);
-
- if (currentIndex < 0) {
- this._addNewPreview(windows[i]);
- } else {
- currentPreviews[currentIndex].assignWindow(windows[i]);
- currentPreviews.splice(currentIndex, 1);
+ for (let i = 0, l = windows.length; i < l; ++i) {
+ let currentIndex = Utils.findIndex(
+ currentPreviews,
+ (c) => c.window == windows[i],
+ )
- if (this._peekedWindow && this._peekedWindow == windows[i]) {
- this.requestPeek(windows[i]);
- }
- }
+ if (currentIndex < 0) {
+ this._addNewPreview(windows[i])
+ } else {
+ currentPreviews[currentIndex].assignWindow(windows[i])
+ currentPreviews.splice(currentIndex, 1)
+
+ if (this._peekedWindow && this._peekedWindow == windows[i]) {
+ this.requestPeek(windows[i])
+ }
}
+ }
- currentPreviews.forEach(c => c.animateOut());
+ currentPreviews.forEach((c) => c.animateOut())
}
_addNewPreview(window) {
- let preview = new Preview(this);
+ let preview = new Preview(this)
- this._box.add_child(preview);
- preview.adjustOnStage();
- preview.assignWindow(window, this.opened);
+ this._box.add_child(preview)
+ preview.adjustOnStage()
+ preview.assignWindow(window, this.opened)
}
_addCloseTimeout() {
- this._timeoutsHandler.add([T2, SETTINGS.get_int('leave-timeout'), () => this.close()]);
+ this._timeoutsHandler.add([
+ T2,
+ SETTINGS.get_int('leave-timeout'),
+ () => this.close(),
+ ])
}
_onHoverChanged() {
- this._endOpenCloseTimeouts();
+ this._endOpenCloseTimeouts()
- if (this.currentAppIcon && !this.menu.hover) {
- this._addCloseTimeout();
- this._endPeek();
- }
+ if (this.currentAppIcon && !this.menu.hover) {
+ this._addCloseTimeout()
+ this._endPeek()
+ }
}
_onScrollEvent(actor, event) {
- if (!event.is_pointer_emulated()) {
- let vOrh = this.isVertical ? 'v' : 'h';
- let adjustment = this._scrollView['get_' + vOrh + 'scroll_bar']().get_adjustment();
- let increment = adjustment.step_increment;
- let delta = increment;
+ if (!event.is_pointer_emulated()) {
+ let vOrh = this.isVertical ? 'v' : 'h'
+ let adjustment =
+ this._scrollView['get_' + vOrh + 'scroll_bar']().get_adjustment()
+ let increment = adjustment.step_increment
+ let delta = increment
- switch (event.get_scroll_direction()) {
- case Clutter.ScrollDirection.UP:
- delta = -increment;
- break;
- case Clutter.ScrollDirection.SMOOTH:
- let [dx, dy] = event.get_scroll_delta();
- delta = dy * increment;
- delta += dx * increment;
- break;
- }
-
- adjustment.set_value(adjustment.get_value() + delta);
- this._updateScrollFade();
+ switch (event.get_scroll_direction()) {
+ case Clutter.ScrollDirection.UP:
+ delta = -increment
+ break
+ case Clutter.ScrollDirection.SMOOTH:
+ let [dx, dy] = event.get_scroll_delta()
+ delta = dy * increment
+ delta += dx * increment
+ break
}
- return Clutter.EVENT_STOP;
+ adjustment.set_value(adjustment.get_value() + delta)
+ this._updateScrollFade()
+ }
+
+ return Clutter.EVENT_STOP
}
_endOpenCloseTimeouts() {
- this._timeoutsHandler.remove(T1);
- this._timeoutsHandler.remove(T2);
- this._timeoutsHandler.remove(T4);
+ this._timeoutsHandler.remove(T1)
+ this._timeoutsHandler.remove(T2)
+ this._timeoutsHandler.remove(T4)
}
_refreshGlobals() {
- isLeftButtons = Meta.prefs_get_button_layout().left_buttons.indexOf(Meta.ButtonFunction.CLOSE) >= 0;
- isTopHeader = SETTINGS.get_string('window-preview-title-position') == 'TOP';
- isManualStyling = SETTINGS.get_boolean('window-preview-manual-styling');
- scaleFactor = Utils.getScaleFactor();
- headerHeight = SETTINGS.get_boolean('window-preview-show-title') ? HEADER_HEIGHT * scaleFactor : 0;
- animationTime = SETTINGS.get_int('window-preview-animation-time') * .001;
- aspectRatio.x = {
- size: SETTINGS.get_int('window-preview-aspect-ratio-x'),
- fixed: SETTINGS.get_boolean('window-preview-fixed-x')
- };
- aspectRatio.y = {
- size: SETTINGS.get_int('window-preview-aspect-ratio-y'),
- fixed: SETTINGS.get_boolean('window-preview-fixed-y')
- };
-
- alphaBg = SETTINGS.get_boolean('preview-use-custom-opacity') ?
- SETTINGS.get_int('preview-custom-opacity') * .01 :
- this.panel.dynamicTransparency.alpha;
+ isLeftButtons =
+ Meta.prefs_get_button_layout().left_buttons.indexOf(
+ Meta.ButtonFunction.CLOSE,
+ ) >= 0
+ isTopHeader =
+ SETTINGS.get_string('window-preview-title-position') == 'TOP'
+ isManualStyling = SETTINGS.get_boolean('window-preview-manual-styling')
+ scaleFactor = Utils.getScaleFactor()
+ headerHeight = SETTINGS.get_boolean('window-preview-show-title')
+ ? HEADER_HEIGHT * scaleFactor
+ : 0
+ animationTime = SETTINGS.get_int('window-preview-animation-time') * 0.001
+ aspectRatio.x = {
+ size: SETTINGS.get_int('window-preview-aspect-ratio-x'),
+ fixed: SETTINGS.get_boolean('window-preview-fixed-x'),
+ }
+ aspectRatio.y = {
+ size: SETTINGS.get_int('window-preview-aspect-ratio-y'),
+ fixed: SETTINGS.get_boolean('window-preview-fixed-y'),
+ }
+
+ alphaBg = SETTINGS.get_boolean('preview-use-custom-opacity')
+ ? SETTINGS.get_int('preview-custom-opacity') * 0.01
+ : this.panel.dynamicTransparency.alpha
}
_updateClip() {
- let x, y, w;
- let geom = this.panel.getGeometry();
- let panelBoxTheme = this.panel.panelBox.get_theme_node();
- let previewSize = (SETTINGS.get_int('window-preview-size') +
- SETTINGS.get_int('window-preview-padding') * 2) * scaleFactor;
-
- if (this.isVertical) {
- w = previewSize;
- this.clipHeight = this.panel.monitor.height;
- y = this.panel.monitor.y;
- } else {
- w = this.panel.monitor.width;
- this.clipHeight = (previewSize + headerHeight);
- x = this.panel.monitor.x;
- }
+ let x, y, w
+ let geom = this.panel.getGeometry()
+ let panelBoxTheme = this.panel.panelBox.get_theme_node()
+ let previewSize =
+ (SETTINGS.get_int('window-preview-size') +
+ SETTINGS.get_int('window-preview-padding') * 2) *
+ scaleFactor
- if (geom.position == St.Side.LEFT) {
- x = this.panel.monitor.x + this.panel.dtpSize + panelBoxTheme.get_padding(St.Side.LEFT);
- } else if (geom.position == St.Side.RIGHT) {
- x = this.panel.monitor.x + this.panel.monitor.width - (this.panel.dtpSize + previewSize) - panelBoxTheme.get_padding(St.Side.RIGHT);
- } else if (geom.position == St.Side.TOP) {
- y = this.panel.monitor.y + this.panel.dtpSize + panelBoxTheme.get_padding(St.Side.TOP);
- } else { //St.Side.BOTTOM
- y = this.panel.monitor.y + this.panel.monitor.height - (this.panel.dtpSize + panelBoxTheme.get_padding(St.Side.BOTTOM) + previewSize + headerHeight);
- }
+ if (this.isVertical) {
+ w = previewSize
+ this.clipHeight = this.panel.monitor.height
+ y = this.panel.monitor.y
+ } else {
+ w = this.panel.monitor.width
+ this.clipHeight = previewSize + headerHeight
+ x = this.panel.monitor.x
+ }
- Utils.setClip(this, x, y, w, this.clipHeight);
+ if (geom.position == St.Side.LEFT) {
+ x =
+ this.panel.monitor.x +
+ this.panel.dtpSize +
+ panelBoxTheme.get_padding(St.Side.LEFT)
+ } else if (geom.position == St.Side.RIGHT) {
+ x =
+ this.panel.monitor.x +
+ this.panel.monitor.width -
+ (this.panel.dtpSize + previewSize) -
+ panelBoxTheme.get_padding(St.Side.RIGHT)
+ } else if (geom.position == St.Side.TOP) {
+ y =
+ this.panel.monitor.y +
+ this.panel.dtpSize +
+ panelBoxTheme.get_padding(St.Side.TOP)
+ } else {
+ //St.Side.BOTTOM
+ y =
+ this.panel.monitor.y +
+ this.panel.monitor.height -
+ (this.panel.dtpSize +
+ panelBoxTheme.get_padding(St.Side.BOTTOM) +
+ previewSize +
+ headerHeight)
+ }
+
+ Utils.setClip(this, x, y, w, this.clipHeight)
}
_updatePosition() {
- let sourceNode = this.currentAppIcon.get_theme_node();
- let sourceContentBox = sourceNode.get_content_box(this.currentAppIcon.get_allocation_box());
- let sourceAllocation = Utils.getTransformedAllocation(this.currentAppIcon);
- let [previewsWidth, previewsHeight] = this._getPreviewsSize();
- let appIconMargin = SETTINGS.get_int('appicon-margin') / scaleFactor;
- let x = 0, y = 0;
+ let sourceNode = this.currentAppIcon.get_theme_node()
+ let sourceContentBox = sourceNode.get_content_box(
+ this.currentAppIcon.get_allocation_box(),
+ )
+ let sourceAllocation = Utils.getTransformedAllocation(this.currentAppIcon)
+ let [previewsWidth, previewsHeight] = this._getPreviewsSize()
+ let appIconMargin = SETTINGS.get_int('appicon-margin') / scaleFactor
+ let x = 0,
+ y = 0
- previewsWidth = Math.min(previewsWidth, this.panel.monitor.width);
- previewsHeight = Math.min(previewsHeight, this.panel.monitor.height);
- this._updateScrollFade(previewsWidth < this.panel.monitor.width && previewsHeight < this.panel.monitor.height);
-
- if (this.isVertical) {
- y = sourceAllocation.y1 + appIconMargin - this.panel.monitor.y + (sourceContentBox.y2 - sourceContentBox.y1 - previewsHeight) * .5;
- y = Math.max(y, 0);
- y = Math.min(y, this.panel.monitor.height - previewsHeight);
- } else {
- x = sourceAllocation.x1 + appIconMargin - this.panel.monitor.x + (sourceContentBox.x2 - sourceContentBox.x1 - previewsWidth) * .5;
- x = Math.max(x, 0);
- x = Math.min(x, this.panel.monitor.width - previewsWidth);
- }
+ previewsWidth = Math.min(previewsWidth, this.panel.monitor.width)
+ previewsHeight = Math.min(previewsHeight, this.panel.monitor.height)
+ this._updateScrollFade(
+ previewsWidth < this.panel.monitor.width &&
+ previewsHeight < this.panel.monitor.height,
+ )
- if (!this.opened) {
- this.menu.set_position(x, y);
- this.menu.set_size(previewsWidth, previewsHeight);
- } else {
- Utils.animate(this.menu, getTweenOpts({ x: x, y: y, width: previewsWidth, height: previewsHeight }));
- }
+ if (this.isVertical) {
+ y =
+ sourceAllocation.y1 +
+ appIconMargin -
+ this.panel.monitor.y +
+ (sourceContentBox.y2 - sourceContentBox.y1 - previewsHeight) * 0.5
+ y = Math.max(y, 0)
+ y = Math.min(y, this.panel.monitor.height - previewsHeight)
+ } else {
+ x =
+ sourceAllocation.x1 +
+ appIconMargin -
+ this.panel.monitor.x +
+ (sourceContentBox.x2 - sourceContentBox.x1 - previewsWidth) * 0.5
+ x = Math.max(x, 0)
+ x = Math.min(x, this.panel.monitor.width - previewsWidth)
+ }
+
+ if (!this.opened) {
+ this.menu.set_position(x, y)
+ this.menu.set_size(previewsWidth, previewsHeight)
+ } else {
+ Utils.animate(
+ this.menu,
+ getTweenOpts({
+ x: x,
+ y: y,
+ width: previewsWidth,
+ height: previewsHeight,
+ }),
+ )
+ }
}
_updateScrollFade(remove) {
- let [value, upper, pageSize] = this._getScrollAdjustmentValues();
- let needsFade = Math.round(upper) > Math.round(pageSize);
- let fadeWidgets = this.menu.get_children().filter(c => c != this._scrollView);
-
- if (!remove && needsFade) {
- if (!fadeWidgets.length) {
- fadeWidgets.push(this._getFadeWidget());
- fadeWidgets.push(this._getFadeWidget(true));
-
- this.menu.add_child(fadeWidgets[0]);
- this.menu.add_child(fadeWidgets[1]);
- }
-
- fadeWidgets[0].visible = value > 0;
- fadeWidgets[1].visible = value + pageSize < upper;
- } else if (remove || (!needsFade && fadeWidgets.length)) {
- fadeWidgets.forEach(fw => fw.destroy());
+ let [value, upper, pageSize] = this._getScrollAdjustmentValues()
+ let needsFade = Math.round(upper) > Math.round(pageSize)
+ let fadeWidgets = this.menu
+ .get_children()
+ .filter((c) => c != this._scrollView)
+
+ if (!remove && needsFade) {
+ if (!fadeWidgets.length) {
+ fadeWidgets.push(this._getFadeWidget())
+ fadeWidgets.push(this._getFadeWidget(true))
+
+ this.menu.add_child(fadeWidgets[0])
+ this.menu.add_child(fadeWidgets[1])
}
+
+ fadeWidgets[0].visible = value > 0
+ fadeWidgets[1].visible = value + pageSize < upper
+ } else if (remove || (!needsFade && fadeWidgets.length)) {
+ fadeWidgets.forEach((fw) => fw.destroy())
+ }
}
_getScrollAdjustmentValues() {
- let [value , , upper, , , pageSize] = this._scrollView[(this.isVertical ? 'v' : 'h') + 'adjustment'].get_values();
+ let [value, , upper, , , pageSize] =
+ this._scrollView[
+ (this.isVertical ? 'v' : 'h') + 'adjustment'
+ ].get_values()
- return [value, upper, pageSize];
+ return [value, upper, pageSize]
}
_getFadeWidget(end) {
- let x = 0, y = 0;
- let startBg = Utils.getrgbaColor(this.panel.dynamicTransparency.backgroundColorRgb, Math.min(alphaBg + .1, 1));
- let endBg = Utils.getrgbaColor(this.panel.dynamicTransparency.backgroundColorRgb, 0)
- let fadeStyle = 'background-gradient-start:' + startBg +
- 'background-gradient-end:' + endBg +
- 'background-gradient-direction:' + this.panel.getOrientation();
+ let x = 0,
+ y = 0
+ let startBg = Utils.getrgbaColor(
+ this.panel.dynamicTransparency.backgroundColorRgb,
+ Math.min(alphaBg + 0.1, 1),
+ )
+ let endBg = Utils.getrgbaColor(
+ this.panel.dynamicTransparency.backgroundColorRgb,
+ 0,
+ )
+ let fadeStyle =
+ 'background-gradient-start:' +
+ startBg +
+ 'background-gradient-end:' +
+ endBg +
+ 'background-gradient-direction:' +
+ this.panel.getOrientation()
- if (this.isVertical) {
- y = end ? this.panel.monitor.height - FADE_SIZE : 0;
- } else {
- x = end ? this.panel.monitor.width - FADE_SIZE : 0;
- }
+ if (this.isVertical) {
+ y = end ? this.panel.monitor.height - FADE_SIZE : 0
+ } else {
+ x = end ? this.panel.monitor.width - FADE_SIZE : 0
+ }
- let fadeWidget = new St.Widget({
- reactive: false,
- pivot_point: new Graphene.Point({ x: .5, y: .5 }),
- rotation_angle_z: end ? 180 : 0,
- style: fadeStyle,
- x: x, y: y,
- width: this.isVertical ? this.width : FADE_SIZE,
- height: this.isVertical ? FADE_SIZE : this.height
- });
+ let fadeWidget = new St.Widget({
+ reactive: false,
+ pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
+ rotation_angle_z: end ? 180 : 0,
+ style: fadeStyle,
+ x: x,
+ y: y,
+ width: this.isVertical ? this.width : FADE_SIZE,
+ height: this.isVertical ? FADE_SIZE : this.height,
+ })
- return fadeWidget;
+ return fadeWidget
}
_getPreviewsSize() {
- let previewsWidth = 0;
- let previewsHeight = 0;
+ let previewsWidth = 0
+ let previewsHeight = 0
- this._box.get_children().forEach(c => {
- if (!c.animatingOut) {
- let [width, height] = c.getSize();
+ this._box.get_children().forEach((c) => {
+ if (!c.animatingOut) {
+ let [width, height] = c.getSize()
- if (this.isVertical) {
- previewsWidth = Math.max(width, previewsWidth);
- previewsHeight += height;
- } else {
- previewsWidth += width;
- previewsHeight = Math.max(height, previewsHeight);
- }
- }
- });
+ if (this.isVertical) {
+ previewsWidth = Math.max(width, previewsWidth)
+ previewsHeight += height
+ } else {
+ previewsWidth += width
+ previewsHeight = Math.max(height, previewsHeight)
+ }
+ }
+ })
- return [previewsWidth, previewsHeight];
+ return [previewsWidth, previewsHeight]
}
_animateOpenOrClose(show, onComplete) {
- let isTranslationAnimation = this.menu[this._translationProp] != 0;
- let tweenOpts = {
- opacity: show ? 255 : 0,
- transition: show ? 'easeInOutQuad' : 'easeInCubic',
- onComplete: () => {
- if (isTranslationAnimation) {
- Main.layoutManager._queueUpdateRegions();
- }
-
- (onComplete || (() => {}))();
- }
- };
+ let isTranslationAnimation = this.menu[this._translationProp] != 0
+ let tweenOpts = {
+ opacity: show ? 255 : 0,
+ transition: show ? 'easeInOutQuad' : 'easeInCubic',
+ onComplete: () => {
+ if (isTranslationAnimation) {
+ Main.layoutManager._queueUpdateRegions()
+ }
- tweenOpts[this._translationProp] = show ? this._translationDirection : this._translationOffset;
+ ;(onComplete || (() => {}))()
+ },
+ }
- Utils.animate(this.menu, getTweenOpts(tweenOpts));
+ tweenOpts[this._translationProp] = show
+ ? this._translationDirection
+ : this._translationOffset
+
+ Utils.animate(this.menu, getTweenOpts(tweenOpts))
}
_peek(window) {
- let currentWorkspace = Utils.getCurrentWorkspace();
- let windowWorkspace = window.get_workspace();
- let focusWindow = () => this._focusMetaWindow(SETTINGS.get_int('peek-mode-opacity'), window);
-
- this._restorePeekedWindowStack();
+ let currentWorkspace = Utils.getCurrentWorkspace()
+ let windowWorkspace = window.get_workspace()
+ let focusWindow = () =>
+ this._focusMetaWindow(SETTINGS.get_int('peek-mode-opacity'), window)
- if (this._peekedWindow && windowWorkspace != currentWorkspace) {
- currentWorkspace.list_windows().forEach(mw => this.animateWindowOpacity(mw, null, 255))
- }
+ this._restorePeekedWindowStack()
- this._peekedWindow = window;
-
- if (currentWorkspace != windowWorkspace) {
- this._switchToWorkspaceImmediate(windowWorkspace.index());
- this._timeoutsHandler.add([T3, 100, focusWindow]);
- } else {
- focusWindow();
- }
+ if (this._peekedWindow && windowWorkspace != currentWorkspace) {
+ currentWorkspace
+ .list_windows()
+ .forEach((mw) => this.animateWindowOpacity(mw, null, 255))
+ }
- if (this.peekInitialWorkspaceIndex < 0) {
- this.peekInitialWorkspaceIndex = currentWorkspace.index();
- }
+ this._peekedWindow = window
+
+ if (currentWorkspace != windowWorkspace) {
+ this._switchToWorkspaceImmediate(windowWorkspace.index())
+ this._timeoutsHandler.add([T3, 100, focusWindow])
+ } else {
+ focusWindow()
+ }
+
+ if (this.peekInitialWorkspaceIndex < 0) {
+ this.peekInitialWorkspaceIndex = currentWorkspace.index()
+ }
}
_endPeek(stayHere) {
- this._timeoutsHandler.remove(T3);
+ this._timeoutsHandler.remove(T3)
- if (this._peekedWindow) {
- let immediate = !stayHere && this.peekInitialWorkspaceIndex != Utils.getCurrentWorkspace().index();
+ if (this._peekedWindow) {
+ let immediate =
+ !stayHere &&
+ this.peekInitialWorkspaceIndex != Utils.getCurrentWorkspace().index()
- this._restorePeekedWindowStack();
- this._focusMetaWindow(255, this._peekedWindow, immediate, true);
- this._peekedWindow = null;
+ this._restorePeekedWindowStack()
+ this._focusMetaWindow(255, this._peekedWindow, immediate, true)
+ this._peekedWindow = null
- if (!stayHere) {
- this._switchToWorkspaceImmediate(this.peekInitialWorkspaceIndex);
- }
-
- this.peekInitialWorkspaceIndex = -1;
+ if (!stayHere) {
+ this._switchToWorkspaceImmediate(this.peekInitialWorkspaceIndex)
}
+
+ this.peekInitialWorkspaceIndex = -1
+ }
}
_switchToWorkspaceImmediate(workspaceIndex) {
- let workspace = Utils.getWorkspaceByIndex(workspaceIndex);
- let shouldAnimate = Main.wm._shouldAnimate;
+ let workspace = Utils.getWorkspaceByIndex(workspaceIndex)
+ let shouldAnimate = Main.wm._shouldAnimate
- if (!workspace || (!workspace.list_windows().length &&
- workspaceIndex < Utils.getWorkspaceCount() - 1)) {
- workspace = Utils.getCurrentWorkspace();
- }
+ if (
+ !workspace ||
+ (!workspace.list_windows().length &&
+ workspaceIndex < Utils.getWorkspaceCount() - 1)
+ ) {
+ workspace = Utils.getCurrentWorkspace()
+ }
- Main.wm._shouldAnimate = () => false;
- workspace.activate(global.display.get_current_time_roundtrip());
- Main.wm._shouldAnimate = shouldAnimate;
+ Main.wm._shouldAnimate = () => false
+ workspace.activate(global.display.get_current_time_roundtrip())
+ Main.wm._shouldAnimate = shouldAnimate
}
_focusMetaWindow(dimOpacity, window, immediate, ignoreFocus) {
- window.get_workspace().list_windows().forEach(mw => {
- let wa = mw.get_compositor_private();
- let isFocused = !ignoreFocus && mw == window;
+ window
+ .get_workspace()
+ .list_windows()
+ .forEach((mw) => {
+ let wa = mw.get_compositor_private()
+ let isFocused = !ignoreFocus && mw == window
- if (wa) {
- if (isFocused) {
- mw[PEEK_INDEX_PROP] = wa.get_parent().get_children().indexOf(wa);
- wa.get_parent().set_child_above_sibling(wa, null);
- }
-
- if (isFocused && mw.minimized) {
- wa.show();
- }
-
- this.animateWindowOpacity(mw, wa, isFocused ? 255 : dimOpacity, immediate)
+ if (wa) {
+ if (isFocused) {
+ mw[PEEK_INDEX_PROP] = wa.get_parent().get_children().indexOf(wa)
+ wa.get_parent().set_child_above_sibling(wa, null)
}
- });
+
+ if (isFocused && mw.minimized) {
+ wa.show()
+ }
+
+ this.animateWindowOpacity(
+ mw,
+ wa,
+ isFocused ? 255 : dimOpacity,
+ immediate,
+ )
+ }
+ })
}
animateWindowOpacity(metaWindow, windowActor, opacity, immediate) {
- windowActor = windowActor || metaWindow.get_compositor_private();
-
- if (windowActor && !metaWindow.minimized) {
- let tweenOpts = getTweenOpts({ opacity });
+ windowActor = windowActor || metaWindow.get_compositor_private()
- if (immediate && !metaWindow.is_on_all_workspaces()) {
- tweenOpts.time = 0;
- }
-
- Utils.animateWindowOpacity(windowActor, tweenOpts);
+ if (windowActor && !metaWindow.minimized) {
+ let tweenOpts = getTweenOpts({ opacity })
+
+ if (immediate && !metaWindow.is_on_all_workspaces()) {
+ tweenOpts.time = 0
}
+
+ Utils.animateWindowOpacity(windowActor, tweenOpts)
+ }
}
_restorePeekedWindowStack() {
- let windowActor = this._peekedWindow ? this._peekedWindow.get_compositor_private() : null;
+ let windowActor = this._peekedWindow
+ ? this._peekedWindow.get_compositor_private()
+ : null
- if (windowActor) {
- if (this._peekedWindow.hasOwnProperty(PEEK_INDEX_PROP)) {
- windowActor.get_parent().set_child_at_index(windowActor, this._peekedWindow[PEEK_INDEX_PROP]);
- delete this._peekedWindow[PEEK_INDEX_PROP];
- }
-
- if (this._peekedWindow.minimized) {
- windowActor.hide();
- }
+ if (windowActor) {
+ if (this._peekedWindow.hasOwnProperty(PEEK_INDEX_PROP)) {
+ windowActor
+ .get_parent()
+ .set_child_at_index(
+ windowActor,
+ this._peekedWindow[PEEK_INDEX_PROP],
+ )
+ delete this._peekedWindow[PEEK_INDEX_PROP]
}
+
+ if (this._peekedWindow.minimized) {
+ windowActor.hide()
+ }
+ }
}
-});
-
-export const Preview = GObject.registerClass({
-}, class Preview extends St.Widget {
+ },
+)
+export const Preview = GObject.registerClass(
+ {},
+ class Preview extends St.Widget {
_init(previewMenu) {
- super._init({
- style_class: 'preview-container',
- reactive: true,
- track_hover: true,
- layout_manager: new Clutter.BinLayout()
- });
+ super._init({
+ style_class: 'preview-container',
+ reactive: true,
+ track_hover: true,
+ layout_manager: new Clutter.BinLayout(),
+ })
- this.window = null;
- this._waitWindowId = 0;
- this._needsCloseButton = true;
- this.cloneWidth = this.cloneHeight = 0;
- this._previewMenu = previewMenu;
- this._padding = SETTINGS.get_int('window-preview-padding') * scaleFactor;
- this._previewDimensions = this._getPreviewDimensions();
- this.animatingOut = false;
+ this.window = null
+ this._waitWindowId = 0
+ this._needsCloseButton = true
+ this.cloneWidth = this.cloneHeight = 0
+ this._previewMenu = previewMenu
+ this._padding = SETTINGS.get_int('window-preview-padding') * scaleFactor
+ this._previewDimensions = this._getPreviewDimensions()
+ this.animatingOut = false
- let box = new St.Widget({ layout_manager: new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL }), y_expand: true });
- let [previewBinWidth, previewBinHeight] = this._getBinSize();
- let closeButton = new St.Button({ style_class: 'window-close', accessible_name: 'Close window' });
+ let box = new St.Widget({
+ layout_manager: new Clutter.BoxLayout({
+ orientation: Clutter.Orientation.VERTICAL,
+ }),
+ y_expand: true,
+ })
+ let [previewBinWidth, previewBinHeight] = this._getBinSize()
+ let closeButton = new St.Button({
+ style_class: 'window-close',
+ accessible_name: 'Close window',
+ })
- closeButton.add_child(new St.Icon({ icon_name: 'window-close-symbolic' }));
+ closeButton.add_child(new St.Icon({ icon_name: 'window-close-symbolic' }))
- this._closeButtonBin = new St.Widget({
- style_class: 'preview-close-btn-container',
- layout_manager: new Clutter.BinLayout(),
- opacity: 0,
- x_expand: true, y_expand: true,
- x_align: Clutter.ActorAlign[isLeftButtons ? 'START' : 'END'],
- y_align: Clutter.ActorAlign[isTopHeader ? 'START' : 'END']
- });
+ this._closeButtonBin = new St.Widget({
+ style_class: 'preview-close-btn-container',
+ layout_manager: new Clutter.BinLayout(),
+ opacity: 0,
+ x_expand: true,
+ y_expand: true,
+ x_align: Clutter.ActorAlign[isLeftButtons ? 'START' : 'END'],
+ y_align: Clutter.ActorAlign[isTopHeader ? 'START' : 'END'],
+ })
- this._closeButtonBin.add_child(closeButton);
+ this._closeButtonBin.add_child(closeButton)
- this._previewBin = new St.Widget({
- layout_manager: new Clutter.BinLayout(),
- x_expand: true, y_expand: true,
- style: 'padding: ' + this._padding / scaleFactor + 'px;'
- });
+ this._previewBin = new St.Widget({
+ layout_manager: new Clutter.BinLayout(),
+ x_expand: true,
+ y_expand: true,
+ style: 'padding: ' + this._padding / scaleFactor + 'px;',
+ })
- this._previewBin.set_size(previewBinWidth, previewBinHeight);
+ this._previewBin.set_size(previewBinWidth, previewBinHeight)
- box.add_child(this._previewBin);
-
- if (headerHeight) {
- let headerBox = new St.Widget({
- style_class: 'preview-header-box',
- layout_manager: new Clutter.BoxLayout(),
- x_expand: true,
- y_align: Clutter.ActorAlign[isTopHeader ? 'START' : 'END']
- });
-
- setStyle(headerBox, this._getBackgroundColor(HEADER_COLOR_OFFSET, 1));
- this._workspaceIndicator = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
- this._windowTitle = new St.Label({ y_align: Clutter.ActorAlign.CENTER, x_expand: true });
+ box.add_child(this._previewBin)
- this._iconBin = new St.Widget({ layout_manager: new Clutter.BinLayout() });
- this._iconBin.set_size(headerHeight, headerHeight);
-
- headerBox.add_child(this._iconBin);
- headerBox.insert_child_at_index(this._workspaceIndicator, isLeftButtons ? 0 : 1);
- headerBox.insert_child_at_index(this._windowTitle, isLeftButtons ? 1 : 2);
+ if (headerHeight) {
+ let headerBox = new St.Widget({
+ style_class: 'preview-header-box',
+ layout_manager: new Clutter.BoxLayout(),
+ x_expand: true,
+ y_align: Clutter.ActorAlign[isTopHeader ? 'START' : 'END'],
+ })
- box.insert_child_at_index(headerBox, isTopHeader ? 0 : 1);
- }
+ setStyle(headerBox, this._getBackgroundColor(HEADER_COLOR_OFFSET, 1))
+ this._workspaceIndicator = new St.Label({
+ y_align: Clutter.ActorAlign.CENTER,
+ })
+ this._windowTitle = new St.Label({
+ y_align: Clutter.ActorAlign.CENTER,
+ x_expand: true,
+ })
- this.add_child(box);
- this.add_child(this._closeButtonBin);
+ this._iconBin = new St.Widget({
+ layout_manager: new Clutter.BinLayout(),
+ })
+ this._iconBin.set_size(headerHeight, headerHeight)
- closeButton.connect('clicked', () => this._onCloseBtnClick());
- this.connect('notify::hover', () => this._onHoverChanged());
- this.connect('button-release-event', (actor, e) => this._onButtonReleaseEvent(e));
- this.connect('destroy', () => this._onDestroy());
+ headerBox.add_child(this._iconBin)
+ headerBox.insert_child_at_index(
+ this._workspaceIndicator,
+ isLeftButtons ? 0 : 1,
+ )
+ headerBox.insert_child_at_index(
+ this._windowTitle,
+ isLeftButtons ? 1 : 2,
+ )
+
+ box.insert_child_at_index(headerBox, isTopHeader ? 0 : 1)
+ }
+
+ this.add_child(box)
+ this.add_child(this._closeButtonBin)
+
+ closeButton.connect('clicked', () => this._onCloseBtnClick())
+ this.connect('notify::hover', () => this._onHoverChanged())
+ this.connect('button-release-event', (actor, e) =>
+ this._onButtonReleaseEvent(e),
+ )
+ this.connect('destroy', () => this._onDestroy())
}
adjustOnStage() {
- let closeButton = this._closeButtonBin.get_first_child();
- let closeButtonHeight = closeButton.height;
- let maxCloseButtonSize = MAX_CLOSE_BUTTON_SIZE * scaleFactor;
- let closeButtonBorderRadius = '';
+ let closeButton = this._closeButtonBin.get_first_child()
+ let closeButtonHeight = closeButton.height
+ let maxCloseButtonSize = MAX_CLOSE_BUTTON_SIZE * scaleFactor
+ let closeButtonBorderRadius = ''
- if (closeButtonHeight > maxCloseButtonSize) {
- closeButtonHeight = maxCloseButtonSize;
- closeButton.set_size(closeButtonHeight, closeButtonHeight);
+ if (closeButtonHeight > maxCloseButtonSize) {
+ closeButtonHeight = maxCloseButtonSize
+ closeButton.set_size(closeButtonHeight, closeButtonHeight)
+ }
+
+ if (!headerHeight) {
+ closeButtonBorderRadius = 'border-radius: '
+
+ if (isTopHeader) {
+ closeButtonBorderRadius += isLeftButtons ? '0 0 4px 0;' : '0 0 0 4px;'
+ } else {
+ closeButtonBorderRadius += isLeftButtons ? '0 4px 0 0;' : '4px 0 0 0;'
}
+ }
- if (!headerHeight) {
- closeButtonBorderRadius = 'border-radius: ';
-
- if (isTopHeader) {
- closeButtonBorderRadius += (isLeftButtons ? '0 0 4px 0;' : '0 0 0 4px;');
- } else {
- closeButtonBorderRadius += (isLeftButtons ? '0 4px 0 0;' : '4px 0 0 0;');
- }
- }
-
- setStyle(
- this._closeButtonBin,
- 'padding: ' + (headerHeight ? Math.round((headerHeight - closeButtonHeight) * .5 / scaleFactor) : 4) + 'px;' +
- this._getBackgroundColor(HEADER_COLOR_OFFSET, headerHeight ? 1 : .6) +
- closeButtonBorderRadius
- );
+ setStyle(
+ this._closeButtonBin,
+ 'padding: ' +
+ (headerHeight
+ ? Math.round(
+ ((headerHeight - closeButtonHeight) * 0.5) / scaleFactor,
+ )
+ : 4) +
+ 'px;' +
+ this._getBackgroundColor(
+ HEADER_COLOR_OFFSET,
+ headerHeight ? 1 : 0.6,
+ ) +
+ closeButtonBorderRadius,
+ )
}
assignWindow(window, animateSize) {
- if (this.window != window) {
- let _assignWindowClone = () => {
- if (window.get_compositor_private()) {
- let cloneBin = this._getWindowCloneBin(window);
-
- this._resizeClone(cloneBin, window);
- this._addClone(cloneBin, animateSize);
- this._previewMenu.updatePosition();
- } else if (!this._waitWindowId) {
- this._waitWindowId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
- this._waitWindowId = 0;
+ if (this.window != window) {
+ let _assignWindowClone = () => {
+ if (window.get_compositor_private()) {
+ let cloneBin = this._getWindowCloneBin(window)
- if (this._previewMenu.opened) {
- _assignWindowClone();
- }
+ this._resizeClone(cloneBin, window)
+ this._addClone(cloneBin, animateSize)
+ this._previewMenu.updatePosition()
+ } else if (!this._waitWindowId) {
+ this._waitWindowId = GLib.idle_add(
+ GLib.PRIORITY_DEFAULT_IDLE,
+ () => {
+ this._waitWindowId = 0
- return GLib.SOURCE_REMOVE;
- });
+ if (this._previewMenu.opened) {
+ _assignWindowClone()
}
- };
- _assignWindowClone();
+ return GLib.SOURCE_REMOVE
+ },
+ )
+ }
}
- this._cancelAnimateOut();
- this._removeWindowSignals();
- this.window = window;
- this._needsCloseButton = this._previewMenu.allowCloseWindow && window.can_close() && !Utils.checkIfWindowHasTransient(window);
- this._updateHeader();
+ _assignWindowClone()
+ }
+
+ this._cancelAnimateOut()
+ this._removeWindowSignals()
+ this.window = window
+ this._needsCloseButton =
+ this._previewMenu.allowCloseWindow &&
+ window.can_close() &&
+ !Utils.checkIfWindowHasTransient(window)
+ this._updateHeader()
}
animateOut() {
- if (!this.animatingOut) {
- let tweenOpts = getTweenOpts({ opacity: 0, width: 0, height: 0, onComplete: () => this.destroy() });
+ if (!this.animatingOut) {
+ let tweenOpts = getTweenOpts({
+ opacity: 0,
+ width: 0,
+ height: 0,
+ onComplete: () => this.destroy(),
+ })
- this.animatingOut = true;
+ this.animatingOut = true
- Utils.stopAnimations(this);
- Utils.animate(this, tweenOpts);
- }
+ Utils.stopAnimations(this)
+ Utils.animate(this, tweenOpts)
+ }
}
getSize() {
- let [binWidth, binHeight] = this._getBinSize();
+ let [binWidth, binHeight] = this._getBinSize()
- binWidth = Math.max(binWidth, this.cloneWidth + this._padding * 2);
- binHeight = Math.max(binHeight, this.cloneHeight + this._padding * 2) + headerHeight;
+ binWidth = Math.max(binWidth, this.cloneWidth + this._padding * 2)
+ binHeight =
+ Math.max(binHeight, this.cloneHeight + this._padding * 2) + headerHeight
- return [binWidth, binHeight];
+ return [binWidth, binHeight]
}
setFocus(focused) {
- this._hideOrShowCloseButton(!focused);
- setStyle(this, this._getBackgroundColor(FOCUSED_COLOR_OFFSET, focused ? '-' : 0));
+ this._hideOrShowCloseButton(!focused)
+ setStyle(
+ this,
+ this._getBackgroundColor(FOCUSED_COLOR_OFFSET, focused ? '-' : 0),
+ )
- if (focused) {
- this._previewMenu.ensureVisible(this);
- this._previewMenu.requestPeek(this.window);
- }
+ if (focused) {
+ this._previewMenu.ensureVisible(this)
+ this._previewMenu.requestPeek(this.window)
+ }
}
activate() {
- this._previewMenu.endPeekHere();
- this._previewMenu.close();
- Main.activateWindow(this.window);
+ this._previewMenu.endPeekHere()
+ this._previewMenu.close()
+ Main.activateWindow(this.window)
}
_onDestroy() {
- if (this._waitWindowId) {
- GLib.source_remove(this._waitWindowId);
- this._waitWindowId = 0;
- }
+ if (this._waitWindowId) {
+ GLib.source_remove(this._waitWindowId)
+ this._waitWindowId = 0
+ }
- this._removeWindowSignals();
+ this._removeWindowSignals()
}
_onHoverChanged() {
- this.setFocus(this.hover);
+ this.setFocus(this.hover)
}
_onCloseBtnClick() {
- this._hideOrShowCloseButton(true);
- this.reactive = false;
+ this._hideOrShowCloseButton(true)
+ this.reactive = false
- if (!SETTINGS.get_boolean('group-apps')) {
- this._previewMenu.close();
- } else {
- this._previewMenu.endPeekHere();
- }
+ if (!SETTINGS.get_boolean('group-apps')) {
+ this._previewMenu.close()
+ } else {
+ this._previewMenu.endPeekHere()
+ }
- this.window.delete(global.get_current_time());
+ this.window.delete(global.get_current_time())
}
_onButtonReleaseEvent(e) {
- switch (e.get_button()) {
- case 1: // Left click
- this.activate();
- break;
- case 2: // Middle click
- if (SETTINGS.get_boolean('preview-middle-click-close')) {
- this._onCloseBtnClick();
- }
- break;
- case 3: // Right click
- this._showContextMenu(e);
- break;
- }
+ switch (e.get_button()) {
+ case 1: // Left click
+ this.activate()
+ break
+ case 2: // Middle click
+ if (SETTINGS.get_boolean('preview-middle-click-close')) {
+ this._onCloseBtnClick()
+ }
+ break
+ case 3: // Right click
+ this._showContextMenu(e)
+ break
+ }
- return Clutter.EVENT_STOP;
+ return Clutter.EVENT_STOP
}
_cancelAnimateOut() {
- if (this.animatingOut) {
- this.animatingOut = false;
+ if (this.animatingOut) {
+ this.animatingOut = false
- Utils.stopAnimations(this);
- Utils.animate(this, getTweenOpts({ opacity: 255, width: this.cloneWidth, height: this.cloneHeight }));
- }
+ Utils.stopAnimations(this)
+ Utils.animate(
+ this,
+ getTweenOpts({
+ opacity: 255,
+ width: this.cloneWidth,
+ height: this.cloneHeight,
+ }),
+ )
+ }
}
_showContextMenu(e) {
- let coords = e.get_coords();
- let currentWorkspace = this._previewMenu.peekInitialWorkspaceIndex < 0 ?
- Utils.getCurrentWorkspace() :
- Utils.getWorkspaceByIndex(this._previewMenu.peekInitialWorkspaceIndex);
+ let coords = e.get_coords()
+ let currentWorkspace =
+ this._previewMenu.peekInitialWorkspaceIndex < 0
+ ? Utils.getCurrentWorkspace()
+ : Utils.getWorkspaceByIndex(
+ this._previewMenu.peekInitialWorkspaceIndex,
+ )
- Main.wm._showWindowMenu(null, this.window, Meta.WindowMenuType.WM, {
- x: coords[0],
- y: coords[1],
- width: 0,
- height: 0
- });
+ Main.wm._showWindowMenu(null, this.window, Meta.WindowMenuType.WM, {
+ x: coords[0],
+ y: coords[1],
+ width: 0,
+ height: 0,
+ })
- let menu = Main.wm._windowMenuManager._manager._menus[0];
+ let menu = Main.wm._windowMenuManager._manager._menus[0]
- menu.connect('open-state-changed', () => this._previewMenu.menu.sync_hover());
- this._previewMenu.menu.sync_hover();
+ menu.connect('open-state-changed', () =>
+ this._previewMenu.menu.sync_hover(),
+ )
+ this._previewMenu.menu.sync_hover()
- if (this.window.get_workspace() != currentWorkspace) {
- let menuItem = new PopupMenu.PopupMenuItem(_('Move to current Workspace') + ' [' + (currentWorkspace.index() + 1) + ']');
- let menuItems = menu.box.get_children();
- let insertIndex = Utils.findIndex(menuItems, c => c._delegate instanceof PopupMenu.PopupSeparatorMenuItem);
+ if (this.window.get_workspace() != currentWorkspace) {
+ let menuItem = new PopupMenu.PopupMenuItem(
+ _('Move to current Workspace') +
+ ' [' +
+ (currentWorkspace.index() + 1) +
+ ']',
+ )
+ let menuItems = menu.box.get_children()
+ let insertIndex = Utils.findIndex(
+ menuItems,
+ (c) => c._delegate instanceof PopupMenu.PopupSeparatorMenuItem,
+ )
- insertIndex = insertIndex >= 0 ? insertIndex : menuItems.length - 1;
- menu.addMenuItem(menuItem, insertIndex);
- menuItem.connect('activate', () => this.window.change_workspace(currentWorkspace));
- }
+ insertIndex = insertIndex >= 0 ? insertIndex : menuItems.length - 1
+ menu.addMenuItem(menuItem, insertIndex)
+ menuItem.connect('activate', () =>
+ this.window.change_workspace(currentWorkspace),
+ )
+ }
}
_removeWindowSignals() {
- if (this._titleWindowChangeId) {
- this.window.disconnect(this._titleWindowChangeId);
- this._titleWindowChangeId = 0;
- }
+ if (this._titleWindowChangeId) {
+ this.window.disconnect(this._titleWindowChangeId)
+ this._titleWindowChangeId = 0
+ }
}
_updateHeader() {
- if (headerHeight) {
- let iconTextureSize = SETTINGS.get_boolean('window-preview-use-custom-icon-size') ?
- SETTINGS.get_int('window-preview-custom-icon-size') :
- headerHeight / scaleFactor * .6;
- let icon = this._previewMenu.getCurrentAppIcon().app.create_icon_texture(iconTextureSize);
- let workspaceIndex = '';
- let workspaceStyle = null;
- let fontScale = DESKTOPSETTINGS.get_double('text-scaling-factor');
- let commonTitleStyles = 'color: ' + SETTINGS.get_string('window-preview-title-font-color') + ';' +
- 'font-size: ' + SETTINGS.get_int('window-preview-title-font-size') * fontScale + 'px;' +
- 'font-weight: ' + SETTINGS.get_string('window-preview-title-font-weight') + ';';
-
- this._iconBin.destroy_all_children();
- this._iconBin.add_child(icon);
+ if (headerHeight) {
+ let iconTextureSize = SETTINGS.get_boolean(
+ 'window-preview-use-custom-icon-size',
+ )
+ ? SETTINGS.get_int('window-preview-custom-icon-size')
+ : (headerHeight / scaleFactor) * 0.6
+ let icon = this._previewMenu
+ .getCurrentAppIcon()
+ .app.create_icon_texture(iconTextureSize)
+ let workspaceIndex = ''
+ let workspaceStyle = null
+ let fontScale = DESKTOPSETTINGS.get_double('text-scaling-factor')
+ let commonTitleStyles =
+ 'color: ' +
+ SETTINGS.get_string('window-preview-title-font-color') +
+ ';' +
+ 'font-size: ' +
+ SETTINGS.get_int('window-preview-title-font-size') * fontScale +
+ 'px;' +
+ 'font-weight: ' +
+ SETTINGS.get_string('window-preview-title-font-weight') +
+ ';'
- if (!SETTINGS.get_boolean('isolate-workspaces')) {
- workspaceIndex = (this.window.get_workspace().index() + 1).toString();
- workspaceStyle = 'margin: 0 4px 0 ' + (isLeftButtons ? Math.round((headerHeight - icon.width) * .5) + 'px' : '0') + '; padding: 0 4px;' +
- 'border: 2px solid ' + this._getRgbaColor(FOCUSED_COLOR_OFFSET, .8) + 'border-radius: 2px;' + commonTitleStyles;
- }
-
- this._workspaceIndicator.text = workspaceIndex;
- setStyle(this._workspaceIndicator, workspaceStyle);
+ this._iconBin.destroy_all_children()
+ this._iconBin.add_child(icon)
- this._titleWindowChangeId = this.window.connect('notify::title', () => this._updateWindowTitle());
- setStyle(this._windowTitle, 'max-width: 0px; padding-right: 4px;' + commonTitleStyles);
- this._updateWindowTitle();
+ if (!SETTINGS.get_boolean('isolate-workspaces')) {
+ workspaceIndex = (this.window.get_workspace().index() + 1).toString()
+ workspaceStyle =
+ 'margin: 0 4px 0 ' +
+ (isLeftButtons
+ ? Math.round((headerHeight - icon.width) * 0.5) + 'px'
+ : '0') +
+ '; padding: 0 4px;' +
+ 'border: 2px solid ' +
+ this._getRgbaColor(FOCUSED_COLOR_OFFSET, 0.8) +
+ 'border-radius: 2px;' +
+ commonTitleStyles
}
+
+ this._workspaceIndicator.text = workspaceIndex
+ setStyle(this._workspaceIndicator, workspaceStyle)
+
+ this._titleWindowChangeId = this.window.connect('notify::title', () =>
+ this._updateWindowTitle(),
+ )
+ setStyle(
+ this._windowTitle,
+ 'max-width: 0px; padding-right: 4px;' + commonTitleStyles,
+ )
+ this._updateWindowTitle()
+ }
}
_updateWindowTitle() {
- this._windowTitle.text = this.window.title;
+ this._windowTitle.text = this.window.title
}
_hideOrShowCloseButton(hide) {
- if (this._needsCloseButton) {
- Utils.animate(this._closeButtonBin, getTweenOpts({ opacity: hide ? 0 : 255 }));
- }
+ if (this._needsCloseButton) {
+ Utils.animate(
+ this._closeButtonBin,
+ getTweenOpts({ opacity: hide ? 0 : 255 }),
+ )
+ }
}
_getBackgroundColor(offset, alpha) {
- return 'background-color: ' + this._getRgbaColor(offset, alpha) +
- 'transition-duration:' + this._previewMenu.panel.dynamicTransparency.animationDuration;
+ return (
+ 'background-color: ' +
+ this._getRgbaColor(offset, alpha) +
+ 'transition-duration:' +
+ this._previewMenu.panel.dynamicTransparency.animationDuration
+ )
}
_getRgbaColor(offset, alpha) {
- alpha = Math.abs(alpha);
+ alpha = Math.abs(alpha)
- if (isNaN(alpha)) {
- alpha = alphaBg;
- }
+ if (isNaN(alpha)) {
+ alpha = alphaBg
+ }
- return Utils.getrgbaColor(this._previewMenu.panel.dynamicTransparency.backgroundColorRgb, alpha, offset);
+ return Utils.getrgbaColor(
+ this._previewMenu.panel.dynamicTransparency.backgroundColorRgb,
+ alpha,
+ offset,
+ )
}
_addClone(newCloneBin, animateSize) {
- let currentClones = this._previewBin.get_children();
- let newCloneOpts = getTweenOpts({ opacity: 255 });
-
- this._previewBin.add_child(newCloneBin);
+ let currentClones = this._previewBin.get_children()
+ let newCloneOpts = getTweenOpts({ opacity: 255 })
- if (currentClones.length) {
- let currentCloneBin = currentClones.pop();
- let currentCloneOpts = getTweenOpts({ opacity: 0, onComplete: () => currentCloneBin.destroy() });
+ this._previewBin.add_child(newCloneBin)
- if (newCloneBin.width > currentCloneBin.width) {
- newCloneOpts.width = newCloneBin.width;
- newCloneBin.width = currentCloneBin.width;
- } else {
- currentCloneOpts.width = newCloneBin.width;
- }
+ if (currentClones.length) {
+ let currentCloneBin = currentClones.pop()
+ let currentCloneOpts = getTweenOpts({
+ opacity: 0,
+ onComplete: () => currentCloneBin.destroy(),
+ })
- if (newCloneBin.height > currentCloneBin.height) {
- newCloneOpts.height = newCloneBin.height;
- newCloneBin.height = currentCloneBin.height;
- } else {
- currentCloneOpts.height = newCloneBin.height;
- }
-
- currentClones.forEach(c => c.destroy());
- Utils.animate(currentCloneBin, currentCloneOpts);
- } else if (animateSize) {
- newCloneBin.width = 0;
- newCloneBin.height = 0;
- newCloneOpts.width = this.cloneWidth;
- newCloneOpts.height = this.cloneHeight;
+ if (newCloneBin.width > currentCloneBin.width) {
+ newCloneOpts.width = newCloneBin.width
+ newCloneBin.width = currentCloneBin.width
+ } else {
+ currentCloneOpts.width = newCloneBin.width
}
- Utils.animate(newCloneBin, newCloneOpts);
- }
-
- _getWindowCloneBin(window) {
- let frameRect = window.get_frame_rect();
- let bufferRect = window.get_buffer_rect();
- let clone = new Clutter.Clone({ source: window.get_compositor_private() });
- let cloneBin = new St.Widget({
- opacity: 0,
- layout_manager: frameRect.width != bufferRect.width ||
- frameRect.height != bufferRect.height ?
- new WindowCloneLayout(frameRect, bufferRect) :
- new Clutter.BinLayout()
- });
-
- cloneBin.add_child(clone);
+ if (newCloneBin.height > currentCloneBin.height) {
+ newCloneOpts.height = newCloneBin.height
+ newCloneBin.height = currentCloneBin.height
+ } else {
+ currentCloneOpts.height = newCloneBin.height
+ }
- return cloneBin;
+ currentClones.forEach((c) => c.destroy())
+ Utils.animate(currentCloneBin, currentCloneOpts)
+ } else if (animateSize) {
+ newCloneBin.width = 0
+ newCloneBin.height = 0
+ newCloneOpts.width = this.cloneWidth
+ newCloneOpts.height = this.cloneHeight
+ }
+
+ Utils.animate(newCloneBin, newCloneOpts)
+ }
+
+ _getWindowCloneBin(window) {
+ let frameRect = window.get_frame_rect()
+ let bufferRect = window.get_buffer_rect()
+ let clone = new Clutter.Clone({ source: window.get_compositor_private() })
+ let cloneBin = new St.Widget({
+ opacity: 0,
+ layout_manager:
+ frameRect.width != bufferRect.width ||
+ frameRect.height != bufferRect.height
+ ? new WindowCloneLayout(frameRect, bufferRect)
+ : new Clutter.BinLayout(),
+ })
+
+ cloneBin.add_child(clone)
+
+ return cloneBin
}
_getBinSize() {
- let [fixedWidth, fixedHeight] = this._previewDimensions;
+ let [fixedWidth, fixedHeight] = this._previewDimensions
- return [
- aspectRatio.x.fixed ? fixedWidth + this._padding * 2 : -1,
- aspectRatio.y.fixed ? fixedHeight + this._padding * 2 : -1
- ];
+ return [
+ aspectRatio.x.fixed ? fixedWidth + this._padding * 2 : -1,
+ aspectRatio.y.fixed ? fixedHeight + this._padding * 2 : -1,
+ ]
}
_resizeClone(cloneBin, window) {
- let frameRect = cloneBin.layout_manager.frameRect || window.get_frame_rect();
- let [fixedWidth, fixedHeight] = this._previewDimensions;
- let ratio = Math.min(fixedWidth / frameRect.width, fixedHeight / frameRect.height, 1);
- let cloneWidth = frameRect.width * ratio;
- let cloneHeight = frameRect.height * ratio;
-
- let clonePaddingTB = cloneHeight < MIN_DIMENSION ? MIN_DIMENSION - cloneHeight : 0;
- let clonePaddingLR = cloneWidth < MIN_DIMENSION ? MIN_DIMENSION - cloneWidth : 0;
- let clonePaddingTop = clonePaddingTB * .5;
- let clonePaddingLeft = clonePaddingLR * .5;
-
- this.cloneWidth = cloneWidth + clonePaddingLR * scaleFactor;
- this.cloneHeight = cloneHeight + clonePaddingTB * scaleFactor;
+ let frameRect =
+ cloneBin.layout_manager.frameRect || window.get_frame_rect()
+ let [fixedWidth, fixedHeight] = this._previewDimensions
+ let ratio = Math.min(
+ fixedWidth / frameRect.width,
+ fixedHeight / frameRect.height,
+ 1,
+ )
+ let cloneWidth = frameRect.width * ratio
+ let cloneHeight = frameRect.height * ratio
- cloneBin.set_style('padding: ' + clonePaddingTop + 'px ' + clonePaddingLeft + 'px;');
- cloneBin.layout_manager.ratio = ratio;
- cloneBin.layout_manager.padding = [clonePaddingLeft * scaleFactor, clonePaddingTop * scaleFactor];
+ let clonePaddingTB =
+ cloneHeight < MIN_DIMENSION ? MIN_DIMENSION - cloneHeight : 0
+ let clonePaddingLR =
+ cloneWidth < MIN_DIMENSION ? MIN_DIMENSION - cloneWidth : 0
+ let clonePaddingTop = clonePaddingTB * 0.5
+ let clonePaddingLeft = clonePaddingLR * 0.5
- cloneBin.get_first_child().set_size(cloneWidth, cloneHeight);
+ this.cloneWidth = cloneWidth + clonePaddingLR * scaleFactor
+ this.cloneHeight = cloneHeight + clonePaddingTB * scaleFactor
+
+ cloneBin.set_style(
+ 'padding: ' + clonePaddingTop + 'px ' + clonePaddingLeft + 'px;',
+ )
+ cloneBin.layout_manager.ratio = ratio
+ cloneBin.layout_manager.padding = [
+ clonePaddingLeft * scaleFactor,
+ clonePaddingTop * scaleFactor,
+ ]
+
+ cloneBin.get_first_child().set_size(cloneWidth, cloneHeight)
}
_getPreviewDimensions() {
- let size = SETTINGS.get_int('window-preview-size') * scaleFactor;
- let w, h;
+ let size = SETTINGS.get_int('window-preview-size') * scaleFactor
+ let w, h
- if (this._previewMenu.isVertical) {
- w = size;
- h = w * aspectRatio.y.size / aspectRatio.x.size;
- } else {
- h = size;
- w = h * aspectRatio.x.size / aspectRatio.y.size;
- }
+ if (this._previewMenu.isVertical) {
+ w = size
+ h = (w * aspectRatio.y.size) / aspectRatio.x.size
+ } else {
+ h = size
+ w = (h * aspectRatio.x.size) / aspectRatio.y.size
+ }
- return [w, h];
+ return [w, h]
}
-});
-
-export const WindowCloneLayout = GObject.registerClass({
-}, class WindowCloneLayout extends Clutter.BinLayout {
+ },
+)
+export const WindowCloneLayout = GObject.registerClass(
+ {},
+ class WindowCloneLayout extends Clutter.BinLayout {
_init(frameRect, bufferRect) {
- super._init();
+ super._init()
- //the buffer_rect contains the transparent padding that must be removed
- this.frameRect = frameRect;
- this.bufferRect = bufferRect;
+ //the buffer_rect contains the transparent padding that must be removed
+ this.frameRect = frameRect
+ this.bufferRect = bufferRect
}
vfunc_allocate(actor, box) {
- let [width, height] = box.get_size();
+ let [width, height] = box.get_size()
- box.set_origin(
- (this.bufferRect.x - this.frameRect.x) * this.ratio + this.padding[0],
- (this.bufferRect.y - this.frameRect.y) * this.ratio + this.padding[1]
- );
+ box.set_origin(
+ (this.bufferRect.x - this.frameRect.x) * this.ratio + this.padding[0],
+ (this.bufferRect.y - this.frameRect.y) * this.ratio + this.padding[1],
+ )
- box.set_size(
- width + (this.bufferRect.width - this.frameRect.width) * this.ratio,
- height + (this.bufferRect.height - this.frameRect.height) * this.ratio
- );
+ box.set_size(
+ width + (this.bufferRect.width - this.frameRect.width) * this.ratio,
+ height + (this.bufferRect.height - this.frameRect.height) * this.ratio,
+ )
- actor.get_first_child().allocate(box);
+ actor.get_first_child().allocate(box)
}
-});
+ },
+)
export function setStyle(actor, style) {
- if (!isManualStyling) {
- actor.set_style(style);
- }
+ if (!isManualStyling) {
+ actor.set_style(style)
+ }
}
export function getTweenOpts(opts) {
- let defaults = {
- time: animationTime,
- transition: 'easeInOutQuad'
- };
+ let defaults = {
+ time: animationTime,
+ transition: 'easeInOutQuad',
+ }
- return Utils.mergeObjects(opts || {}, defaults);
+ return Utils.mergeObjects(opts || {}, defaults)
}
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 0000000..3f5af8f
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,583 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@eslint-community/eslint-utils@^4.2.0":
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56"
+ integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==
+ dependencies:
+ eslint-visitor-keys "^3.4.3"
+
+"@eslint-community/regexpp@^4.12.1":
+ version "4.12.1"
+ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
+ integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
+
+"@eslint/config-array@^0.19.0":
+ version "0.19.1"
+ resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.1.tgz#734aaea2c40be22bbb1f2a9dac687c57a6a4c984"
+ integrity sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==
+ dependencies:
+ "@eslint/object-schema" "^2.1.5"
+ debug "^4.3.1"
+ minimatch "^3.1.2"
+
+"@eslint/core@^0.10.0":
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.10.0.tgz#23727063c21b335f752dbb3a16450f6f9cbc9091"
+ integrity sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==
+ dependencies:
+ "@types/json-schema" "^7.0.15"
+
+"@eslint/eslintrc@^3.2.0":
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c"
+ integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==
+ dependencies:
+ ajv "^6.12.4"
+ debug "^4.3.2"
+ espree "^10.0.1"
+ globals "^14.0.0"
+ ignore "^5.2.0"
+ import-fresh "^3.2.1"
+ js-yaml "^4.1.0"
+ minimatch "^3.1.2"
+ strip-json-comments "^3.1.1"
+
+"@eslint/js@9.19.0", "@eslint/js@^9.19.0":
+ version "9.19.0"
+ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.19.0.tgz#51dbb140ed6b49d05adc0b171c41e1a8713b7789"
+ integrity sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==
+
+"@eslint/object-schema@^2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.5.tgz#8670a8f6258a2be5b2c620ff314a1d984c23eb2e"
+ integrity sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==
+
+"@eslint/plugin-kit@^0.2.5":
+ version "0.2.5"
+ resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz#ee07372035539e7847ef834e3f5e7b79f09e3a81"
+ integrity sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==
+ dependencies:
+ "@eslint/core" "^0.10.0"
+ levn "^0.4.1"
+
+"@humanfs/core@^0.19.1":
+ version "0.19.1"
+ resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77"
+ integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==
+
+"@humanfs/node@^0.16.6":
+ version "0.16.6"
+ resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e"
+ integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==
+ dependencies:
+ "@humanfs/core" "^0.19.1"
+ "@humanwhocodes/retry" "^0.3.0"
+
+"@humanwhocodes/module-importer@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
+ integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
+
+"@humanwhocodes/retry@^0.3.0":
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a"
+ integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==
+
+"@humanwhocodes/retry@^0.4.1":
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b"
+ integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==
+
+"@types/estree@^1.0.6":
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
+ integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
+
+"@types/json-schema@^7.0.15":
+ version "7.0.15"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
+ integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
+
+acorn-jsx@^5.3.2:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
+ integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
+
+acorn@^8.14.0:
+ version "8.14.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0"
+ integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
+
+ajv@^6.12.4:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
+ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
+argparse@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+callsites@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+ integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+chalk@^4.0.0:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+cross-spawn@^7.0.6:
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
+ integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+debug@^4.3.1, debug@^4.3.2:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
+ integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
+ dependencies:
+ ms "^2.1.3"
+
+deep-is@^0.1.3:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
+ integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
+
+escape-string-regexp@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
+ integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
+eslint-config-prettier@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.0.1.tgz#fbb03bfc8db0651df9ce4e8b7150d11c5fe3addf"
+ integrity sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==
+
+eslint-scope@^8.2.0:
+ version "8.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442"
+ integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^5.2.0"
+
+eslint-visitor-keys@^3.4.3:
+ version "3.4.3"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
+ integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
+
+eslint-visitor-keys@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45"
+ integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
+
+eslint@^9.19.0:
+ version "9.19.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.19.0.tgz#ffa1d265fc4205e0f8464330d35f09e1d548b1bf"
+ integrity sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.2.0"
+ "@eslint-community/regexpp" "^4.12.1"
+ "@eslint/config-array" "^0.19.0"
+ "@eslint/core" "^0.10.0"
+ "@eslint/eslintrc" "^3.2.0"
+ "@eslint/js" "9.19.0"
+ "@eslint/plugin-kit" "^0.2.5"
+ "@humanfs/node" "^0.16.6"
+ "@humanwhocodes/module-importer" "^1.0.1"
+ "@humanwhocodes/retry" "^0.4.1"
+ "@types/estree" "^1.0.6"
+ "@types/json-schema" "^7.0.15"
+ ajv "^6.12.4"
+ chalk "^4.0.0"
+ cross-spawn "^7.0.6"
+ debug "^4.3.2"
+ escape-string-regexp "^4.0.0"
+ eslint-scope "^8.2.0"
+ eslint-visitor-keys "^4.2.0"
+ espree "^10.3.0"
+ esquery "^1.5.0"
+ esutils "^2.0.2"
+ fast-deep-equal "^3.1.3"
+ file-entry-cache "^8.0.0"
+ find-up "^5.0.0"
+ glob-parent "^6.0.2"
+ ignore "^5.2.0"
+ imurmurhash "^0.1.4"
+ is-glob "^4.0.0"
+ json-stable-stringify-without-jsonify "^1.0.1"
+ lodash.merge "^4.6.2"
+ minimatch "^3.1.2"
+ natural-compare "^1.4.0"
+ optionator "^0.9.3"
+
+espree@^10.0.1, espree@^10.3.0:
+ version "10.3.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a"
+ integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==
+ dependencies:
+ acorn "^8.14.0"
+ acorn-jsx "^5.3.2"
+ eslint-visitor-keys "^4.2.0"
+
+esquery@^1.5.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7"
+ integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==
+ dependencies:
+ estraverse "^5.1.0"
+
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
+estraverse@^5.1.0, estraverse@^5.2.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
+ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+esutils@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+ integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-json-stable-stringify@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fast-levenshtein@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+ integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
+
+file-entry-cache@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f"
+ integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==
+ dependencies:
+ flat-cache "^4.0.0"
+
+find-up@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+ dependencies:
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
+
+flat-cache@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c"
+ integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==
+ dependencies:
+ flatted "^3.2.9"
+ keyv "^4.5.4"
+
+flatted@^3.2.9:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27"
+ integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==
+
+glob-parent@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+ dependencies:
+ is-glob "^4.0.3"
+
+globals@^14.0.0:
+ version "14.0.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e"
+ integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==
+
+globals@^15.14.0:
+ version "15.14.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-15.14.0.tgz#b8fd3a8941ff3b4d38f3319d433b61bbb482e73f"
+ integrity sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+ignore@^5.2.0:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
+ integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
+
+import-fresh@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
+ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+ dependencies:
+ parent-module "^1.0.0"
+ resolve-from "^4.0.0"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+ integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-glob@^4.0.0, is-glob@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+js-yaml@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
+json-buffer@3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
+ integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json-stable-stringify-without-jsonify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+ integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
+
+keyv@^4.5.4:
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
+ integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
+ dependencies:
+ json-buffer "3.0.1"
+
+levn@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+ integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+ dependencies:
+ prelude-ls "^1.2.1"
+ type-check "~0.4.0"
+
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
+
+lodash.merge@^4.6.2:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
+ integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+
+minimatch@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+ms@^2.1.3:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+ integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+ integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+
+optionator@^0.9.3:
+ version "0.9.4"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734"
+ integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==
+ dependencies:
+ deep-is "^0.1.3"
+ fast-levenshtein "^2.0.6"
+ levn "^0.4.1"
+ prelude-ls "^1.2.1"
+ type-check "^0.4.0"
+ word-wrap "^1.2.5"
+
+p-limit@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
+parent-module@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
+ integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+ dependencies:
+ callsites "^3.0.0"
+
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+prelude-ls@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+ integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+
+prettier@^3.4.2:
+ version "3.4.2"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.4.2.tgz#a5ce1fb522a588bf2b78ca44c6e6fe5aa5a2b13f"
+ integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==
+
+punycode@^2.1.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
+ integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
+
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+strip-json-comments@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+ integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+
+supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+type-check@^0.4.0, type-check@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+ integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+ dependencies:
+ prelude-ls "^1.2.1"
+
+uri-js@^4.2.2:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+ dependencies:
+ punycode "^2.1.0"
+
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+word-wrap@^1.2.5:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
+ integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
+
+yocto-queue@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==