From c7e5daa357182f0243ca5c57d16e06d1de70529f Mon Sep 17 00:00:00 2001 From: Louis Pontoise Date: Mon, 1 Jun 2020 18:19:00 +0900 Subject: [PATCH] fix: mouse hover during scroll bounce produced visual jank (closes #259) --- src/ui/main-window/ThumbnailView.swift | 10 ++------- src/ui/main-window/ThumbnailsView.swift | 30 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/ui/main-window/ThumbnailView.swift b/src/ui/main-window/ThumbnailView.swift index 067b0069..66390362 100644 --- a/src/ui/main-window/ThumbnailView.swift +++ b/src/ui/main-window/ThumbnailView.swift @@ -98,12 +98,6 @@ class ThumbnailView: NSStackView { assignIfDifferent(&subviews.first!.frame.size, frame.size) self.mouseDownCallback = { () -> Void in App.app.focusSelectedWindow(element) } self.mouseMovedCallback = { () -> Void in Windows.updateFocusedWindowIndex(index) } - if trackingAreas.count == 0 { - addTrackingArea(NSTrackingArea(rect: bounds, options: [.mouseMoved, .activeAlways], owner: self, userInfo: nil)) - } else if trackingAreas.count > 0 && trackingAreas[0].rect != bounds { - removeTrackingArea(trackingAreas[0]) - addTrackingArea(NSTrackingArea(rect: bounds, options: [.mouseMoved, .activeAlways], owner: self, userInfo: nil)) - } // force a display to avoid flickering; see https://github.com/lwouis/alt-tab-macos/issues/197 // quirk: display() should be called last as it resets thumbnail.frame.size somehow if labelChanged { @@ -144,8 +138,8 @@ class ThumbnailView: NSStackView { return open != nil } - override func mouseMoved(with event: NSEvent) { - if Preferences.mouseHoverEnabled { + func mouseMoved() { + if !isHighlighted { mouseMovedCallback() } } diff --git a/src/ui/main-window/ThumbnailsView.swift b/src/ui/main-window/ThumbnailsView.swift index 705d7a58..5a96b160 100644 --- a/src/ui/main-window/ThumbnailsView.swift +++ b/src/ui/main-window/ThumbnailsView.swift @@ -117,6 +117,10 @@ class ThumbnailsView: NSVisualEffectView { scrollView.documentView!.subviews.forEach { $0.frame.origin.x -= croppedWidth } } scrollView.documentView!.frame.size = NSSize(width: maxX, height: maxY) + if let existingTrackingArea = scrollView.trackingAreas.first { + scrollView.documentView!.removeTrackingArea(existingTrackingArea) + } + scrollView.addTrackingArea(NSTrackingArea(rect: scrollView.bounds, options: [.mouseMoved, .activeAlways], owner: scrollView, userInfo: nil)) } func centerRows(_ maxX: CGFloat) { @@ -163,6 +167,8 @@ class ScrollView: NSScrollView { // overriding scrollWheel() turns this false; we force it to be true to enable responsive scrolling override class var isCompatibleWithResponsiveScrolling: Bool { true } + var isCurrentlyScrolling = false + convenience init() { self.init(frame: .zero) documentView = FlippedView(frame: .zero) @@ -173,6 +179,30 @@ class ScrollView: NSScrollView { horizontalScrollElasticity = .none usesPredominantAxisScrolling = true forceOverlayStyle() + observeScrollingEvents() + } + + private func observeScrollingEvents() { + NotificationCenter.default.addObserver(forName: NSScrollView.didEndLiveScrollNotification, object: nil, queue: nil) { [weak self] _ in + self?.isCurrentlyScrolling = false + } + NotificationCenter.default.addObserver(forName: NSScrollView.willStartLiveScrollNotification, object: nil, queue: nil) { [weak self] _ in + self?.isCurrentlyScrolling = true + } + } + + override func mouseMoved(with event: NSEvent) { + // disable mouse hover during scrolling as it creates jank during elastic bounces at the start/end of the scrollview + if !Preferences.mouseHoverEnabled || isCurrentlyScrolling { return } + if let hit = hitTest(App.app.thumbnailsPanel.mouseLocationOutsideOfEventStream) { + var target: NSView? = hit + while !(target is ThumbnailView) && target != nil { + target = target!.superview + } + if let target = target, target is ThumbnailView { + (target as! ThumbnailView).mouseMoved() + } + } } // holding shift and using the scrolling wheel will generate a horizontal movement