diff --git a/appIcons.js b/appIcons.js index c24e133..517cc5c 100644 --- a/appIcons.js +++ b/appIcons.js @@ -30,6 +30,7 @@ import GObject from 'gi://GObject'; import Mtk from 'gi://Mtk'; import Shell from 'gi://Shell'; import St from 'gi://St'; +import Gtk from 'gi://Gtk'; import * as AppDisplay from 'resource:///org/gnome/shell/ui/appDisplay.js'; import * as AppMenu from 'resource:///org/gnome/shell/ui/appMenu.js'; @@ -117,6 +118,9 @@ 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); @@ -127,7 +131,7 @@ export const TaskbarAppIcon = GObject.registerClass({ 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(); @@ -143,27 +147,27 @@ export const TaskbarAppIcon = GObject.registerClass({ 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(); @@ -192,11 +196,12 @@ export const TaskbarAppIcon = GObject.registerClass({ } this._onAnimateAppiconHoverChanged(); + this._onAppIconHoverHighlightChanged(); this._setAppIconPadding(); this._setAppIconStyle(); this._showDots(); - this._focusWindowChangedId = global.display.connect('notify::focus-window', + this._focusWindowChangedId = global.display.connect('notify::focus-window', this._onFocusAppChanged.bind(this)); this._windowEnteredMonitorId = this._windowLeftMonitorId = 0; @@ -207,17 +212,17 @@ 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; } else { - this._titleWindowChangeId = this.window.connect('notify::title', + this._titleWindowChangeId = this.window.connect('notify::title', this._updateWindowTitle.bind(this)); this._minimizedWindowChangeId = this.window.connect('notify::minimized', this._updateWindowTitleStyle.bind(this)); } - + this._scrollEventId = this.connect('scroll-event', this._onMouseScroll.bind(this)); this._overviewWindowDragEndId = Main.overview.connect('window-drag-end', @@ -227,9 +232,18 @@ export const TaskbarAppIcon = GObject.registerClass({ this._onSwitchWorkspace.bind(this)); this._hoverChangeId = this.connect('notify::hover', () => this._onAppIconHoverChanged()); - + if (!this._checkGtkVersion_cssVariables()) { + 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)), @@ -255,8 +269,14 @@ 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)), + ]; + + if (!this._checkGtkVersion_cssVariables()) { + this._dtpSettingsSignalIds += [ + SETTINGS.connect('changed::highlight-appicon-hover-border-radius', () => this._setIconStyle(this._isFocusedWindow())), + ]; + } this._progressIndicator = new Progress.ProgressIndicator(this, panel.progressManager); @@ -269,10 +289,11 @@ 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 clone = new Clutter.Clone({ - source: this.child, + source: this._dtpIconContainer, x: this.child.x, y: this.child.y, width: this.child.width, height: this.child.height, pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }), @@ -293,19 +314,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)) { return false; } else { - return this.hover && !this.window && - (!this._menu || !this._menu.isOpen) && + 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; } @@ -329,7 +350,7 @@ export const TaskbarAppIcon = GObject.registerClass({ this.app.disconnect(this._stateChangedId); this._stateChangedId = 0; } - + if(this._overviewWindowDragEndId) Main.overview.disconnect(this._overviewWindowDragEndId); @@ -356,6 +377,12 @@ export const TaskbarAppIcon = GObject.registerClass({ 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 +442,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 { @@ -438,9 +465,59 @@ 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'); + if (this._checkGtkVersion_cssVariables()) { + this._container.set_style(`--dtp-hover-background-color: ${background_color}; --dtp-hover-border-radius: ${border_radius}px; --dtp-pressed-background-color: ${pressed_color};`); + } else { + // Some trickery needed to get the same 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 = ''; + } + } + + _checkGtkVersion_cssVariables() { + // Support for CSS variables will be added in GTK 4.16 + return Gtk.get_major_version() >= 5 || + (Gtk.get_major_version() == 4 && Gtk.get_minor_version() >= 16); + } + + _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._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)) { @@ -458,7 +535,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) { @@ -467,7 +544,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 @@ -478,23 +555,23 @@ export const TaskbarAppIcon = GObject.registerClass({ this.disconnect(mappedId); }); } else { - this._focusedDots = 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, () => { @@ -512,7 +589,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); @@ -558,7 +635,7 @@ export const TaskbarAppIcon = GObject.registerClass({ this._windowTitle.set_style('font-size: ' + SETTINGS.get_int('group-apps-label-font-size') * fontScale + 'px;' + 'font-weight: ' + fontWeight + ';' + - (useFixedWidth ? '' : 'max-width: ' + maxLabelWidth + 'px;') + + (useFixedWidth ? '' : 'max-width: ' + maxLabelWidth + 'px;') + 'color: ' + fontColor); } } @@ -566,7 +643,7 @@ export const TaskbarAppIcon = GObject.registerClass({ _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(); } @@ -576,8 +653,8 @@ export const TaskbarAppIcon = GObject.registerClass({ _setIconStyle(isFocused) { let inlineStyle = 'margin: 0;'; - if(SETTINGS.get_boolean('focus-highlight') && - this._checkIfFocusedApp() && !this.isLauncher && + 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'); @@ -585,7 +662,7 @@ export const TaskbarAppIcon = GObject.registerClass({ if(!this.window) { let containerWidth = this._dtpIconContainer.get_width() / Utils.getScaleFactor(); - let backgroundSize = containerWidth + "px " + + let backgroundSize = containerWidth + "px " + (containerWidth - (pos == DOT_POSITION.BOTTOM ? highlightMargin : 0)) + "px;"; if (focusedDotStyle == DOT_STYLE.CILIORA || focusedDotStyle == DOT_STYLE.SEGMENTED) @@ -598,16 +675,19 @@ export const TaskbarAppIcon = GObject.registerClass({ bgSvg += (this.dtpPanel.checkIfVertical() ? '_2' : '_3'); } - inlineStyle += "background-image: url('" + EXTENSION_PATH + bgSvg + ".svg');" + + 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) + ";"; + if (!this._checkGtkVersion_cssVariables()) { + inlineStyle += this._appicon_normalstyle; + } } - + if(this._dotsContainer.get_style() != inlineStyle) { this._dotsContainer.set_style(inlineStyle); } @@ -618,17 +698,30 @@ export const TaskbarAppIcon = GObject.registerClass({ } _checkIfMonitorHasFocus() { - return global.display.focus_window && + 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') || + !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;'); } @@ -710,7 +803,7 @@ export const TaskbarAppIcon = GObject.registerClass({ 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(); @@ -727,11 +820,11 @@ 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'); @@ -744,7 +837,7 @@ export const TaskbarAppIcon = GObject.registerClass({ newFocusedDotsSize = this._containerSize; newFocusedDotsOpacity = (isFocused && this._nWindows > 0) ? 255 : 0; } - + if(this._unfocusedIsWide) { newUnfocusedDotsSize = (!isFocused && this._nWindows > 0) ? this._containerSize : 0; newUnfocusedDotsOpacity = 255; @@ -752,7 +845,7 @@ export const TaskbarAppIcon = GObject.registerClass({ 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 @@ -770,10 +863,10 @@ export const TaskbarAppIcon = GObject.registerClass({ _animateDotDisplay(dots, newSize, otherDots, newOtherOpacity, sizeProp, duration) { Utils.stopAnimations(dots) - let tweenOpts = { + let tweenOpts = { time: duration, transition: 'easeInOutCubic', - onComplete: () => { + onComplete: () => { if(newOtherOpacity > 0) otherDots.opacity = newOtherOpacity; } @@ -789,7 +882,7 @@ export const TaskbarAppIcon = GObject.registerClass({ _isFocusedWindow() { let focusedWindow = global.display.focus_window; - + while (focusedWindow) { if (focusedWindow == this.window) { return true; @@ -802,9 +895,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; } @@ -812,7 +905,7 @@ 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() && + return (this.icon.get_stage() && this.icon.get_theme_node().get_border_image()); } @@ -875,23 +968,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(); } 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 @@ -902,11 +995,11 @@ 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 @@ -925,10 +1018,10 @@ export const TaskbarAppIcon = GObject.registerClass({ else this.app.activate(); break; - + case "CYCLE": if (!Main.overview._shown){ - if (appHasFocus) + if (appHasFocus) cycleThroughWindows(this.app, false, false, monitor); else { activateFirstWindow(this.app, monitor); @@ -939,7 +1032,7 @@ export const TaskbarAppIcon = GObject.registerClass({ break; case "CYCLE-MIN": if (!Main.overview._shown){ - if (appHasFocus || (recentlyClickedApp == this.app && recentlyClickedAppWindows[recentlyClickedAppIndex % recentlyClickedAppWindows.length] == "MINIMIZE")) + if (appHasFocus || (recentlyClickedApp == this.app && recentlyClickedAppWindows[recentlyClickedAppIndex % recentlyClickedAppWindows.length] == "MINIMIZE")) cycleThroughWindows(this.app, false, true, monitor); else { activateFirstWindow(this.app, monitor); @@ -964,10 +1057,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(); @@ -981,7 +1074,7 @@ export const TaskbarAppIcon = GObject.registerClass({ activateFirstWindow(this.app, monitor); } else { cycleThroughWindows(this.app, false, false, monitor); - } + } } else this.app.activate(); @@ -1003,7 +1096,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); @@ -1021,12 +1114,12 @@ 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) @@ -1065,7 +1158,7 @@ export const TaskbarAppIcon = GObject.registerClass({ } } else if(SETTINGS.get_boolean('dot-color-override')) { let dotColorSettingPrefix = 'dot-color-'; - + if(!isFocused && SETTINGS.get_boolean('dot-color-unfocused-different')) dotColorSettingPrefix = 'dot-color-unfocused-'; @@ -1164,7 +1257,7 @@ export const TaskbarAppIcon = GObject.registerClass({ 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; @@ -1226,7 +1319,7 @@ export const TaskbarAppIcon = GObject.registerClass({ } cr.fill(); } - + cr.$dispose(); } @@ -1287,7 +1380,7 @@ export const TaskbarAppIcon = GObject.registerClass({ if (source == Main.xdndHandler) { this._previewMenu.close(true); } - + return DND.DragMotionResult.CONTINUE; } @@ -1354,7 +1447,7 @@ export function cycleThroughWindows(app, reversed, shouldMinimize, monitor) { if (recentlyClickedAppLoopId > 0) GLib.Source.remove(recentlyClickedAppLoopId); - + recentlyClickedAppLoopId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, MEMORY_TIME, resetRecentlyClickedApp); @@ -1377,7 +1470,7 @@ export function cycleThroughWindows(app, reversed, shouldMinimize, monitor) { recentlyClickedAppIndex++; } let index = recentlyClickedAppIndex % recentlyClickedAppWindows.length; - + if(recentlyClickedAppWindows[index] === "MINIMIZE") minimizeWindow(app, true, monitor); else @@ -1407,8 +1500,8 @@ 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); @@ -1416,7 +1509,7 @@ export function getInterestingWindows(app, monitor, isolateMonitors) { // 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() && + return w.get_workspace() && w.get_workspace() == Utils.getCurrentWorkspace(); }); @@ -1425,7 +1518,7 @@ export function getInterestingWindows(app, monitor, isolateMonitors) { return w.get_monitor() == monitor.index; }); } - + return windows; } @@ -1486,7 +1579,7 @@ 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) { @@ -1502,17 +1595,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] : + [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; }); } @@ -1577,13 +1670,13 @@ export function ItemShowLabel() { 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', @@ -1657,10 +1750,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) { @@ -1736,7 +1829,7 @@ export const ShowAppsIconWrapper = class extends EventEmitter { } shouldShowTooltip() { - return SETTINGS.get_boolean('show-tooltip') && + return SETTINGS.get_boolean('show-tooltip') && (this.actor.hover && (!this._menu || !this._menu.isOpen)); } @@ -1863,12 +1956,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], 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 d2337c2..2746ef4 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'); @@ -222,6 +223,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; @@ -377,7 +380,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()); @@ -403,7 +406,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)); }; @@ -462,7 +465,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); @@ -484,7 +487,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, @@ -572,7 +575,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 @@ -621,6 +624,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) => { @@ -684,6 +695,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() { @@ -846,7 +863,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', @@ -856,7 +873,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)); @@ -927,7 +944,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); @@ -935,7 +952,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); @@ -1110,7 +1127,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); @@ -1143,7 +1160,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', @@ -1153,7 +1170,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) => { @@ -1191,7 +1208,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'), @@ -1268,7 +1285,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')); @@ -1340,7 +1357,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', @@ -1349,7 +1366,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(); @@ -1378,7 +1395,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')); @@ -1405,7 +1422,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')); @@ -1413,7 +1430,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')); @@ -1467,7 +1484,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', @@ -1480,7 +1497,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', @@ -1551,7 +1568,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()); @@ -1571,7 +1588,7 @@ const Preferences = class { dialog.show(); }); - + this._settings.bind('isolate-workspaces', this._builder.get_object('isolate_workspaces_switch'), 'active', @@ -1634,7 +1651,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'); @@ -1696,7 +1713,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) => { @@ -1890,7 +1907,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'); @@ -1935,11 +1952,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) { @@ -2054,6 +2074,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', @@ -2064,7 +2149,7 @@ const Preferences = class { 'active', Gio.SettingsBindFlags.DEFAULT); - + this._settings.connect('changed::stockgs-keep-top-panel', () => this._maybeDisableTopPosition()); @@ -2074,7 +2159,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', @@ -2151,7 +2236,7 @@ const Preferences = class { dialog.connect('response', (dialog, id) => { if (id == Gtk.ResponseType.ACCEPT) acceptHandler.call(this, dialog.get_file().get_path()); - + dialog.destroy(); }); } @@ -2161,7 +2246,7 @@ const Preferences = class { const BuilderScope = GObject.registerClass({ Implements: [Gtk.BuilderScope], }, class BuilderScope extends GObject.Object { - + _init(preferences) { this._preferences = preferences; super._init(); @@ -2170,13 +2255,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"); } @@ -2188,7 +2273,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); } @@ -2281,6 +2366,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 a73a349..c79bd50 100644 --- a/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml +++ b/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml @@ -735,6 +735,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 @@ -795,6 +805,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..fd05e22 100644 --- a/stylesheet.css +++ b/stylesheet.css @@ -39,24 +39,40 @@ } #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; + background-color: var(--dtp-hover-background-color); + border-radius: var(--dtp-hover-border-radius); +} + +#dashtopanelScrollview .overview-tile:hover .dtp-container > .dtp-dots-container, +#dashtopanelScrollview .overview-tile:focus .dtp-container > .dtp-dots-container { + border-radius: 0px; + border-radius: var(--dtp-hover-border-radius); +} + .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; } - -#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 { 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.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); + background-color: var(--dtp-pressed-background-color); } #dashtopanelScrollview .overview-tile .favorite { diff --git a/taskbar.js b/taskbar.js index 54da64f..af08ccd 100644 --- a/taskbar.js +++ b/taskbar.js @@ -98,11 +98,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')); }, }; @@ -154,7 +154,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); @@ -168,13 +168,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]; } }); @@ -199,7 +199,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; @@ -252,13 +252,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); @@ -278,7 +278,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' }); @@ -318,7 +318,7 @@ export const Taskbar = class extends EventEmitter { ], [ global.window_manager, - 'switch-workspace', + 'switch-workspace', () => this._connectWorkspaceSignals() ], [ @@ -400,7 +400,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) @@ -425,7 +425,7 @@ export const Taskbar = class extends EventEmitter { this._signalsHandler = 0; this._container.destroy(); - + this.previewMenu.disable(); this.previewMenu.destroy(); @@ -592,7 +592,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(); } @@ -614,10 +614,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(); } @@ -639,9 +639,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')); } @@ -686,12 +686,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'), @@ -730,7 +730,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) ]) @@ -761,7 +761,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; @@ -863,13 +863,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++) { @@ -902,7 +902,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); } @@ -941,9 +941,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); @@ -953,13 +953,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) { @@ -969,10 +969,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); @@ -1011,14 +1011,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) @@ -1029,8 +1029,8 @@ export const Taskbar = class extends EventEmitter { if (apps.indexOf(windowApp) >= 0) separateApps.push({ - app: windowApp, - isLauncher: false, + app: windowApp, + isLauncher: false, windows: [w] }) }) @@ -1039,8 +1039,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) @@ -1129,10 +1129,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]; } @@ -1145,13 +1145,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) @@ -1160,14 +1160,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; } @@ -1198,9 +1198,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)); @@ -1208,15 +1208,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; } @@ -1255,10 +1255,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); }; @@ -1293,13 +1293,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); @@ -1374,7 +1374,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) { @@ -1470,10 +1470,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, @@ -1524,7 +1524,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 @@ -1541,7 +1541,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); @@ -1552,5 +1552,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 abe5c34..b76c96c 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