From 8d3d9ef8d8688999d959f1062a62e9f3b7f489fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Mon, 19 Feb 2024 14:42:04 +0100 Subject: [PATCH 23/28] workspace-indicator: Handle preview overflow We currently avoid previews from overflowing in most setups by artificially limiting them to a maximum of six workspaces. Add some proper handling to also cover cases where space is more limited, and to allow removing the restriction in the future. For that, wrap the previews in an auto-scrolling scroll view and add overflow indicators on each side. Part-of: --- .../workspace-indicator/stylesheet-dark.css | 4 ++ .../workspace-indicator/workspaceIndicator.js | 64 ++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/extensions/workspace-indicator/stylesheet-dark.css b/extensions/workspace-indicator/stylesheet-dark.css index 3e2ba67f..22d13370 100644 --- a/extensions/workspace-indicator/stylesheet-dark.css +++ b/extensions/workspace-indicator/stylesheet-dark.css @@ -9,6 +9,10 @@ padding: 0 8px; } +.workspace-indicator .workspaces-view.hfade { + -st-hfade-offset: 20px; +} + .workspace-indicator .workspaces-box { padding: 5px; spacing: 3px; diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js index 73ebca6f..314b9f45 100644 --- a/extensions/workspace-indicator/workspaceIndicator.js +++ b/extensions/workspace-indicator/workspaceIndicator.js @@ -20,6 +20,8 @@ import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; const TOOLTIP_OFFSET = 6; const TOOLTIP_ANIMATION_TIME = 150; +const SCROLL_TIME = 100; + const MAX_THUMBNAILS = 6; let baseStyleClassName = ''; @@ -294,13 +296,29 @@ class WorkspacePreviews extends Clutter.Actor { workspaceManager.connectObject( 'notify::n-workspaces', () => this._updateThumbnails(), GObject.ConnectFlags.AFTER, + 'workspace-switched', () => this._updateScrollPosition(), this); + this.connect('notify::mapped', () => { + if (this.mapped) + this._updateScrollPosition(); + }); + this._thumbnailsBox = new St.BoxLayout({ style_class: 'workspaces-box', y_expand: true, }); - this.add_child(this._thumbnailsBox); + + this._scrollView = new St.ScrollView({ + style_class: 'workspaces-view hfade', + enable_mouse_scrolling: false, + hscrollbar_policy: St.PolicyType.EXTERNAL, + vscrollbar_policy: St.PolicyType.NEVER, + y_expand: true, + child: this._thumbnailsBox, + }); + + this.add_child(this._scrollView); this._updateThumbnails(); } @@ -314,6 +332,50 @@ class WorkspacePreviews extends Clutter.Actor { const thumb = new WorkspaceThumbnail(i); this._thumbnailsBox.add_child(thumb); } + + if (this.mapped) + this._updateScrollPosition(); + } + + _updateScrollPosition() { + const adjustment = this._scrollView.hadjustment; + const {upper, pageSize} = adjustment; + let {value} = adjustment; + + const activeWorkspace = + [...this._thumbnailsBox].find(a => a.active); + + if (!activeWorkspace) + return; + + let offset = 0; + const hfade = this._scrollView.get_effect('fade'); + if (hfade) + offset = hfade.fade_margins.left; + + let {x1, x2} = activeWorkspace.get_allocation_box(); + let parent = activeWorkspace.get_parent(); + while (parent !== this._scrollView) { + if (!parent) + throw new Error('actor not in scroll view'); + + const box = parent.get_allocation_box(); + x1 += box.x1; + x2 += box.x1; + parent = parent.get_parent(); + } + + if (x1 < value + offset) + value = Math.max(0, x1 - offset); + else if (x2 > value + pageSize - offset) + value = Math.min(upper, x2 + offset - pageSize); + else + return; + + adjustment.ease(value, { + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + duration: SCROLL_TIME, + }); } } -- 2.44.0