diff --git a/Makefile b/Makefile index 46e2c0d..465b260 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ INSTALLNAME = dash-to-panel@jderose9.github.com # The command line passed variable VERSION is used to set the version string # in the metadata and in the generated zip-file. If no VERSION is passed, the -# version is pulled from the latest git tag and the current commit SHA1 is +# version is pulled from the latest git tag and the current commit SHA1 is # added to the metadata ifdef VERSION ifdef TARGET @@ -51,7 +51,7 @@ mergepo: potfile ./po/dash-to-panel.pot: $(TOLOCALIZE) mkdir -p po xgettext -k_ -kN_ -o po/dash-to-panel.pot --package-name "Dash To Panel" $(TOLOCALIZE) --from-code=UTF-8 - + for l in $(UI_MODULES) ; do \ intltool-extract --type=gettext/glade $$l; \ xgettext -k_ -kN_ -o po/dash-to-panel.pot $$l.h --join-existing --from-code=UTF-8; \ diff --git a/appIcons.js b/appIcons.js index 1ac175e..3bfad20 100644 --- a/appIcons.js +++ b/appIcons.js @@ -39,14 +39,14 @@ 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 { 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 { 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'; @@ -118,17 +118,20 @@ export const TaskbarAppIcon = GObject.registerClass({ this._previewMenu = previewMenu; this.iconAnimator = iconAnimator; this.lastClick = 0; + this._appicon_normalstyle = ''; + this._appicon_hoverstyle = ''; + this._appicon_pressedstyle = ''; super._init(appInfo.app, iconParams); this._timeoutsHandler = new Utils.TimeoutsHandler(); // Fix touchscreen issues before the listener is added by the parent constructor. - this._onTouchEvent = function(actor, event) { + 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)) { + } 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(); @@ -138,33 +141,33 @@ export const TaskbarAppIcon = GObject.registerClass({ return Clutter.EVENT_STOP; }; // Hack for missing TOUCH_END event. - this._onLeaveEvent = function(actor, 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({ 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._windowTitle = new St.Label({ + y_align: Clutter.ActorAlign.CENTER, + x_align: Clutter.ActorAlign.START, + style_class: 'overview-label' }); - + this._updateWindowTitle(); this._updateWindowTitleStyle(); @@ -187,18 +190,19 @@ export const TaskbarAppIcon = GObject.registerClass({ // Monitor windows-changes instead of app state. // Keep using the same Id and function callback (that is extended) - if(this._stateChangedId > 0) { + 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._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)); @@ -208,13 +212,13 @@ export const TaskbarAppIcon = GObject.registerClass({ 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 && + global.display.focus_window?.get_monitor() == this.dtpPanel.monitor.index && !this.dtpPanel.monitor.inFullscreen ) { this._resetDots(true); @@ -222,25 +226,34 @@ export const TaskbarAppIcon = GObject.registerClass({ } }) } else { - this._titleWindowChangeId = this.window.connect('notify::title', - this._updateWindowTitle.bind(this)); + this._titleWindowChangeId = this.window.connect('notify::title', + this._updateWindowTitle.bind(this)); this._minimizedWindowChangeId = this.window.connect('notify::minimized', - this._updateWindowTitleStyle.bind(this)); + 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._onOverviewWindowDragEnd.bind(this)); this._switchWorkspaceId = global.window_manager.connect('switch-workspace', - this._onSwitchWorkspace.bind(this)); + 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)), @@ -266,8 +279,13 @@ export const TaskbarAppIcon = GObject.registerClass({ 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)) - ] + 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); @@ -280,12 +298,14 @@ export const TaskbarAppIcon = GObject.registerClass({ // Used by TaskbarItemContainer to animate appIcons on hover getCloneButton() { - // The source of the clone is this._container, + // 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: this.child, + source: cloneSource, x: this.child.x, y: this.child.y, - width: this.child.width, height: this.child.height, + width: cloneSource.width, height: cloneSource.height, pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }), opacity: 255, reactive: false, @@ -304,19 +324,19 @@ export const TaskbarAppIcon = GObject.registerClass({ } shouldShowTooltip() { - if (!SETTINGS.get_boolean('show-tooltip') || + if (!SETTINGS.get_boolean('show-tooltip') || (!this.isLauncher && SETTINGS.get_boolean("show-window-previews") && - this.getAppIconInterestingWindows().length > 0)) { + this.getAppIconInterestingWindows().length > 0)) { return false; } else { - return this.hover && !this.window && - (!this._menu || !this._menu.isOpen) && - (this._previewMenu.getCurrentAppIcon() !== this); + return this.hover && !this.window && + (!this._menu || !this._menu.isOpen) && + (this._previewMenu.getCurrentAppIcon() !== this); } } _onAppIconHoverChanged() { - if (!SETTINGS.get_boolean('show-window-previews') || + if (!SETTINGS.get_boolean('show-window-previews') || (!this.window && !this._nWindows)) { return; } @@ -340,20 +360,20 @@ export const TaskbarAppIcon = GObject.registerClass({ this.app.disconnect(this._stateChangedId); this._stateChangedId = 0; } - - if(this._overviewWindowDragEndId) + + if (this._overviewWindowDragEndId) Main.overview.disconnect(this._overviewWindowDragEndId); - if(this._focusWindowChangedId) + if (this._focusWindowChangedId) global.display.disconnect(this._focusWindowChangedId); if (this._fullscreenId) Utils.DisplayWrapper.getScreen().disconnect(this._fullscreenId); - if(this._titleWindowChangeId) + if (this._titleWindowChangeId) this.window.disconnect(this._titleWindowChangeId); - if(this._minimizedWindowChangeId) + if (this._minimizedWindowChangeId) this.window.disconnect(this._minimizedWindowChangeId); if (this._windowEnteredMonitorId) { @@ -361,15 +381,21 @@ export const TaskbarAppIcon = GObject.registerClass({ Utils.DisplayWrapper.getScreen().disconnect(this._windowLeftMonitorId); } - if(this._switchWorkspaceId) + if (this._switchWorkspaceId) global.window_manager.disconnect(this._switchWorkspaceId); - if(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._scrollEventId) { this.disconnect(this._scrollEventId); @@ -415,7 +441,7 @@ export const TaskbarAppIcon = GObject.registerClass({ [rect.width, rect.height] = this.get_transformed_size(); let windows = this.window ? [this.window] : this.getAppIconInterestingWindows(true); - windows.forEach(function(w) { + windows.forEach(function (w) { w.set_icon_geometry(rect); }); } @@ -429,7 +455,7 @@ export const TaskbarAppIcon = GObject.registerClass({ 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 { @@ -452,9 +478,53 @@ export const TaskbarAppIcon = GObject.registerClass({ } } + _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'); + + // 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 = ''; + } + } + + _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(''); + } + } + + _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(''); + } + } + _onMouseScroll(actor, event) { 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)) { @@ -464,7 +534,7 @@ export const TaskbarAppIcon = GObject.registerClass({ let direction = Utils.getMouseScrollDirection(event); if (direction && !this._timeoutsHandler.getId(T2)) { - this._timeoutsHandler.add([T2, SETTINGS.get_int('scroll-icon-delay'), () => {}]); + this._timeoutsHandler.add([T2, SETTINGS.get_int('scroll-icon-delay'), () => { }]); let windows = this.getAppIconInterestingWindows(); @@ -472,7 +542,7 @@ export const TaskbarAppIcon = GObject.registerClass({ Utils.activateSiblingWindow(windows, direction, this.window); } } - + _showDots() { // Just update style if dots already exist if (this._focusedDots && this._unfocusedDots) { @@ -481,7 +551,7 @@ export const TaskbarAppIcon = GObject.registerClass({ } if (!this._isGroupApps) { - this._focusedDots = new St.Widget({ + this._focusedDots = new St.Widget({ layout_manager: new Clutter.BinLayout(), x_expand: true, y_expand: true, visible: false @@ -492,23 +562,23 @@ export const TaskbarAppIcon = GObject.registerClass({ this.disconnect(mappedId); }); } else { - this._focusedDots = new St.DrawingArea(), - this._unfocusedDots = new St.DrawingArea(); - + 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._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._updateWindows(); this._timeoutsHandler.add([T3, 0, () => { @@ -526,7 +596,7 @@ export const TaskbarAppIcon = GObject.registerClass({ 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); @@ -560,8 +630,8 @@ export const TaskbarAppIcon = GObject.registerClass({ 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'); + 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; @@ -573,16 +643,16 @@ export const TaskbarAppIcon = GObject.registerClass({ 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); + '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._focusedDots) { this._displayProperIndicator(); } @@ -592,17 +662,17 @@ export const TaskbarAppIcon = GObject.registerClass({ _setIconStyle(isFocused) { let inlineStyle = 'margin: 0;'; - if(SETTINGS.get_boolean('focus-highlight') && - this._checkIfFocusedApp() && !this.isLauncher && - (!this.window || isFocused) && !this._isThemeProvidingIndicator() && this._checkIfMonitorHasFocus()) { + 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) { + if (!this.window) { let containerWidth = this._dtpIconContainer.get_width() / Utils.getScaleFactor(); - let backgroundSize = containerWidth + "px " + - (containerWidth - (pos == DOT_POSITION.BOTTOM ? highlightMargin : 0)) + "px;"; + let backgroundSize = containerWidth + "px " + + (containerWidth - (pos == DOT_POSITION.BOTTOM ? highlightMargin : 0)) + "px;"; if (focusedDotStyle == DOT_STYLE.CILIORA || focusedDotStyle == DOT_STYLE.SEGMENTED) highlightMargin += 1; @@ -614,17 +684,18 @@ export const TaskbarAppIcon = GObject.registerClass({ 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; + inlineStyle += "background-image: url('" + EXTENSION_PATH + bgSvg + ".svg');" + + "background-position: 0 " + (pos == DOT_POSITION.TOP ? highlightMargin : 0) + "px;" + + "background-size: " + backgroundSize; } } let highlightColor = this._getFocusHighlightColor(); - inlineStyle += "background-color: " + cssHexTocssRgba(highlightColor, SETTINGS.get_int('focus-highlight-opacity') * 0.01); + inlineStyle += "background-color: " + cssHexTocssRgba(highlightColor, SETTINGS.get_int('focus-highlight-opacity') * 0.01) + ";"; + inlineStyle += this._appicon_normalstyle; } - - if(this._dotsContainer.get_style() != inlineStyle) { + + if (this._dotsContainer.get_style() != inlineStyle) { this._dotsContainer.set_style(inlineStyle); } } @@ -634,17 +705,30 @@ export const TaskbarAppIcon = GObject.registerClass({ } _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') || + 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() { - let padding = getIconPadding(this.dtpPanel.monitor.index); - let margin = SETTINGS.get_int('appicon-margin'); + 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'); - this.set_style('padding:' + (this.dtpPanel.checkIfVertical() ? margin + 'px 0' : '0 ' + margin + '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;'); } @@ -724,10 +808,10 @@ export const TaskbarAppIcon = GObject.registerClass({ this._setIconStyle(isFocused); - if(!this._isGroupApps) { + 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(); @@ -744,39 +828,39 @@ export const TaskbarAppIcon = GObject.registerClass({ let newFocusedDotsOpacity = 0; let newUnfocusedDotsSize = 0; let newUnfocusedDotsOpacity = 0; - + isFocused = this._checkIfFocusedApp() && this._checkIfMonitorHasFocus(); this._timeoutsHandler.add([T6, 0, () => { - if(isFocused) + if (isFocused) this.add_style_class_name('focused'); else this.remove_style_class_name('focused'); }]); - if(this._focusedIsWide) { + 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) { + + 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)) + ((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); @@ -787,16 +871,16 @@ export const TaskbarAppIcon = GObject.registerClass({ _animateDotDisplay(dots, newSize, otherDots, newOtherOpacity, sizeProp, duration) { Utils.stopAnimations(dots) - let tweenOpts = { + let tweenOpts = { time: duration, transition: 'easeInOutCubic', - onComplete: () => { - if(newOtherOpacity > 0) + onComplete: () => { + if (newOtherOpacity > 0) otherDots.opacity = newOtherOpacity; } }; - if(newOtherOpacity == 0) + if (newOtherOpacity == 0) otherDots.opacity = newOtherOpacity; tweenOpts[sizeProp] = newSize; @@ -806,7 +890,7 @@ export const TaskbarAppIcon = GObject.registerClass({ _isFocusedWindow() { let focusedWindow = global.display.focus_window; - + while (focusedWindow) { if (focusedWindow == this.window) { return true; @@ -819,9 +903,9 @@ export const TaskbarAppIcon = GObject.registerClass({ } _isWideDotStyle(dotStyle) { - return dotStyle == DOT_STYLE.SEGMENTED || - dotStyle == DOT_STYLE.CILIORA || - dotStyle == DOT_STYLE.METRO || + return dotStyle == DOT_STYLE.SEGMENTED || + dotStyle == DOT_STYLE.CILIORA || + dotStyle == DOT_STYLE.METRO || dotStyle == DOT_STYLE.SOLID; } @@ -829,8 +913,8 @@ export const TaskbarAppIcon = GObject.registerClass({ // 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()); + return (this.icon.get_stage() && + this.icon.get_theme_node().get_border_image()); } activate(button, modifiers, handleAsGrouped) { @@ -854,7 +938,7 @@ export const TaskbarAppIcon = GObject.registerClass({ let buttonAction = 0; let doubleClick; - if (button && button == 2 ) { + if (button && button == 2) { if (modifiers & Clutter.ModifierType.SHIFT_MASK) buttonAction = SETTINGS.get_string('shift-middle-click-action'); else @@ -892,23 +976,23 @@ export const TaskbarAppIcon = GObject.registerClass({ //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') && + 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(); + this.window.minimize(); } else { Main.activateWindow(this.window); } - + break; - + case "LAUNCH": this._launchNewInstance(); break; case "QUIT": this.window.delete(global.get_current_time()); - break; + break; } } else { //grouped application behaviors @@ -919,21 +1003,21 @@ export const TaskbarAppIcon = GObject.registerClass({ 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 (!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; + let all_windows = (button == 1 && !modifiers) || doubleClick; minimizeWindow(this.app, all_windows, monitor); } else @@ -942,10 +1026,10 @@ export const TaskbarAppIcon = GObject.registerClass({ else this.app.activate(); break; - + case "CYCLE": - if (!Main.overview._shown){ - if (appHasFocus) + if (!Main.overview._shown) { + if (appHasFocus) cycleThroughWindows(this.app, false, false, monitor); else { activateFirstWindow(this.app, monitor); @@ -955,8 +1039,8 @@ export const TaskbarAppIcon = GObject.registerClass({ this.app.activate(); break; case "CYCLE-MIN": - if (!Main.overview._shown){ - if (appHasFocus || (recentlyClickedApp == this.app && recentlyClickedAppWindows[recentlyClickedAppIndex % recentlyClickedAppWindows.length] == "MINIMIZE")) + 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); @@ -981,10 +1065,10 @@ export const TaskbarAppIcon = GObject.registerClass({ minimizeWindow(this.app, true, monitor); } else if (previewedAppIcon != this) { this._previewMenu.open(this); - } - + } + this.emit('sync-tooltip'); - } + } } else this.app.activate(); @@ -998,7 +1082,7 @@ export const TaskbarAppIcon = GObject.registerClass({ activateFirstWindow(this.app, monitor); } else { cycleThroughWindows(this.app, false, false, monitor); - } + } } else this.app.activate(); @@ -1020,7 +1104,7 @@ export const TaskbarAppIcon = GObject.registerClass({ _launchNewInstance(ctrlPressed) { let maybeAnimate = () => SETTINGS.get_boolean('animate-window-launch') && this.animateLaunch() - if ((ctrlPressed || this.app.state == Shell.AppState.RUNNING) && + if ((ctrlPressed || this.app.state == Shell.AppState.RUNNING) && this.app.can_open_new_window()) { maybeAnimate(); this.app.open_new_window(-1); @@ -1038,15 +1122,15 @@ export const TaskbarAppIcon = GObject.registerClass({ _updateWindows() { let windows = [this.window]; - + if (!this.window) { windows = this.getAppIconInterestingWindows(); - + this._nWindows = windows.length; - - for (let i = 1; i <= MAX_INDICATORS; i++){ - let className = 'running'+i; - if(i != this._nWindows) + + 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); @@ -1078,15 +1162,15 @@ export const TaskbarAppIcon = GObject.registerClass({ color = themeNode.get_background_color(); // theme didn't provide one, use a default - if(color.alpha == 0) color = fallbackColor; + if (color.alpha == 0) color = fallbackColor; } - } else if(SETTINGS.get_boolean('dot-color-override')) { + } else if (SETTINGS.get_boolean('dot-color-override')) { let dotColorSettingPrefix = 'dot-color-'; - - if(!isFocused && SETTINGS.get_boolean('dot-color-unfocused-different')) + + 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]; + 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 @@ -1094,7 +1178,7 @@ export const TaskbarAppIcon = GObject.registerClass({ color = themeNode.get_background_color(); // theme didn't provide one, use a default - if(color.alpha == 0) color = fallbackColor; + if (color.alpha == 0) color = fallbackColor; } return color; @@ -1175,13 +1259,13 @@ export const TaskbarAppIcon = GObject.registerClass({ let dist; let indicatorSize; let translate; - let preDraw = () => {}; + 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; @@ -1243,7 +1327,7 @@ export const TaskbarAppIcon = GObject.registerClass({ } cr.fill(); } - + cr.$dispose(); } @@ -1271,12 +1355,12 @@ export const TaskbarAppIcon = GObject.registerClass({ // 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 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;'; + 'border-radius: ' + this.icon.iconSize + 'px;' + + 'height: ' + size + 'px;'; if (fixedSize || label.get_text().length == 1) { style += 'width: ' + size + 'px;'; @@ -1295,16 +1379,16 @@ export const TaskbarAppIcon = GObject.registerClass({ toggleNumberOverlay(activate) { if (activate && this._numberOverlayOrder > -1) - this._numberOverlayBin.show(); + this._numberOverlayBin.show(); else - this._numberOverlayBin.hide(); + this._numberOverlayBin.hide(); } handleDragOver(source, actor, x, y, time) { if (source == Main.xdndHandler) { this._previewMenu.close(true); } - + return DND.DragMotionResult.CONTINUE; } @@ -1312,19 +1396,19 @@ export const TaskbarAppIcon = GObject.registerClass({ 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){ +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()){ + 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) + if (!param) break; } } @@ -1334,7 +1418,7 @@ export function minimizeWindow(app, param, monitor){ * By default only non minimized windows are activated. * This activates all windows in the current workspace. */ -export function activateAllWindows(app, monitor){ +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. @@ -1346,14 +1430,14 @@ export function activateAllWindows(app, monitor){ if (windows.length <= 0) return; - for (let i = windows.length - 1; i >= 0; i--){ - if (windows[i].get_workspace().index() == activeWorkspace){ + 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){ +export function activateFirstWindow(app, monitor) { let windows = getInterestingWindows(app, monitor); Main.activateWindow(windows[0]); @@ -1362,16 +1446,16 @@ export function activateFirstWindow(app, monitor){ 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; + let MEMORY_TIME = 3000; let app_windows = getInterestingWindows(app, monitor); - if(shouldMinimize) + if (shouldMinimize) app_windows.push("MINIMIZE"); if (recentlyClickedAppLoopId > 0) GLib.Source.remove(recentlyClickedAppLoopId); - + recentlyClickedAppLoopId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, MEMORY_TIME, resetRecentlyClickedApp); @@ -1394,8 +1478,8 @@ export function cycleThroughWindows(app, reversed, shouldMinimize, monitor) { recentlyClickedAppIndex++; } let index = recentlyClickedAppIndex % recentlyClickedAppWindows.length; - - if(recentlyClickedAppWindows[index] === "MINIMIZE") + + if (recentlyClickedAppWindows[index] === "MINIMIZE") minimizeWindow(app, true, monitor); else Main.activateWindow(recentlyClickedAppWindows[index]); @@ -1405,8 +1489,8 @@ export function resetRecentlyClickedApp() { if (recentlyClickedAppLoopId > 0) GLib.Source.remove(recentlyClickedAppLoopId); - recentlyClickedAppLoopId=0; - recentlyClickedApp =null; + recentlyClickedAppLoopId = 0; + recentlyClickedApp = null; recentlyClickedAppWindows = null; recentlyClickedAppIndex = 0; recentlyClickedAppMonitorIndex = null; @@ -1424,25 +1508,25 @@ export function closeAllWindows(app, monitor) { // nautilus desktop window. export function getInterestingWindows(app, monitor, isolateMonitors) { let windows = ( - app ? - app.get_windows() : + app ? + app.get_windows() : global.get_window_actors().map(wa => wa.get_meta_window()) - ).filter(w => !w.skip_taskbar); + ).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(); + 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) { + windows = windows.filter(function (w) { return w.get_monitor() == monitor.index; }); } - + return windows; } @@ -1485,7 +1569,7 @@ export class TaskbarSecondaryMenu extends AppMenu.AppMenu { this._showSingleWindows = true; // Remove "Show Details" menu item - if(!SETTINGS.get_boolean('secondarymenu-contains-showdetails')) { + if (!SETTINGS.get_boolean('secondarymenu-contains-showdetails')) { let existingMenuItems = this._getMenuItems(); for (let i = 0; i < existingMenuItems.length; i++) { let item = existingMenuItems[i]; @@ -1503,10 +1587,10 @@ export class TaskbarSecondaryMenu extends AppMenu.AppMenu { } updateQuitText() { - let count = this.sourceActor.window ? 1 : + let count = this.sourceActor.window ? 1 : getInterestingWindows(this._app, this.sourceActor.dtpPanel.monitor).length; - if ( count > 0) { + if (count > 0) { let quitFromTaskbarMenuText = ""; if (count == 1) quitFromTaskbarMenuText = _("Quit"); @@ -1519,17 +1603,17 @@ export class TaskbarSecondaryMenu extends AppMenu.AppMenu { _quitFromTaskbar() { let time = global.get_current_time() - let windows = + let windows = this.sourceActor.window ? // ungrouped applications - [this.sourceActor.window] : - getInterestingWindows(this._app, this.sourceActor.dtpPanel.monitor) - + [this.sourceActor.window] : + getInterestingWindows(this._app, this.sourceActor.dtpPanel.monitor) + 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++)); - + return GLib.SOURCE_REMOVE; }); } @@ -1555,7 +1639,7 @@ export function ItemShowLabel() { let [stageX, stageY] = this.get_transformed_position(); let node = this.label.get_theme_node(); - let itemWidth = this.allocation.x2 - this.allocation.x1; + let itemWidth = this.allocation.x2 - this.allocation.x1; let itemHeight = this.allocation.y2 - this.allocation.y1; let labelWidth = this.label.get_width(); @@ -1572,19 +1656,19 @@ export function ItemShowLabel() { let x = stageX + xOffset let y = stageY + (itemHeight - labelHeight) * .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 @@ -1593,20 +1677,20 @@ export function ItemShowLabel() { // Leave a few pixel gap let gap = LABEL_GAP; let monitor = Main.layoutManager.findMonitorForActor(this); - if ( x - monitor.x < gap) + 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; + 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)); - let duration = Dash.DASH_ITEM_LABEL_SHOW_TIME; - + let duration = Dash.DASH_ITEM_LABEL_SHOW_TIME; + if (duration > 1) { duration /= 1000; } - - Utils.animate(this.label, { + + Utils.animate(this.label, { opacity: 255, time: duration, transition: 'easeOutQuad', @@ -1660,11 +1744,13 @@ export const ShowAppsIconWrapper = class extends EventEmitter { 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) }); @@ -1680,10 +1766,10 @@ export const ShowAppsIconWrapper = class extends EventEmitter { 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) { @@ -1702,7 +1788,7 @@ export const ShowAppsIconWrapper = class extends EventEmitter { _onTouchEvent(actor, event) { if (event.type() == Clutter.EventType.TOUCH_BEGIN) - this._setPopupTimeout(); + this._setPopupTimeout(); return Clutter.EVENT_PROPAGATE; } @@ -1759,8 +1845,8 @@ export const ShowAppsIconWrapper = class extends EventEmitter { } shouldShowTooltip() { - return SETTINGS.get_boolean('show-tooltip') && - (this.actor.hover && (!this._menu || !this._menu.isOpen)); + return SETTINGS.get_boolean('show-tooltip') && + (this.actor.hover && (!this._menu || !this._menu.isOpen)); } destroy() { @@ -1864,7 +1950,7 @@ export const MyShowAppsIconMenu = class extends PopupMenu.PopupMenu { let settingsMenuItem = this._appendMenuItem(_('Dash to Panel Settings')); settingsMenuItem.connect('activate', () => DTP_EXTENSION.openPreferences()) - if(this.sourceActor == Main.layoutManager.dummyCursor) { + 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)); @@ -1877,7 +1963,7 @@ export const MyShowAppsIconMenu = class extends PopupMenu.PopupMenu { if (GLib.find_program_in_path(info.cmd[0])) { let item = this._appendMenuItem(_(info.title)); - item.connect('activate', function() { + item.connect('activate', function () { print("activated: " + info.title); Util.spawn(info.cmd); }); @@ -1886,12 +1972,12 @@ export const MyShowAppsIconMenu = class extends PopupMenu.PopupMenu { return null; } - + _appendList(commandList, titleList) { if (commandList.length != titleList.length) { return; } - + for (let entry = 0; entry < commandList.length; entry++) { this._appendItem({ title: titleList[entry], @@ -1914,7 +2000,7 @@ export const MyShowAppsIconMenu = class extends PopupMenu.PopupMenu { }; -export const getIconContainerStyle = function(isVertical) { +export const getIconContainerStyle = function (isVertical) { let style = 'padding: '; if (SETTINGS.get_boolean('group-apps')) { diff --git a/panel.js b/panel.js index d025b9b..a0bfdac 100644 --- a/panel.js +++ b/panel.js @@ -17,13 +17,13 @@ * 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. */ @@ -85,7 +85,7 @@ export const Panel = GObject.registerClass({ // 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') && + this.isPrimary = !isStandalone || (SETTINGS.get_boolean('stockgs-keep-top-panel') && monitor == panelManager.dtpPrimaryMonitor); this._sessionStyle = null; @@ -144,20 +144,20 @@ export const Panel = GObject.registerClass({ }); } - // Create a wrapper around the real showAppsIcon in order to add a popupMenu. Most of + // 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, + this.panel, [ - 'button-press-event', + 'button-press-event', 'touch-event' ], this._onButtonPress.bind(this) @@ -167,7 +167,7 @@ export const Panel = GObject.registerClass({ 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 }); } @@ -180,7 +180,7 @@ export const Panel = GObject.registerClass({ } this.geom = this.getGeometry(); - + this._setPanelPosition(); if (!this.isStandalone) { @@ -209,13 +209,13 @@ export const Panel = GObject.registerClass({ }; 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()); @@ -225,14 +225,14 @@ export const Panel = GObject.registerClass({ this._signalsHandler.add( // this is to catch changes to the theme or window scale factor [ - Utils.getStageTheme(), - 'changed', + Utils.getStageTheme(), + 'changed', () => (this._resetGeometry(), this._setShowDesktopButtonStyle()), ], [ // sync hover after a popupmenu is closed this.taskbar, - 'menu-closed', + 'menu-closed', () => this.panel.sync_hover() ], [ @@ -255,10 +255,10 @@ export const Panel = GObject.registerClass({ ], [ this.statusArea.activities, - 'captured-event', + '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 + //temporarily use as primary the monitor on which the activities btn was clicked this.panelManager.setFocusedMonitor(this.monitor); } } @@ -302,7 +302,7 @@ export const Panel = GObject.registerClass({ if (this.statusArea.dateMenu) { this._formatVerticalClock(); - + this._signalsHandler.add([ this.statusArea.dateMenu._clock, 'notify::clock', @@ -324,7 +324,7 @@ export const Panel = GObject.registerClass({ this._timeoutsHandler.destroy(); this._signalsHandler.destroy(); - + this.panel.remove_child(this.taskbar.actor); if (this.intellihide) { @@ -366,14 +366,14 @@ export const Panel = GObject.registerClass({ ['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, + container, Math.min(container._dtpOriginalIndex, originalParent.get_children().length - 1) ); - + delete container._dtpOriginalParent; delete container._dtpOriginalIndex; }); @@ -384,7 +384,7 @@ export const Panel = GObject.registerClass({ delete Utils.getIndicators(this.statusArea[systemMenuName]._volumeOutput)._dtpIgnoreScroll; this._injectionManager.clear(); - + this.panel._delegate = this.panel; } else { this._removePanelMenu('dateMenu'); @@ -405,16 +405,16 @@ export const Panel = GObject.registerClass({ } else if (position == Pos.BOTTOM) { return St.Side.BOTTOM; } - + return St.Side.LEFT; } checkIfVertical() { let position = this.getPosition(); - + return (position == St.Side.LEFT || position == St.Side.RIGHT); } - + getOrientation() { return (this.checkIfVertical() ? 'vertical' : 'horizontal'); } @@ -452,7 +452,7 @@ export const Panel = GObject.registerClass({ currentPosition = Pos.STACKED_BR; } - if (!previousPosition || + 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)) { @@ -486,6 +486,8 @@ export const Panel = GObject.registerClass({ SETTINGS, [ 'changed::panel-sizes', + 'changed::appicon-margin-todesktop', + 'changed::appicon-margin-toscreenborder', 'changed::group-apps' ], () => this._resetGeometry() @@ -514,7 +516,7 @@ export const Panel = GObject.registerClass({ 'changed::clock-format', () => { this._clockFormat = null; - + if (isVertical) { this._formatVerticalClock(); } @@ -544,7 +546,7 @@ export const Panel = GObject.registerClass({ container.insert_child_at_index(this.statusArea[propName].container, 0); } } - + _removePanelMenu(propName) { if (this.statusArea[propName]) { let parent = this.statusArea[propName].container.get_parent(); @@ -555,8 +557,8 @@ export const Panel = GObject.registerClass({ //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 + //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]; @@ -619,7 +621,7 @@ export const Panel = GObject.registerClass({ let x = 0, y = 0; let w = 0, h = 0; - const panelSize = PanelSettings.getPanelSize(SETTINGS, this.monitor.index); + 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) { @@ -660,7 +662,7 @@ export const Panel = GObject.registerClass({ if (this.checkIfVertical()) { let viewHeight = this.monitor.height - gsTopPanelOffset; - + if (anchor === Pos.MIDDLE) { anchorPlaceOnMonitor = (viewHeight - h) / 2; } else if (anchor === Pos.END) { @@ -681,7 +683,7 @@ export const Panel = GObject.registerClass({ } return { - x, y, + x, y, w, h, lrPadding, tbPadding, @@ -691,11 +693,11 @@ export const Panel = GObject.registerClass({ _setAllocationMap() { this.allocationMap = {}; - let setMap = (name, actor) => this.allocationMap[name] = { + let setMap = (name, actor) => this.allocationMap[name] = { actor: actor, - box: new Clutter.ActorBox() + 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); @@ -772,19 +774,19 @@ export const Panel = GObject.registerClass({ brSize += refGroup.size; } } - + if (group.isCentered) { availableSize -= Math.max(tlSize, brSize) * 2; } else { availableSize -= tlSize + brSize; } - + if (availableSize < group.size) { expandable.natSize -= (group.size - availableSize) * (group.isCentered && !Pos.checkIfCentered(expandable.position) ? .5 : 1); assignGroupSize(group, true); } } - + if (group.isCentered) { startPosition = tlLimit + (brLimit - tlLimit - group.size) * .5; } else if (group.position == Pos.STACKED_BR) { @@ -833,9 +835,9 @@ export const Panel = GObject.registerClass({ let prevGroup = this._elementGroups[i - 1]; let nextGroup = this._elementGroups[i + 1]; - let prevLimit = prevGroup && prevGroup.fixed ? prevGroup[this.varCoord.c2] : + 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] : + 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) { @@ -860,7 +862,7 @@ export const Panel = GObject.registerClass({ // 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); }); @@ -892,7 +894,7 @@ export const Panel = GObject.registerClass({ } else { const targetActor = global.stage.get_event_actor(event); - if (Main.modalCount > 0 || targetActor != actor || + if (Main.modalCount > 0 || targetActor != actor || (!isPress && type != Clutter.EventType.TOUCH_BEGIN) || (isPress && button != 1)) { return Clutter.EVENT_PROPAGATE; @@ -956,7 +958,7 @@ export const Panel = GObject.registerClass({ actor.vertical = isVertical; } else if ( actor != this.statusArea.appMenu && - ((actor._delegate || actor) instanceof PanelMenu.ButtonBox || actor == this.statusArea.quickSettings) + ((actor._delegate || actor) instanceof PanelMenu.ButtonBox || actor == this.statusArea.quickSettings) ) { let child = actor.get_first_child(); @@ -983,7 +985,7 @@ export const Panel = GObject.registerClass({ }; _set(actor, false); - + if (isVertical) _set(actor, isVertical); } @@ -994,7 +996,7 @@ export const Panel = GObject.registerClass({ delete actor._dtpVisibleId; delete actor._dtpDestroyId; - + this._unmappedButtons.splice(this._unmappedButtons.indexOf(actor), 1); } @@ -1008,16 +1010,16 @@ export const Panel = GObject.registerClass({ 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(); - + 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 + //on gnome-shell 3.36.4, the clockdisplay isn't ellipsize anymore, so set it back clockText.ellipsize = Pango.EllipsizeMode.END; } @@ -1029,8 +1031,8 @@ export const Panel = GObject.registerClass({ datetimeParts = [datetimeParts.join(' '), time]; } - if (!setClockText(datetime) && - !setClockText(datetimeParts) && + if (!setClockText(datetime) && + !setClockText(datetimeParts) && !setClockText(time)) { let timeParts = time.split('∶'); @@ -1078,7 +1080,7 @@ export const Panel = GObject.registerClass({ }]); } }); - + this._showDesktopButton.connect('leave-event', () => { this._showDesktopButton.remove_style_class_name(this._getBackgroundBrightness() ? 'showdesktop-button-light-hovered' : 'showdesktop-button-dark-hovered'); @@ -1136,7 +1138,7 @@ export const Panel = GObject.registerClass({ time: time, transition: 'easeOutQuad' }; - + Utils.animateWindowOpacity(w.get_compositor_private(), tweenOpts); } }); @@ -1168,14 +1170,14 @@ export const Panel = GObject.registerClass({ windows.forEach(function(w) { w.minimize(); }); - + this._restoreWindowList = windows; this._timeoutsHandler.add([T5, 20, () => this._signalsHandler.addWithLabel( - label, + label, [ - tracker, - 'notify::focus-app', + tracker, + 'notify::focus-app', () => this._restoreWindowList = null ] )]); @@ -1208,7 +1210,7 @@ export const Panel = GObject.registerClass({ 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; diff --git a/prefs.js b/prefs.js index 30eabb9..db51cdb 100644 --- a/prefs.js +++ b/prefs.js @@ -160,7 +160,7 @@ const Preferences = class { 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']); @@ -168,6 +168,7 @@ const Preferences = class { // 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'); @@ -226,6 +227,8 @@ const Preferences = class { 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; @@ -394,7 +397,7 @@ const Preferences = class { _displayPanelPositionsForMonitor(monitorIndex) { let taskbarListBox = this._builder.get_object('taskbar_display_listbox'); - + while(taskbarListBox.get_first_child()) { taskbarListBox.remove(taskbarListBox.get_first_child()); @@ -420,7 +423,7 @@ const Preferences = class { }); child = child.get_next_sibling(); } - + monitors.forEach(m => panelElementPositionsSettings[m] = newPanelElementPositions); this._settings.set_string('panel-element-positions', JSON.stringify(panelElementPositionsSettings)); }; @@ -479,7 +482,7 @@ const Preferences = class { 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); @@ -501,7 +504,7 @@ const Preferences = class { _createPreferencesDialog(title, content, reset_function = null) { let dialog; - + dialog = new Gtk.Dialog({ title: title, transient_for: this.notebook.get_root(), use_header_bar: true, @@ -589,7 +592,7 @@ const Preferences = class { _showDesktopButtonOptions() { let box = this._builder.get_object('box_show_showdesktop_options'); - + let dialog = this._createPreferencesDialog(_('Show Desktop options'), box, () => { // restore default settings @@ -638,6 +641,14 @@ const Preferences = class { .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) => { @@ -701,6 +712,12 @@ const Preferences = class { .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() { @@ -863,7 +880,7 @@ const Preferences = class { 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', @@ -873,7 +890,7 @@ const Preferences = class { 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)); @@ -944,7 +961,7 @@ const Preferences = class { 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); @@ -952,7 +969,7 @@ const Preferences = class { 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); @@ -1127,7 +1144,7 @@ const Preferences = class { 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); @@ -1160,7 +1177,7 @@ const Preferences = class { 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', @@ -1170,7 +1187,7 @@ const Preferences = class { 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) => { @@ -1208,7 +1225,7 @@ const Preferences = class { this._settings.bind('intellihide-use-pressure', this._builder.get_object('intellihide_use_pressure_switch'), 'active', - Gio.SettingsBindFlags.DEFAULT); + Gio.SettingsBindFlags.DEFAULT); this._settings.bind('intellihide-use-pressure', this._builder.get_object('intellihide_use_pressure_options'), @@ -1285,7 +1302,7 @@ const Preferences = class { 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')); @@ -1357,7 +1374,7 @@ const Preferences = class { 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', @@ -1366,7 +1383,7 @@ const Preferences = class { this._settings.bind('show-running-apps', this._builder.get_object('show_runnning_apps_switch'), 'active', - Gio.SettingsBindFlags.DEFAULT); + Gio.SettingsBindFlags.DEFAULT); this._setPreviewTitlePosition(); @@ -1395,7 +1412,7 @@ const Preferences = class { 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')); @@ -1422,7 +1439,7 @@ const Preferences = class { 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')); @@ -1430,7 +1447,7 @@ const Preferences = class { 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')); @@ -1484,7 +1501,7 @@ const Preferences = class { 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', @@ -1497,7 +1514,7 @@ const Preferences = class { 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', @@ -1568,7 +1585,7 @@ const Preferences = class { 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()); @@ -1588,7 +1605,7 @@ const Preferences = class { dialog.show(); }); - + this._settings.bind('isolate-workspaces', this._builder.get_object('isolate_workspaces_switch'), 'active', @@ -1651,7 +1668,7 @@ const Preferences = class { this._settings.bind('group-apps-use-launchers', this._builder.get_object('group_apps_use_launchers_switch'), 'active', - Gio.SettingsBindFlags.DEFAULT); + Gio.SettingsBindFlags.DEFAULT); this._builder.get_object('show_group_apps_options_button').connect('clicked', () => { let box = this._builder.get_object('box_group_apps_options'); @@ -1713,7 +1730,7 @@ const Preferences = class { 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) => { @@ -1907,7 +1924,7 @@ const Preferences = class { 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'); @@ -1952,11 +1969,14 @@ const Preferences = class { {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: '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) { @@ -2071,6 +2091,71 @@ const Preferences = class { }); + 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', @@ -2081,7 +2166,7 @@ const Preferences = class { 'active', Gio.SettingsBindFlags.DEFAULT); - + this._settings.connect('changed::stockgs-keep-top-panel', () => this._maybeDisableTopPosition()); @@ -2091,7 +2176,7 @@ const Preferences = class { 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', @@ -2193,7 +2278,7 @@ const Preferences = class { dialog.connect('response', (dialog, id) => { if (id == Gtk.ResponseType.ACCEPT) acceptHandler.call(this, dialog.get_file().get_path()); - + dialog.destroy(); }); } @@ -2203,7 +2288,7 @@ const Preferences = class { const BuilderScope = GObject.registerClass({ Implements: [Gtk.BuilderScope], }, class BuilderScope extends GObject.Object { - + _init(preferences) { this._preferences = preferences; super._init(); @@ -2212,13 +2297,13 @@ const BuilderScope = GObject.registerClass({ vfunc_create_closure(builder, handlerName, flags, connectObject) { if (flags & Gtk.BuilderClosureFlags.SWAPPED) throw new Error('Unsupported template signal flag "swapped"'); - + if (typeof this[handlerName] === 'undefined') throw new Error(`${handlerName} is undefined`); - + return this[handlerName].bind(connectObject || this); } - + on_btn_click(connectObject) { connectObject.set_label("Clicked"); } @@ -2230,7 +2315,7 @@ const BuilderScope = GObject.registerClass({ position_top_button_clicked_cb(button) { 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); } @@ -2323,6 +2408,30 @@ const BuilderScope = GObject.registerClass({ }); } + 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); + + 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); + + 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) diff --git a/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml b/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml index 64d278db..a605be4 100644 --- a/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml +++ b/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml @@ -736,6 +736,16 @@ App icon margin Set the margin for application icons in the embedded dash. + + 0 + App icon margin to desktop + Set the margin for application icons in the embedded dash towards the desktop (top margin if panel is on the bottom). + + + 0 + App icon margin to screen border + Set the margin for application icons in the embedded dash towards the desktop (bottom margin if panel is on the bottom). + 4 App icon padding @@ -796,6 +806,22 @@ {'SIMPLE':1,'RIPPLE':1.25,'PLANK':2} App icon hover animation zoom scale in relation to the app icon size + + true + Highlight app icon on hover + + + "rgba(238, 238, 236, 0.1)" + Highlight color + + + "rgba(238, 238, 236, 0.18)" + Mouse down highlight color + + + 0 + Highlight border radius + true Integrate items from the gnome appmenu into the right click menu diff --git a/stylesheet.css b/stylesheet.css index 58d191a..8b951bf 100644 --- a/stylesheet.css +++ b/stylesheet.css @@ -39,22 +39,34 @@ } #dashtopanelScrollview .overview-tile:hover .dtp-container, -#dashtopanelScrollview .overview-tile:focus .dtp-container, +#dashtopanelScrollview .overview-tile:focus .dtp-container { + background-color: rgba(238, 238, 236, 0.1); + border-radius: 0px; +} + +#dashtopanelScrollview .overview-tile:hover .dtp-container > .dtp-dots-container, +#dashtopanelScrollview .overview-tile:focus .dtp-container > .dtp-dots-container { + border-radius: 0px; +} + .dashtopanelMainPanel .dash-item-container .show-apps:hover { background-color: rgba(238, 238, 238, 0.1); } - .dashtopanelMainPanel .dash-item-container .show-apps .overview-icon { color: #FFF; } +.dashtopanelMainPanel .dash-item-container .show-apps:hover .overview-icon { + background: none; +} #dashtopanelTaskbar .dash-item-container .overview-tile:hover, #dashtopanelTaskbar .dash-item-container .overview-tile .dtp-container .overview-icon, -#dashtopanelScrollview .overview-tile:hover .dtp-container.animate-appicon-hover, -.dashtopanelMainPanel .dash-item-container .show-apps:hover .overview-icon { +#dashtopanelScrollview .overview-tile:hover .dtp-container.no-highlight, +#dashtopanelScrollview .overview-tile:focus .dtp-container.no-highlight { background: none; } + #dashtopanelScrollview .overview-tile:active .dtp-container { background-color: rgba(238, 238, 236, 0.18); } diff --git a/taskbar.js b/taskbar.js index afcf727..9b63cba 100644 --- a/taskbar.js +++ b/taskbar.js @@ -153,11 +153,11 @@ const iconAnimationSettings = { }, get travel() { - return Math.max(0, this._getDictValue('animate-appicon-hover-animation-travel')); + return Math.max(-1, this._getDictValue('animate-appicon-hover-animation-travel')); }, get zoom() { - return Math.max(1, this._getDictValue('animate-appicon-hover-animation-zoom')); + return Math.max(0.5, this._getDictValue('animate-appicon-hover-animation-zoom')); }, }; @@ -209,7 +209,7 @@ export const TaskbarActor = GObject.registerClass({ leftFade.set_style(gradientStyle); rightFade.set_style(gradientStyle); } - + childBox[panel.varCoord.c2] = childBox[panel.varCoord.c1] + (value > 0 ? scrollview._dtpFadeSize : 0); leftFade.allocate(childBox); @@ -223,13 +223,13 @@ export const TaskbarActor = GObject.registerClass({ // then calls BoxLayout) vfunc_get_preferred_width(forHeight) { let [, natWidth] = St.Widget.prototype.vfunc_get_preferred_width.call(this, forHeight); - + return [0, natWidth]; } vfunc_get_preferred_height(forWidth) { let [, natHeight] = St.Widget.prototype.vfunc_get_preferred_height.call(this, forWidth); - + return [0, natHeight]; } }); @@ -254,7 +254,7 @@ export const Taskbar = class extends EventEmitter { super(); this.dtpPanel = panel; - + // start at smallest size due to running indicator drawing area expanding but not shrinking this.iconSize = 16; @@ -307,13 +307,13 @@ export const Taskbar = class extends EventEmitter { 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: .5, y: .5 }), + 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); @@ -333,7 +333,7 @@ export const Taskbar = class extends EventEmitter { }); const adjustment = this._scrollView[orientation[0] + 'adjustment']; - + this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this)); this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' }); @@ -373,7 +373,7 @@ export const Taskbar = class extends EventEmitter { ], [ global.window_manager, - 'switch-workspace', + 'switch-workspace', () => this._connectWorkspaceSignals() ], [ @@ -456,7 +456,7 @@ export const Taskbar = class extends EventEmitter { 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.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) @@ -483,7 +483,7 @@ export const Taskbar = class extends EventEmitter { this._signalsHandler = 0; this._container.destroy(); - + this.previewMenu.disable(); this.previewMenu.destroy(); @@ -650,7 +650,7 @@ export const Taskbar = class extends EventEmitter { if (this._dragInfo) { this._box.set_child_at_index(this._dragInfo[1]._dashItemContainer, this._dragInfo[0]); } - + this._endDrag(); } @@ -672,10 +672,10 @@ export const Taskbar = class extends EventEmitter { this._clearEmptyDropTarget(); this._showAppsIcon.setDragApp(null); DND.removeDragMonitor(this._dragMonitor); - + this._dragMonitor = null; this.emit('end-drag'); - + this._toggleFavoriteHighlight(); } @@ -697,9 +697,9 @@ export const Taskbar = class extends EventEmitter { _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._getAppIcons().filter(appIcon => (this.usingLaunchers && appIcon.isLauncher) || (!this.usingLaunchers && appFavorites.isFavorite(appIcon.app.get_id()))) .forEach(fav => fav._container[cssFuncName]('favorite')); } @@ -744,12 +744,12 @@ export const Taskbar = class extends EventEmitter { _createAppItem(app, window, isLauncher) { let appIcon = new AppIcons.TaskbarAppIcon( { - app, + app, window, isLauncher }, this.dtpPanel, - { + { setSizeManually: true, showLabel: false, isDraggable: !SETTINGS.get_boolean('taskbar-locked'), @@ -788,7 +788,7 @@ export const Taskbar = class extends EventEmitter { appIcon.connect('notify::hover', () => { if (appIcon.hover){ - this._timeoutsHandler.add([T1, 100, + this._timeoutsHandler.add([T1, 100, () => Utils.ensureActorVisibleInScrollView(this._scrollView, appIcon, this._scrollView._dtpFadeSize) ]) @@ -819,7 +819,7 @@ export const Taskbar = class extends EventEmitter { appIcon._menu._boxPointer.yOffset = -y_shift; } }); - + // Override default AppIcon label_actor, now the // accessible_name is set at DashItemContainer.setLabelText appIcon.label_actor = null; @@ -921,13 +921,13 @@ export const Taskbar = class extends EventEmitter { 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 + // 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++) { @@ -960,7 +960,7 @@ export const Taskbar = class extends EventEmitter { } sortAppsCompareFunction(appA, appB) { - return getAppStableSequence(appA, this.dtpPanel.monitor) - + return getAppStableSequence(appA, this.dtpPanel.monitor) - getAppStableSequence(appB, this.dtpPanel.monitor); } @@ -1012,9 +1012,9 @@ export const Taskbar = class extends EventEmitter { (!this.allowSplitApps || this.isGroupApps || appInfo.windows[0] == appIcon.window) && appInfo.isLauncher == appIcon.isLauncher); - if (appIndex < 0 || + if (appIndex < 0 || (appIcon.window && (this.isGroupApps || expectedAppInfos[appIndex].windows.indexOf(appIcon.window) < 0)) || - (!appIcon.window && !appIcon.isLauncher && + (!appIcon.window && !appIcon.isLauncher && !this.isGroupApps && expectedAppInfos[appIndex].windows.length)) { currentAppIcons[i][this._shownInitially ? 'animateOutAndDestroy' : 'destroy'](); currentAppIcons.splice(i, 1); @@ -1024,13 +1024,13 @@ export const Taskbar = class extends EventEmitter { //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 }] : + 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 && + 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) { @@ -1040,10 +1040,10 @@ export const Taskbar = class extends EventEmitter { } 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); @@ -1082,14 +1082,14 @@ export const Taskbar = class extends EventEmitter { 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) @@ -1100,8 +1100,8 @@ export const Taskbar = class extends EventEmitter { if (apps.indexOf(windowApp) >= 0) separateApps.push({ - app: windowApp, - isLauncher: false, + app: windowApp, + isLauncher: false, windows: [w] }) }) @@ -1110,8 +1110,8 @@ export const Taskbar = class extends EventEmitter { return separateApps } - return apps.map(app => ({ - app: app, + return apps.map(app => ({ + app: app, isLauncher: defaultIsLauncher || false, windows: defaultWindows || AppIcons.getInterestingWindows(app, this.dtpPanel.monitor) .sort(sortWindowsCompareFunction) @@ -1200,10 +1200,10 @@ export const Taskbar = class extends EventEmitter { let currentAppIcons = this._getAppIcons(); let sourceIndex = currentAppIcons.indexOf(source); - let hoveredIndex = Utils.findIndex(currentAppIcons, - appIcon => pos >= appIcon._dashItemContainer[posProp] && + let hoveredIndex = Utils.findIndex(currentAppIcons, + appIcon => pos >= appIcon._dashItemContainer[posProp] && pos <= (appIcon._dashItemContainer[posProp] + appIcon._dashItemContainer[sizeProp])); - + if (!this._dragInfo) { this._dragInfo = [sourceIndex, source]; } @@ -1216,13 +1216,13 @@ export const Taskbar = class extends EventEmitter { // 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 && + (!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 && + (!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) @@ -1231,14 +1231,14 @@ export const Taskbar = class extends EventEmitter { 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() || + if (!this._dragInfo || !source.app || source.app.is_window_backed() || !this._settings.is_writable('favorite-apps')) { return false; } @@ -1269,9 +1269,9 @@ export const Taskbar = class extends EventEmitter { 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) && + + 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)); @@ -1279,15 +1279,15 @@ export const Taskbar = class extends EventEmitter { 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) || + if (this.showFavorites && + ((usingLaunchers && appIcons[i].isLauncher) || (!usingLaunchers && appFavorites.isFavorite(appIcons[i].app.get_id())))) { ++favoritesCount; } @@ -1326,10 +1326,10 @@ export const Taskbar = class extends EventEmitter { 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); }; @@ -1364,13 +1364,13 @@ export const Taskbar = class extends EventEmitter { } } } - + _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); @@ -1446,7 +1446,7 @@ export const TaskbarItemContainer = GObject.registerClass({ let travel = iconAnimationSettings.travel; let zoom = iconAnimationSettings.zoom; - return this._dtpPanel.dtpSize * (travel + (zoom - 1) / 2); + return this._dtpPanel.dtpSize * Math.max(0, travel + (zoom - 1) / 2); } _updateCloneContainerPosition(cloneContainer) { @@ -1542,10 +1542,10 @@ export const TaskbarItemContainer = GObject.registerClass({ 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.abs(translationEnd - translationDone); + let translationTodo = Math.sign(travel)*Math.abs(translationEnd - translationDone); let scale = 1 + (zoom - 1) * level; let rotationAngleZ = rotationDirection * rotation * level; - let time = duration * translationTodo / translationMax; + let time = Math.abs(duration * translationTodo / translationMax); let options = { scale_x: scale, scale_y: scale, @@ -1596,7 +1596,7 @@ const DragPlaceholderItem = GObject.registerClass({ this.child = { _delegate: appIcon }; - this._clone = new Clutter.Clone({ + this._clone = new Clutter.Clone({ source: appIcon.icon._iconBin, width: iconSize, height: iconSize @@ -1613,7 +1613,7 @@ const DragPlaceholderItem = GObject.registerClass({ export function getAppStableSequence(app, monitor) { let windows = AppIcons.getInterestingWindows(app, monitor); - + return windows.reduce((prevWindow, window) => { return Math.min(prevWindow, getWindowStableSequence(window)); }, Infinity); @@ -1624,5 +1624,5 @@ export function sortWindowsCompareFunction(windowA, 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/ui/BoxAnimateAppIconHoverOptions.ui b/ui/BoxAnimateAppIconHoverOptions.ui index f49e2d7..f0ab669 100644 --- a/ui/BoxAnimateAppIconHoverOptions.ui +++ b/ui/BoxAnimateAppIconHoverOptions.ui @@ -18,14 +18,14 @@ - 0 + -100 100 1 5 - 100 + 10 250 1 5 diff --git a/ui/BoxHighlightAppIconHoverOptions.ui b/ui/BoxHighlightAppIconHoverOptions.ui new file mode 100644 index 0000000..5b99fcf --- /dev/null +++ b/ui/BoxHighlightAppIconHoverOptions.ui @@ -0,0 +1,70 @@ + + + + + + + 0 + 10 + 1 + 2 + + + + vertical + 600 + 24 + 32 + 32 + 32 + 32 + + + + + + Highlight AppIcon color + + + True + center + True + + + + + + + Pressed AppIcon color + + + True + center + True + + + + + + + Highlight AppIcon border radius + (default is 0) + + + 300 + highlight_appicon_borderradius_adjustment + 0 + 0 + right + True + + + + + + + + + + + \ No newline at end of file diff --git a/ui/BoxShowDesktopOptions.ui b/ui/BoxShowDesktopOptions.ui index be5d21c..e068126 100644 --- a/ui/BoxShowDesktopOptions.ui +++ b/ui/BoxShowDesktopOptions.ui @@ -52,7 +52,7 @@ Override Show Desktop line color - > + True center True diff --git a/ui/SettingsStyle.ui b/ui/SettingsStyle.ui index e461782..d31ef7f 100644 --- a/ui/SettingsStyle.ui +++ b/ui/SettingsStyle.ui @@ -9,6 +9,20 @@ 0.1 + + 0.33 + 1 + 0.01 + 0.1 + + + + 0.33 + 1 + 0.01 + 0.1 + + 0.33 1 @@ -42,7 +56,7 @@ AppIcon style - + App Icon Margin @@ -61,6 +75,42 @@ + + + App Icon Margin Towards Desktop + (default is 0) + + + 300 + appicon_margin_todesktop_adjustment + 0 + 0 + right + True + + + + + + + + + App Icon Margin Towards Screen Border + (default is 0) + + + 300 + appicon_margin_toscreenborder_adjustment + 0 + 0 + right + True + + + + + + App Icon Padding @@ -104,6 +154,31 @@ + + + Highlight hovering app icons + + + True + center + + + emblem-system-symbolic + + + + + + + + center + + + + + Icon style