fix: preserve scroll position in switcher if windows change

This commit is contained in:
lwouis committed 2026-02-11 21:35:41 +01:00
1 parent 6de7fee90c
commit fa9e4d0ee1
3 files changed
+27 -8

No files matched your search

+5 -4
View File
@@ -205,15 +205,16 @@ class App: AppCenterApplication {
refreshOpenUiWithThrottling {
guard self.appIsBeingUsed else { return }
if !Windows.updatesBeforeShowing() { self.hideUi(); return }
self.refreshUi()
self.refreshUi(true)
}
}
func refreshUi() {
func refreshUi(_ preserveScrollPosition: Bool = false) {
guard self.appIsBeingUsed else { return }
let preservedScrollOrigin = preserveScrollPosition ? thumbnailsPanel.tilesView.currentScrollOrigin() : nil
Windows.updateSelectedWindow()
guard self.appIsBeingUsed else { return }
self.thumbnailsPanel.updateContents()
self.thumbnailsPanel.updateContents(preservedScrollOrigin)
guard self.appIsBeingUsed else { return }
Windows.voiceOverWindow() // at this point TileViews are assigned to the window, and ready
guard self.appIsBeingUsed else { return }
+3 -3
View File
@@ -32,9 +32,9 @@ class TilesPanel: NSPanel {
appearance = NSAppearance(named: Appearance.currentTheme == .dark ? .vibrantDark : .vibrantLight)
}
func updateContents() {
func updateContents(_ preservedScrollOrigin: CGPoint?) {
caTransaction {
tilesView.updateItemsAndLayout()
tilesView.updateItemsAndLayout(preservedScrollOrigin)
guard App.app.appIsBeingUsed else { return }
setContentSize(tilesView.contentView.frame.size)
guard App.app.appIsBeingUsed else { return }
@@ -130,4 +130,4 @@ extension TilesPanel: NSWindowDelegate {
Applications.manuallyRefreshAllWindows()
}
}
}
}
+19 -1
View File
@@ -118,7 +118,7 @@ class TilesView {
Windows.updateSelectedAndHoveredWindowIndex(targetIndex)
}
func updateItemsAndLayout() {
func updateItemsAndLayout(_ preservedScrollOrigin: CGPoint?) {
let widthMax = TilesPanel.maxThumbnailsWidth().rounded()
if let (maxX, maxY, labelHeight, rowSignature) = layoutTileViews(widthMax) {
layoutParentViews(maxX, widthMax, maxY, labelHeight)
@@ -137,9 +137,27 @@ class TilesView {
lastRowSignature = rowSignature
}
highlightStartView()
if let preservedScrollOrigin {
restoreScrollOrigin(preservedScrollOrigin)
}
}
}
func currentScrollOrigin() -> CGPoint {
scrollView.contentView.bounds.origin
}
private func restoreScrollOrigin(_ scrollOrigin: CGPoint) {
guard let documentView = scrollView.documentView else { return }
let visibleSize = scrollView.contentView.bounds.size
let documentSize = documentView.frame.size
let maxX = max(0, documentSize.width - visibleSize.width)
let maxY = max(0, documentSize.height - visibleSize.height)
let clampedOrigin = CGPoint(x: min(max(0, scrollOrigin.x), maxX), y: min(max(0, scrollOrigin.y), maxY))
scrollView.contentView.scroll(to: clampedOrigin)
scrollView.reflectScrolledClipView(scrollView.contentView)
}
private func layoutTileViews(_ widthMax: CGFloat) -> (CGFloat, CGFloat, CGFloat, [Int])? {
let labelHeight = Self.layoutCache.labelHeight
let height = TileView.height(labelHeight)