diff options
| author | AlexanderCurl <alexc@alexc.hu> | 2026-04-18 17:46:06 +0100 |
|---|---|---|
| committer | AlexanderCurl <alexc@alexc.hu> | 2026-04-18 17:46:06 +0100 |
| commit | 70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 (patch) | |
| tree | ab1123d4067c1b086dd6faa7ee4ea643236b565a /raveos-theme/gnome/theme-data/extensions/installed/dash-to-dock@micxgx.gmail.com/dash.js | |
| parent | 5d94c0a7d44a2255b81815a52a7056a94a39842d (diff) | |
| download | RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.tar.gz RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.zip | |
Replaced file structures for themes in the correct format
Diffstat (limited to 'raveos-theme/gnome/theme-data/extensions/installed/dash-to-dock@micxgx.gmail.com/dash.js')
| -rw-r--r-- | raveos-theme/gnome/theme-data/extensions/installed/dash-to-dock@micxgx.gmail.com/dash.js | 1177 |
1 files changed, 0 insertions, 1177 deletions
diff --git a/raveos-theme/gnome/theme-data/extensions/installed/dash-to-dock@micxgx.gmail.com/dash.js b/raveos-theme/gnome/theme-data/extensions/installed/dash-to-dock@micxgx.gmail.com/dash.js deleted file mode 100644 index 956bbeb..0000000 --- a/raveos-theme/gnome/theme-data/extensions/installed/dash-to-dock@micxgx.gmail.com/dash.js +++ /dev/null @@ -1,1177 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import { - Clutter, - Gio, - GLib, - GObject, - Shell, - St, -} from './dependencies/gi.js'; - -import { - AppFavorites, - Dash, - DND, - Main, -} from './dependencies/shell/ui.js'; - -import { - Util, -} from './dependencies/shell/misc.js'; - -import { - AppIcons, - Docking, - Theming, - Utils, -} from './imports.js'; - -// module "Dash" did not export DASH_ANIMATION_TIME in old versions -// so we just define it like it is defined in Dash; -// taken from https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/dash.js -const DASH_ANIMATION_TIME = Dash.DASH_ANIMATION_TIME ?? 200; -const DASH_VISIBILITY_TIMEOUT = 3; - -const Labels = Object.freeze({ - SHOW_MOUNTS: Symbol('show-mounts'), - FIRST_LAST_CHILD_WORKAROUND: Symbol('first-last-child-workaround'), -}); - -/** - * Extend DashItemContainer - * - * - set label position based on dash orientation - * - */ -const DockDashItemContainer = GObject.registerClass( -class DockDashItemContainer extends Dash.DashItemContainer { - _init(position) { - super._init(); - - this.label?.add_style_class_name(Theming.PositionStyleClass[position]); - if (Docking.DockManager.settings.customThemeShrink) - this.label?.add_style_class_name('shrink'); - } - - showLabel() { - return AppIcons.itemShowLabel.call(this); - } - - // we override the method show taken from: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/dash.js - // in order to apply a little modification at the end of the animation - // which makes sure that the icon background is not blurry - show(animate) { - if (this.child == null) - return; - - this.ease({ - scale_x: 1, - scale_y: 1, - opacity: 255, - duration: animate ? DASH_ANIMATION_TIME : 0, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => { - // when the animation is ended, we simulate - // a hover to gain back focus and unblur the - // background - this.set_hover(true); - }, - }); - } -}); - -const DockDashIconsVerticalLayout = GObject.registerClass( - class DockDashIconsVerticalLayout extends Clutter.BoxLayout { - _init() { - super._init({ - orientation: Clutter.Orientation.VERTICAL, - }); - } - - vfunc_get_preferred_height(container, forWidth) { - const [natHeight] = super.vfunc_get_preferred_height(container, forWidth); - return [natHeight, 0]; - } - }); - - -const baseIconSizes = [16, 22, 24, 32, 48, 64, 96, 128]; - -/** - * This class is a fork of the upstream dash class (ui.dash.js) - * - * Summary of changes: - * - disconnect global signals adding a destroy method; - * - play animations even when not in overview mode - * - set a maximum icon size - * - show running and/or favorite applications - * - hide showApps label when the custom menu is shown. - * - add scrollview - * ensure actor is visible on keyfocus inseid the scrollview - * - add 128px icon size, might be useful for hidpi display - * - sync minimization application target position. - * - keep running apps ordered. - */ -export const DockDash = GObject.registerClass({ - Properties: { - 'requires-visibility': GObject.ParamSpec.boolean( - 'requires-visibility', 'requires-visibility', 'requires-visibility', - GObject.ParamFlags.READWRITE, - false), - }, - Signals: { - 'menu-opened': {}, - 'menu-closed': {}, - 'icon-size-changed': {}, - }, -}, class DockDash extends St.Widget { - _init(monitorIndex) { - // Initialize icon variables and size - super._init({ - name: 'dash', - offscreen_redirect: Clutter.OffscreenRedirect.ALWAYS, - layout_manager: new Clutter.BinLayout(), - }); - - this._maxWidth = -1; - this._maxHeight = -1; - this.iconSize = Docking.DockManager.settings.dashMaxIconSize; - this._availableIconSizes = baseIconSizes; - this._shownInitially = false; - this._initializeIconSize(this.iconSize); - this._signalsHandler = new Utils.GlobalSignalsHandler(this); - - this._separator = null; - - this._monitorIndex = monitorIndex; - this._position = Utils.getPosition(); - this._isHorizontal = (this._position === St.Side.TOP) || - (this._position === St.Side.BOTTOM); - - this._dragPlaceholder = null; - this._dragPlaceholderPos = -1; - this._animatingPlaceholdersCount = 0; - this._showLabelTimeoutId = 0; - this._resetHoverTimeoutId = 0; - this._labelShowing = false; - - this._dashContainer = new St.BoxLayout({ - name: 'dashtodockDashContainer', - x_align: Clutter.ActorAlign.CENTER, - y_align: Clutter.ActorAlign.CENTER, - vertical: !this._isHorizontal, - y_expand: this._isHorizontal, - x_expand: !this._isHorizontal, - }); - - this._scrollView = new St.ScrollView({ - name: 'dashtodockDashScrollview', - hscrollbar_policy: this._isHorizontal ? St.PolicyType.EXTERNAL : St.PolicyType.NEVER, - vscrollbar_policy: this._isHorizontal ? St.PolicyType.NEVER : St.PolicyType.EXTERNAL, - x_expand: this._isHorizontal, - y_expand: !this._isHorizontal, - enable_mouse_scrolling: false, - }); - - this._scrollView.connect('scroll-event', this._onScrollEvent.bind(this)); - - this._boxContainer = new St.BoxLayout({ - name: 'dashtodockBoxContainer', - x_align: Clutter.ActorAlign.FILL, - y_align: Clutter.ActorAlign.FILL, - vertical: !this._isHorizontal, - }); - this._boxContainer.add_style_class_name(Theming.PositionStyleClass[this._position]); - - const rtl = Clutter.get_default_text_direction() === Clutter.TextDirection.RTL; - this._box = new St.BoxLayout({ - vertical: !this._isHorizontal, - clip_to_allocation: false, - ...!this._isHorizontal ? {layout_manager: new DockDashIconsVerticalLayout()} : {}, - x_align: rtl ? Clutter.ActorAlign.END : Clutter.ActorAlign.START, - y_align: this._isHorizontal ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.START, - y_expand: !this._isHorizontal, - x_expand: this._isHorizontal, - }); - this._box._delegate = this; - this._boxContainer.add_child(this._box); - Utils.addActor(this._scrollView, this._boxContainer); - this._dashContainer.add_child(this._scrollView); - - this._showAppsIcon = new AppIcons.DockShowAppsIcon(this._position); - this._showAppsIcon.show(false); - this._showAppsIcon.icon.setIconSize(this.iconSize); - this._showAppsIcon.x_expand = false; - this._showAppsIcon.y_expand = false; - this.showAppsButton.connect('notify::hover', a => { - if (this._showAppsIcon.get_parent() === this._boxContainer) - this._ensureItemVisibility(a); - }); - if (!this._isHorizontal) - this._showAppsIcon.y_align = Clutter.ActorAlign.START; - this._hookUpLabel(this._showAppsIcon); - this._showAppsIcon.connect('menu-state-changed', (_icon, opened) => { - this._itemMenuStateChanged(this._showAppsIcon, opened); - }); - this.updateShowAppsButton(); - - this._background = new St.Widget({ - style_class: 'dash-background', - y_expand: this._isHorizontal, - x_expand: !this._isHorizontal, - }); - - const sizerBox = new Clutter.Actor(); - sizerBox.add_constraint(new Clutter.BindConstraint({ - source: this._isHorizontal ? this._showAppsIcon.icon : this._dashContainer, - coordinate: Clutter.BindCoordinate.HEIGHT, - })); - sizerBox.add_constraint(new Clutter.BindConstraint({ - source: this._isHorizontal ? this._dashContainer : this._showAppsIcon.icon, - coordinate: Clutter.BindCoordinate.WIDTH, - })); - this._background.add_child(sizerBox); - - this.add_child(this._background); - this.add_child(this._dashContainer); - - this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this)); - - this._shellSettings = new Gio.Settings({ - schema_id: 'org.gnome.shell', - }); - - this._appSystem = Shell.AppSystem.get_default(); - - this.iconAnimator = new Docking.IconAnimator(this); - - this._signalsHandler.add([ - this._appSystem, - 'installed-changed', - () => { - AppFavorites.getAppFavorites().reload(); - this._queueRedisplay(); - }, - ], [ - AppFavorites.getAppFavorites(), - 'changed', - this._queueRedisplay.bind(this), - ], [ - this._appSystem, - 'app-state-changed', - this._queueRedisplay.bind(this), - ], [ - Main.overview, - 'item-drag-begin', - this._onItemDragBegin.bind(this), - ], [ - Main.overview, - 'item-drag-end', - this._onItemDragEnd.bind(this), - ], [ - Main.overview, - 'item-drag-cancelled', - this._onItemDragCancelled.bind(this), - ], [ - Main.overview, - 'window-drag-begin', - this._onWindowDragBegin.bind(this), - ], [ - Main.overview, - 'window-drag-cancelled', - this._onWindowDragEnd.bind(this), - ], [ - Main.overview, - 'window-drag-end', - this._onWindowDragEnd.bind(this), - ]); - - this.connect('destroy', this._onDestroy.bind(this)); - } - - vfunc_get_preferred_height(forWidth) { - const [minHeight, natHeight] = super.vfunc_get_preferred_height.call(this, forWidth); - if (!this._isHorizontal && this._maxHeight !== -1 && natHeight > this._maxHeight) - return [minHeight, this._maxHeight]; - else - return [minHeight, natHeight]; - } - - vfunc_get_preferred_width(forHeight) { - const [minWidth, natWidth] = super.vfunc_get_preferred_width.call(this, forHeight); - if (this._isHorizontal && this._maxWidth !== -1 && natWidth > this._maxWidth) - return [minWidth, this._maxWidth]; - else - return [minWidth, natWidth]; - } - - get _container() { - return this._dashContainer; - } - - _onDestroy() { - this.iconAnimator.destroy(); - - if (this._requiresVisibilityTimeout) { - GLib.source_remove(this._requiresVisibilityTimeout); - delete this._requiresVisibilityTimeout; - } - - if (this._ensureActorVisibilityTimeoutId) { - GLib.source_remove(this._ensureActorVisibilityTimeoutId); - delete this._ensureActorVisibilityTimeoutId; - } - } - - - _onItemDragBegin(...args) { - return Dash.Dash.prototype._onItemDragBegin.call(this, ...args); - } - - _onItemDragCancelled(...args) { - return Dash.Dash.prototype._onItemDragCancelled.call(this, ...args); - } - - _onItemDragEnd(...args) { - return Dash.Dash.prototype._onItemDragEnd.call(this, ...args); - } - - _endItemDrag(...args) { - return Dash.Dash.prototype._endItemDrag.call(this, ...args); - } - - _onItemDragMotion(...args) { - return Dash.Dash.prototype._onItemDragMotion.call(this, ...args); - } - - _appIdListToHash(...args) { - return Dash.Dash.prototype._appIdListToHash.call(this, ...args); - } - - _queueRedisplay(...args) { - return Dash.Dash.prototype._queueRedisplay.call(this, ...args); - } - - _hookUpLabel(...args) { - return Dash.Dash.prototype._hookUpLabel.call(this, ...args); - } - - _syncLabel(...args) { - return Dash.Dash.prototype._syncLabel.call(this, ...args); - } - - _clearDragPlaceholder(...args) { - return Dash.Dash.prototype._clearDragPlaceholder.call(this, ...args); - } - - _clearEmptyDropTarget(...args) { - return Dash.Dash.prototype._clearEmptyDropTarget.call(this, ...args); - } - - handleDragOver(source, actor, x, y, time) { - let ret; - if (this._isHorizontal) { - ret = Dash.Dash.prototype.handleDragOver.call(this, source, actor, x, y, time); - - if (ret === DND.DragMotionResult.CONTINUE) - return ret; - } else { - const propertyInjections = new Utils.PropertyInjectionsHandler(); - propertyInjections.add(this._box, 'width', { - get: () => this._box.get_children().reduce((a, c) => a + c.height, 0), - }); - - if (this._dragPlaceholder) { - propertyInjections.add(this._dragPlaceholder, 'width', { - get: () => this._dragPlaceholder.height, - }); - } - - ret = Dash.Dash.prototype.handleDragOver.call(this, source, actor, y, x, time); - propertyInjections.destroy(); - - if (ret === DND.DragMotionResult.CONTINUE) - return ret; - - if (this._dragPlaceholder) { - this._dragPlaceholder.child.set_width(this.iconSize / 2); - this._dragPlaceholder.child.set_height(this.iconSize); - - let pos = this._dragPlaceholderPos; - if (this._isHorizontal && - Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) - pos = this._box.get_children() - 1 - pos; - - if (pos !== this._dragPlaceholderPos) { - this._dragPlaceholderPos = pos; - this._box.set_child_at_index(this._dragPlaceholder, - this._dragPlaceholderPos); - } - } - } - - if (this._dragPlaceholder) { - // Ensure the next and previous icon are visible when moving the - // placeholder (we're assuming there's room for both of them) - const children = this._box.get_children(); - if (this._dragPlaceholderPos > 0) { - ensureActorVisibleInScrollView(this._scrollView, - children[this._dragPlaceholderPos - 1]); - } - - if (this._dragPlaceholderPos >= -1 && - this._dragPlaceholderPos < children.length - 1) { - ensureActorVisibleInScrollView(this._scrollView, - children[this._dragPlaceholderPos + 1]); - } - } - - return ret; - } - - acceptDrop(...args) { - return Dash.Dash.prototype.acceptDrop.call(this, ...args); - } - - _onWindowDragBegin(...args) { - return Dash.Dash.prototype._onWindowDragBegin.call(this, ...args); - } - - _onWindowDragEnd(...args) { - return Dash.Dash.prototype._onWindowDragEnd.call(this, ...args); - } - - _onScrollEvent(actor, event) { - // If scroll is not used because the icon is resized, let the scroll event propagate. - if (!Docking.DockManager.settings.iconSizeFixed) - return Clutter.EVENT_PROPAGATE; - - // reset timeout to avid conflicts with the mousehover event - this._ensureItemVisibility(null); - - // Skip to avoid double events mouse - if (event.get_scroll_direction() !== Clutter.ScrollDirection.SMOOTH) - return Clutter.EVENT_STOP; - - - let adjustment, delta = 0; - - if (this._isHorizontal) { - adjustment = this._scrollView.get_hadjustment - ? this._scrollView.get_hadjustment() - : this._scrollView.get_hscroll_bar().get_adjustment(); - } else { - adjustment = this._scrollView.get_vadjustment - ? this._scrollView.get_vadjustment() - : this._scrollView.get_vscroll_bar().get_adjustment(); - } - - const increment = adjustment.step_increment; - const [dx, dy] = event.get_scroll_delta(); - - if (this._isHorizontal) - delta = (Math.abs(dx) > Math.abs(dy) ? dx : dy) * increment; - else - delta = dy * increment; - - const value = adjustment.get_value(); - - // TODO: Remove this if possible. - if (Number.isNaN(value)) - adjustment.set_value(delta); - else - adjustment.set_value(value + delta); - - return Clutter.EVENT_STOP; - } - - _ensureItemVisibility(actor) { - if (actor?.hover) { - const destroyId = - actor.connect('destroy', () => this._ensureItemVisibility(null)); - this._ensureActorVisibilityTimeoutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, 100, () => { - actor.disconnect(destroyId); - ensureActorVisibleInScrollView(this._scrollView, actor); - this._ensureActorVisibilityTimeoutId = 0; - return GLib.SOURCE_REMOVE; - }); - } else if (this._ensureActorVisibilityTimeoutId) { - GLib.source_remove(this._ensureActorVisibilityTimeoutId); - this._ensureActorVisibilityTimeoutId = 0; - } - } - - _createAppItem(app) { - const appIcon = new AppIcons.makeAppIcon(app, this._monitorIndex, this.iconAnimator); - - if (appIcon._draggable) { - appIcon._draggable.connect('drag-begin', () => { - appIcon.opacity = 50; - }); - appIcon._draggable.connect('drag-end', () => { - appIcon.opacity = 255; - }); - } - - appIcon.connectObject('menu-state-changed', (_, opened) => { - this._itemMenuStateChanged(item, opened); - }, this); - - const item = new DockDashItemContainer(this._position); - item.setChild(appIcon); - - appIcon.connectObject('notify::hover', a => this._ensureItemVisibility(a), this); - appIcon.connectObject('clicked', actor => { - ensureActorVisibleInScrollView(this._scrollView, actor); - }, this); - - appIcon.connectObject('key-focus-in', actor => { - const [xShift, yShift] = ensureActorVisibleInScrollView(this._scrollView, actor); - - // This signal is triggered also by mouse click. The popup menu is opened at the original - // coordinates. Thus correct for the shift which is going to be applied to the scrollview. - if (appIcon._menu) { - appIcon._menu._boxPointer.xOffset = -xShift; - appIcon._menu._boxPointer.yOffset = -yShift; - } - }, this); - - appIcon.connectObject('notify::focused', () => { - const {settings} = Docking.DockManager; - if (appIcon.focused && settings.scrollToFocusedApplication) - ensureActorVisibleInScrollView(this._scrollView, item); - }, this); - - appIcon.connectObject('notify::urgent', () => { - if (appIcon.urgent) { - ensureActorVisibleInScrollView(this._scrollView, item); - if (Docking.DockManager.settings.showDockUrgentNotify) - this._requireVisibility(); - } - }, this); - - // Override default AppIcon label_actor, now the - // accessible_name is set at DashItemContainer.setLabelText - appIcon.label_actor = null; - item.setLabelText(app.get_name()); - - appIcon.icon.setIconSize(this.iconSize); - this._hookUpLabel(item, appIcon); - - item.connectObject('notify::position', () => appIcon.updateIconGeometry(), appIcon); - item.connectObject('notify::size', () => appIcon.updateIconGeometry(), appIcon); - - return item; - } - - _requireVisibility() { - this.requiresVisibility = true; - - if (this._requiresVisibilityTimeout) - GLib.source_remove(this._requiresVisibilityTimeout); - - this._requiresVisibilityTimeout = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, - DASH_VISIBILITY_TIMEOUT, () => { - this._requiresVisibilityTimeout = 0; - this.requiresVisibility = false; - }); - } - - /** - * Return an array with the "proper" appIcons currently in the dash - */ - getAppIcons() { - // Only consider children which are "proper" - // icons (i.e. ignoring drag placeholders) and which are not - // animating out (which means they will be destroyed at the end of - // the animation) - const iconChildren = this._box.get_children().filter(actor => { - return actor.child && - !!actor.child.icon && - !actor.animatingOut; - }); - - const appIcons = iconChildren.map(actor => { - return actor.child; - }); - - return appIcons; - } - - _itemMenuStateChanged(item, opened) { - Dash.Dash.prototype._itemMenuStateChanged.call(this, item, opened); - - if (opened) { - this.emit('menu-opened'); - } else { - // I want to listen from outside when a menu is closed. I used to - // add a custom signal to the appIcon, since gnome 3.8 the signal - // calling this callback was added upstream. - this.emit('menu-closed'); - } - } - - _adjustIconSize() { - // For the icon size, we only consider children which are "proper" - // icons (i.e. ignoring drag placeholders) and which are not - // animating out (which means they will be destroyed at the end of - // the animation) - const iconChildren = this._box.get_children().filter(actor => { - return actor.child && - actor.child._delegate && - actor.child._delegate.icon && - !actor.animatingOut; - }); - - iconChildren.push(this._showAppsIcon); - - if (this._maxWidth === -1 && this._maxHeight === -1) - return; - - // Check if the container is present in the stage. This avoids critical - // errors when unlocking the screen - if (!this._container.get_stage()) - return; - - const themeNode = this._dashContainer.get_theme_node(); - const maxAllocation = new Clutter.ActorBox({ - x1: 0, - y1: 0, - x2: this._isHorizontal ? this._maxWidth : 42 /* whatever */, - y2: this._isHorizontal ? 42 : this._maxHeight, - }); - const maxContent = themeNode.get_content_box(maxAllocation); - let availSpace; - if (this._isHorizontal) - availSpace = maxContent.get_width(); - else - availSpace = maxContent.get_height(); - - const spacing = themeNode.get_length('spacing'); - - const [{child: firstButton}] = iconChildren; - const {child: firstIcon} = firstButton?.icon ?? {child: null}; - - // if no icons there's nothing to adjust - if (!firstIcon) - return; - - // Enforce valid spacings during the size request - firstIcon.ensure_style(); - const [, , iconWidth, iconHeight] = firstIcon.get_preferred_size(); - const [, , buttonWidth, buttonHeight] = firstButton.get_preferred_size(); - - if (this._isHorizontal) { - // Subtract icon padding and box spacing from the available width - availSpace -= iconChildren.length * (buttonWidth - iconWidth) + - (iconChildren.length - 1) * spacing; - - if (this._separator) { - const [, , separatorWidth] = this._separator.get_preferred_size(); - availSpace -= separatorWidth + spacing; - } - } else { - // Subtract icon padding and box spacing from the available height - availSpace -= iconChildren.length * (buttonHeight - iconHeight) + - (iconChildren.length - 1) * spacing; - - if (this._separator) { - const [, , , separatorHeight] = this._separator.get_preferred_size(); - availSpace -= separatorHeight + spacing; - } - } - - const maxIconSize = availSpace / iconChildren.length; - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - const iconSizes = this._availableIconSizes.map(s => s * scaleFactor); - - let [newIconSize] = this._availableIconSizes; - for (let i = 0; i < iconSizes.length; i++) { - if (iconSizes[i] <= maxIconSize) - newIconSize = this._availableIconSizes[i]; - } - - if (newIconSize === this.iconSize) - return; - - const oldIconSize = this.iconSize; - this.iconSize = newIconSize; - this.emit('icon-size-changed'); - - const scale = oldIconSize / newIconSize; - for (let i = 0; i < iconChildren.length; i++) { - const {icon} = iconChildren[i].child._delegate; - - // Set the new size immediately, to keep the icons' sizes - // in sync with this.iconSize - icon.setIconSize(this.iconSize); - - // Don't animate the icon size change when the overview - // is transitioning, not visible or when initially filling - // the dash - if (!Main.overview.visible || Main.overview.animationInProgress || - !this._shownInitially) - continue; - - const [targetWidth, targetHeight] = icon.icon.get_size(); - - // Scale the icon's texture to the previous size and - // tween to the new size - icon.icon.set_size(icon.icon.width * scale, - icon.icon.height * scale); - - icon.icon.ease({ - width: targetWidth, - height: targetHeight, - duration: DASH_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - } - - if (this._separator) { - const animateProperties = this._isHorizontal - ? {height: this.iconSize} : {width: this.iconSize}; - - this._separator.ease({ - ...animateProperties, - duration: DASH_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - } - } - - _redisplay() { - const favorites = AppFavorites.getAppFavorites().getFavoriteMap(); - - let running = this._appSystem.get_running(); - const dockManager = Docking.DockManager.getDefault(); - const {settings} = dockManager; - - this._scrollView.set({ - xAlign: Clutter.ActorAlign.FILL, - yAlign: Clutter.ActorAlign.FILL, - }); - if (dockManager.settings.dockExtended) { - if (!this._isHorizontal) { - this._scrollView.yAlign = dockManager.settings.alwaysCenterIcons - ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.START; - } else { - this._scrollView.xAlign = dockManager.settings.alwaysCenterIcons - ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.START; - } - } - - if (settings.isolateWorkspaces || - settings.isolateMonitors) { - // When using isolation, we filter out apps that have no windows in - // the current workspace - const monitorIndex = this._monitorIndex; - running = running.filter(app => - AppIcons.getInterestingWindows(app.get_windows(), monitorIndex).length); - } - - const children = this._box.get_children().filter(actor => { - return actor.child && - actor.child._delegate && - actor.child._delegate.app; - }); - // Apps currently in the dash - let oldApps = children.map(actor => actor.child._delegate.app); - // Apps supposed to be in the dash - const newApps = []; - - const {showFavorites} = settings; - if (showFavorites) - newApps.push(...Object.values(favorites)); - - if (settings.showRunning) { - // We reorder the running apps so that they don't change position on the - // dash with every redisplay() call - - // First: add the apps from the oldApps list that are still running - oldApps.forEach(oldApp => { - const index = running.indexOf(oldApp); - if (index > -1) { - const [app] = running.splice(index, 1); - if (!showFavorites || !(app.get_id() in favorites)) - newApps.push(app); - } - }); - - // Second: add the new apps - running.forEach(app => { - if (!showFavorites || !(app.get_id() in favorites)) - newApps.push(app); - }); - } - - this._signalsHandler.removeWithLabel(Labels.SHOW_MOUNTS); - if (dockManager.removables) { - this._signalsHandler.addWithLabel(Labels.SHOW_MOUNTS, - dockManager.removables, 'changed', this._queueRedisplay.bind(this)); - dockManager.removables.getApps().forEach(removable => { - if (!newApps.includes(removable)) - newApps.push(removable); - }); - } else { - oldApps = oldApps.filter(app => !app.location || app.isTrash); - } - - if (dockManager.trash) { - const trashApp = dockManager.trash.getApp(); - if (!newApps.includes(trashApp)) - newApps.push(trashApp); - } else { - oldApps = oldApps.filter(app => !app.isTrash); - } - - // Temporary remove the separator so that we don't compute to position icons - const oldSeparatorPos = this._box.get_children().indexOf(this._separator); - if (this._separator) - this._box.remove_child(this._separator); - - // Figure out the actual changes to the list of items; we iterate - // over both the list of items currently in the dash and the list - // of items expected there, and collect additions and removals. - // Moves are both an addition and a removal, where the order of - // the operations depends on whether we encounter the position - // where the item has been added first or the one from where it - // was removed. - // There is an assumption that only one item is moved at a given - // time; when moving several items at once, everything will still - // end up at the right position, but there might be additional - // additions/removals (e.g. it might remove all the launchers - // and add them back in the new order even if a smaller set of - // additions and removals is possible). - // If above assumptions turns out to be a problem, we might need - // to use a more sophisticated algorithm, e.g. Longest Common - // Subsequence as used by diff. - - const addedItems = []; - const removedActors = []; - - let newIndex = 0; - let oldIndex = 0; - while (newIndex < newApps.length || oldIndex < oldApps.length) { - const oldApp = oldApps.length > oldIndex ? oldApps[oldIndex] : null; - const newApp = newApps.length > newIndex ? newApps[newIndex] : null; - - // No change at oldIndex/newIndex - if (oldApp === newApp) { - oldIndex++; - newIndex++; - continue; - } - - // App removed at oldIndex - if (oldApp && !newApps.includes(oldApp)) { - removedActors.push(children[oldIndex]); - oldIndex++; - continue; - } - - // App added at newIndex - if (newApp && !oldApps.includes(newApp)) { - addedItems.push({ - app: newApp, - item: this._createAppItem(newApp), - pos: newIndex, - }); - newIndex++; - continue; - } - - // App moved - const nextApp = newApps.length > newIndex + 1 - ? newApps[newIndex + 1] : null; - const insertHere = nextApp && nextApp === oldApp; - const alreadyRemoved = removedActors.reduce((result, actor) => { - const removedApp = actor.child._delegate.app; - return result || removedApp === newApp; - }, false); - - if (insertHere || alreadyRemoved) { - const newItem = this._createAppItem(newApp); - addedItems.push({ - app: newApp, - item: newItem, - pos: newIndex + removedActors.length, - }); - newIndex++; - } else { - removedActors.push(children[oldIndex]); - oldIndex++; - } - } - - for (let i = 0; i < addedItems.length; i++) { - this._box.insert_child_at_index(addedItems[i].item, - addedItems[i].pos); - } - - for (let i = 0; i < removedActors.length; i++) { - const item = removedActors[i]; - - // Don't animate item removal when the overview is transitioning - // or hidden - if (!Main.overview.animationInProgress) - item.animateOutAndDestroy(); - else - item.destroy(); - } - - // Update separator - const nFavorites = Object.keys(favorites).length; - const nIcons = children.length + addedItems.length - removedActors.length; - if (nFavorites > 0 && nFavorites < nIcons) { - if (!this._separator) { - this._separator = new St.Widget({ - style_class: 'dash-separator', - x_align: this._isHorizontal - ? Clutter.ActorAlign.FILL : Clutter.ActorAlign.CENTER, - y_align: this._isHorizontal - ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.FILL, - width: this._isHorizontal ? -1 : this.iconSize, - height: this._isHorizontal ? this.iconSize : -1, - reactive: true, - track_hover: true, - }); - this._separator.connect('notify::hover', a => this._ensureItemVisibility(a)); - } - let pos = nFavorites + this._animatingPlaceholdersCount; - if (this._dragPlaceholder) - pos++; - const removedFavorites = removedActors.filter(a => - children.indexOf(a) < oldSeparatorPos); - pos += removedFavorites.length; - this._box.insert_child_at_index(this._separator, pos); - } else if (this._separator) { - this._separator.destroy(); - this._separator = null; - } - - this._adjustIconSize(); - - // Skip animations on first run when adding the initial set - // of items, to avoid all items zooming in at once - const animate = this._shownInitially && - !Main.layoutManager._startingUp; - - if (!this._shownInitially) - this._shownInitially = true; - - addedItems.forEach(({item}) => item.show(animate)); - - // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744 - // Without it, StBoxLayout may use a stale size cache - this._box.queue_relayout(); - - // This will update the size, and the corresponding number for each icon - this._updateNumberOverlay(); - - this.updateShowAppsButton(); - } - - _updateNumberOverlay() { - const appIcons = this.getAppIcons(); - let counter = 1; - appIcons.forEach(icon => { - if (counter < 10) { - icon.setNumberOverlay(counter); - counter++; - } else if (counter === 10) { - icon.setNumberOverlay(0); - counter++; - } else { - // No overlay after 10 - icon.setNumberOverlay(-1); - } - icon.updateNumberOverlay(); - }); - } - - toggleNumberOverlay(activate) { - const appIcons = this.getAppIcons(); - appIcons.forEach(icon => { - icon.toggleNumberOverlay(activate); - }); - } - - _initializeIconSize(maxSize) { - const maxAllowed = baseIconSizes[baseIconSizes.length - 1]; - maxSize = Math.min(maxSize, maxAllowed); - - if (Docking.DockManager.settings.iconSizeFixed) { - this._availableIconSizes = [maxSize]; - } else { - this._availableIconSizes = baseIconSizes.filter(val => { - return val < maxSize; - }); - this._availableIconSizes.push(maxSize); - } - } - - setIconSize(maxSize, doNotAnimate) { - this._initializeIconSize(maxSize); - - if (doNotAnimate) - this._shownInitially = false; - - this._queueRedisplay(); - } - - /** - * Reset the displayed apps icon to maintain the correct order when changing - * show favorites/show running settings - */ - resetAppIcons() { - const children = this._box.get_children().filter(actor => { - return actor.child && - !!actor.child.icon; - }); - for (let i = 0; i < children.length; i++) { - const item = children[i]; - item.destroy(); - } - - // to avoid ugly animations, just suppress them like when dash is first loaded. - this._shownInitially = false; - this._redisplay(); - } - - get showAppsButton() { - return this._showAppsIcon.toggleButton; - } - - showShowAppsButton() { - this._showAppsIcon.visible = true; - this._showAppsIcon.show(true); - this.updateShowAppsButton(); - } - - hideShowAppsButton() { - this._showAppsIcon.visible = false; - } - - setMaxSize(maxWidth, maxHeight) { - if (this._maxWidth === maxWidth && - this._maxHeight === maxHeight) - return; - - this._maxWidth = maxWidth; - this._maxHeight = maxHeight; - this._queueRedisplay(); - } - - updateShowAppsButton() { - if (this._showAppsIcon.get_parent() && !this._showAppsIcon.visible) - return; - - const {settings} = Docking.DockManager; - const notifiedProperties = []; - const showAppsContainer = settings.showAppsAlwaysInTheEdge || !settings.dockExtended - ? this._dashContainer : this._boxContainer; - - this._signalsHandler.addWithLabel(Labels.FIRST_LAST_CHILD_WORKAROUND, - showAppsContainer, 'notify', - (_obj, pspec) => notifiedProperties.push(pspec.name)); - - if (this._showAppsIcon.get_parent() !== showAppsContainer) { - this._showAppsIcon.get_parent()?.remove_child(this._showAppsIcon); - - if (Docking.DockManager.settings.showAppsAtTop) - showAppsContainer.insert_child_below(this._showAppsIcon, null); - else - showAppsContainer.insert_child_above(this._showAppsIcon, null); - } else if (settings.showAppsAtTop) { - showAppsContainer.set_child_below_sibling(this._showAppsIcon, null); - } else { - showAppsContainer.set_child_above_sibling(this._showAppsIcon, null); - } - - this._signalsHandler.removeWithLabel(Labels.FIRST_LAST_CHILD_WORKAROUND); - - // This is indeed ugly, but we need to ensure that the last and first - // visible widgets are re-computed by St, that is buggy because of a - // mutter issue that is being fixed: - // https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2047 - if (!notifiedProperties.includes('first-child')) - showAppsContainer.notify('first-child'); - if (!notifiedProperties.includes('last-child')) - showAppsContainer.notify('last-child'); - } -}); - - -/** - * This is a copy of the same function in utils.js, but also adjust horizontal scrolling - * and perform few further checks on the current value to avoid changing the values when - * it would be clamp to the current one in any case. - * Return the amount of shift applied - * - * @param scrollView - * @param actor - */ -function ensureActorVisibleInScrollView(scrollView, actor) { - // access to scrollView.[hv]scroll was deprecated in gnome 46 - // instead, adjustment can be accessed directly - // keep old way for backwards compatibility (gnome <= 45) - const vAdjustment = scrollView.vadjustment ?? scrollView.vscroll.adjustment; - const hAdjustment = scrollView.hadjustment ?? scrollView.hscroll.adjustment; - const {value: vValue0, pageSize: vPageSize, upper: vUpper} = vAdjustment; - const {value: hValue0, pageSize: hPageSize, upper: hUpper} = hAdjustment; - let [hValue, vValue] = [hValue0, vValue0]; - let vOffset = 0; - let hOffset = 0; - - const fade = scrollView.get_effect('fade'); - if (fade) { - vOffset = fade.fade_margins.top; - hOffset = fade.fade_margins.left; - } - - const box = actor.get_allocation_box(); - let {y1} = box, {y2} = box, {x1} = box, {x2} = box; - - let parent = actor.get_parent(); - while (parent !== scrollView) { - if (!parent) - throw new Error('Actor not in scroll view'); - - const parentBox = parent.get_allocation_box(); - y1 += parentBox.y1; - y2 += parentBox.y1; - x1 += parentBox.x1; - x2 += parentBox.x1; - parent = parent.get_parent(); - } - - if (y1 < vValue + vOffset) - vValue = Math.max(0, y1 - vOffset); - else if (vValue < vUpper - vPageSize && y2 > vValue + vPageSize - vOffset) - vValue = Math.min(vUpper - vPageSize, y2 + vOffset - vPageSize); - - if (x1 < hValue + hOffset) - hValue = Math.max(0, x1 - hOffset); - else if (hValue < hUpper - hPageSize && x2 > hValue + hPageSize - hOffset) - hValue = Math.min(hUpper - hPageSize, x2 + hOffset - hPageSize); - - if (vValue !== vValue0) { - vAdjustment.ease(vValue, { - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - duration: Util.SCROLL_TIME, - }); - } - - if (hValue !== hValue0) { - hAdjustment.ease(hValue, { - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - duration: Util.SCROLL_TIME, - }); - } - - return [hValue - hValue0, vValue - vValue0]; -} |