perf: create overlay view to optimize view count
This commit is contained in:
1 parent
fefc491ce5
commit
ec5802a487
5 files changed
+133
-82
No files matched your search
@@ -209,6 +209,7 @@
|
||||
D04BA0DD6819010987B578D1 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BA07BBF2237CC6C72D264 /* Localizable.strings */; };
|
||||
D04BA100BD0F47828EB649FF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BAAEC2847830A3991F8D1 /* InfoPlist.strings */; };
|
||||
D04BA11E56383D082D7BE5A5 /* ThumbnailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BAA998119CAA8B70A2B67 /* ThumbnailsView.swift */; };
|
||||
D04BAFC1A1B2C3D4E5F60002 /* HighlightOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BAFC0A1B2C3D4E5F60001 /* HighlightOverlayView.swift */; };
|
||||
D04BA14D93726795A6937832 /* LabelAndControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA2526DC6726E0F7ACF7C /* LabelAndControl.swift */; };
|
||||
D04BA15A1B0C4871EA7CB899 /* GeneralTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BACE22DC907F03D193075 /* GeneralTab.swift */; };
|
||||
D04BA1621718FF26F8D5E75D /* CustomRecorderControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BAE333F7170E87C5AC0EF /* CustomRecorderControl.swift */; };
|
||||
@@ -672,6 +673,7 @@
|
||||
D04BAA4442D0CE3A4972937F /* nl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = nl; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
D04BAA6E43F1E6EB81F953AF /* ru */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ru; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
D04BAA998119CAA8B70A2B67 /* ThumbnailsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThumbnailsView.swift; sourceTree = "<group>"; };
|
||||
D04BAFC0A1B2C3D4E5F60001 /* HighlightOverlayView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HighlightOverlayView.swift; sourceTree = "<group>"; };
|
||||
D04BAA9E0539EE620D08F63F /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = fr; path = InfoPlist.strings; sourceTree = "<group>"; };
|
||||
D04BAAA1835480F9B3CCF170 /* blacklists@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "blacklists@2x.png"; sourceTree = "<group>"; };
|
||||
D04BAAB92261FC04854FDDE9 /* App.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
|
||||
@@ -1650,6 +1652,7 @@
|
||||
D04BA1DF8CAB2FAB7FE9244B /* ThumbnailFontIconView.swift */,
|
||||
D04BA258B56193958D60978A /* ThumbnailView.swift */,
|
||||
D04BAA998119CAA8B70A2B67 /* ThumbnailsView.swift */,
|
||||
D04BAFC0A1B2C3D4E5F60001 /* HighlightOverlayView.swift */,
|
||||
AA974BA829B7D84C0099A29E /* PreviewPanel.swift */,
|
||||
);
|
||||
path = "main-window";
|
||||
@@ -2483,6 +2486,7 @@
|
||||
D04BAD2A7F2E8BF64EE982E9 /* TextArea.swift in Sources */,
|
||||
5F17452E2F1A908D00128EF8 /* WindowDiscriminator.swift in Sources */,
|
||||
D04BA11E56383D082D7BE5A5 /* ThumbnailsView.swift in Sources */,
|
||||
D04BAFC1A1B2C3D4E5F60002 /* HighlightOverlayView.swift in Sources */,
|
||||
5F21C9E42C6E94700091F72F /* CustomizeStyleSheet.swift in Sources */,
|
||||
D04BA1621718FF26F8D5E75D /* CustomRecorderControl.swift in Sources */,
|
||||
D04BA1637E125D38546C26E2 /* StackView.swift in Sources */,
|
||||
|
||||
@@ -13,7 +13,7 @@ class TrafficLightButton: NSButton {
|
||||
self.type = type
|
||||
target = self
|
||||
action = #selector(onClick)
|
||||
addTrackingArea(NSTrackingArea(rect: bounds, options: [.mouseEnteredAndExited, .activeInKeyWindow], owner: self, userInfo: nil))
|
||||
addTrackingArea(NSTrackingArea(rect: .zero, options: [.mouseEnteredAndExited, .activeInKeyWindow, .inVisibleRect], owner: self, userInfo: nil))
|
||||
toolTip = tooltip
|
||||
appearance = NSAppearance(named: .aqua)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
import Cocoa
|
||||
|
||||
class HighlightOverlayView: FlippedView {
|
||||
let focusedLayer = noAnimation { CALayer() }
|
||||
let hoveredLayer = noAnimation { CALayer() }
|
||||
var quitButton = TrafficLightButton(.quit, NSLocalizedString("Quit app", comment: ""))
|
||||
var closeButton = TrafficLightButton(.close, NSLocalizedString("Close window", comment: ""))
|
||||
var minimizeButton = TrafficLightButton(.miniaturize, NSLocalizedString("Minimize/Deminimize window", comment: ""))
|
||||
var maximizeButton = TrafficLightButton(.fullscreen, NSLocalizedString("Fullscreen/Defullscreen window", comment: ""))
|
||||
var isShowingWindowControls = false
|
||||
|
||||
var windowControlButtons: [TrafficLightButton] { [quitButton, closeButton, minimizeButton, maximizeButton] }
|
||||
|
||||
convenience init() {
|
||||
self.init(frame: .zero)
|
||||
wantsLayer = true
|
||||
layer!.masksToBounds = false
|
||||
for highlightLayer in [focusedLayer, hoveredLayer] {
|
||||
highlightLayer.isHidden = true
|
||||
layer!.addSublayer(highlightLayer)
|
||||
}
|
||||
for button in windowControlButtons {
|
||||
addSubview(button)
|
||||
button.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
override func hitTest(_ point: NSPoint) -> NSView? {
|
||||
for button in windowControlButtons {
|
||||
guard !button.isHidden else { continue }
|
||||
let buttonPoint = button.convert(point, from: self)
|
||||
if button.bounds.contains(buttonPoint) {
|
||||
return button.hitTest(button.convert(point, from: self))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateHighlight(focusedView: ThumbnailView?, hoveredView: ThumbnailView?) {
|
||||
updateLayer(focusedLayer, for: focusedView, isFocused: true)
|
||||
updateLayer(hoveredLayer, for: hoveredView, isFocused: false)
|
||||
}
|
||||
|
||||
private func updateLayer(_ highlightLayer: CALayer, for view: ThumbnailView?, isFocused: Bool) {
|
||||
guard let view, view.frame != .zero else {
|
||||
highlightLayer.isHidden = true
|
||||
return
|
||||
}
|
||||
let vStackFrame = view.vStackView.frame
|
||||
let rect = CGRect(
|
||||
x: view.frame.origin.x + vStackFrame.origin.x,
|
||||
y: view.frame.origin.y + vStackFrame.origin.y,
|
||||
width: vStackFrame.width,
|
||||
height: vStackFrame.height
|
||||
)
|
||||
highlightLayer.frame = rect
|
||||
highlightLayer.cornerRadius = Appearance.cellCornerRadius
|
||||
highlightLayer.backgroundColor = (isFocused
|
||||
? Appearance.highlightFocusedBackgroundColor
|
||||
: Appearance.highlightHoveredBackgroundColor).cgColor
|
||||
highlightLayer.borderColor = (isFocused
|
||||
? Appearance.highlightFocusedBorderColor
|
||||
: Appearance.highlightHoveredBorderColor).cgColor
|
||||
highlightLayer.borderWidth = Appearance.highlightBorderWidth
|
||||
highlightLayer.isHidden = false
|
||||
}
|
||||
|
||||
func showWindowControls(for view: ThumbnailView) {
|
||||
guard Preferences.appearanceStyle == .thumbnails else { hideWindowControls(); return }
|
||||
let shouldShow = !Preferences.hideColoredCircles && !Appearance.hideThumbnails
|
||||
guard shouldShow, let window = view.window_ else { hideWindowControls(); return }
|
||||
isShowingWindowControls = true
|
||||
for button in windowControlButtons { button.window_ = window }
|
||||
let thumbnailOrigin = NSPoint(
|
||||
x: view.frame.origin.x + view.thumbnail.frame.origin.x,
|
||||
y: view.frame.origin.y + view.thumbnail.frame.origin.y
|
||||
)
|
||||
let thumbnailWidth = view.thumbnail.frame.width
|
||||
var xOffset = CGFloat(3)
|
||||
var yOffset = CGFloat(2)
|
||||
for button in windowControlButtons {
|
||||
let shouldHide =
|
||||
(button.type == .quit && !window.application.canBeQuit()) ||
|
||||
(button.type == .close && !window.canBeClosed()) ||
|
||||
((button.type == .miniaturize || button.type == .fullscreen) && !window.canBeMinDeminOrFullscreened())
|
||||
if button.isHidden != shouldHide {
|
||||
button.isHidden = shouldHide
|
||||
button.needsDisplay = true
|
||||
}
|
||||
assignIfDifferent(&button.frame.origin, NSPoint(x: thumbnailOrigin.x + xOffset, y: thumbnailOrigin.y + yOffset))
|
||||
xOffset += TrafficLightButton.size + TrafficLightButton.spacing
|
||||
if xOffset + TrafficLightButton.size > thumbnailWidth {
|
||||
xOffset = 3
|
||||
yOffset += TrafficLightButton.size + TrafficLightButton.spacing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hideWindowControls() {
|
||||
guard isShowingWindowControls else { return }
|
||||
isShowingWindowControls = false
|
||||
for button in windowControlButtons {
|
||||
button.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,6 @@ class ThumbnailView: FlippedView {
|
||||
var dockLabelIcon = ThumbnailFilledFontIconView(
|
||||
ThumbnailFontIconView(symbol: .filledCircledNumber0, size: dockLabelLabelSize(), color: NSColor(srgbRed: 1, green: 0.30, blue: 0.25, alpha: 1)),
|
||||
backgroundColor: NSColor.white, size: dockLabelLabelSize())
|
||||
var quitIcon = TrafficLightButton(.quit, NSLocalizedString("Quit app", comment: ""))
|
||||
var closeIcon = TrafficLightButton(.close, NSLocalizedString("Close window", comment: ""))
|
||||
var minimizeIcon = TrafficLightButton(.miniaturize, NSLocalizedString("Minimize/Deminimize window", comment: ""))
|
||||
var maximizeIcon = TrafficLightButton(.fullscreen, NSLocalizedString("Fullscreen/Defullscreen window", comment: ""))
|
||||
var windowlessAppIndicator = WindowlessAppIndicator(tooltip: ThumbnailView.noOpenWindowToolTip)
|
||||
|
||||
let hStackView = FlippedView()
|
||||
@@ -28,7 +24,6 @@ class ThumbnailView: FlippedView {
|
||||
var mouseMovedCallback: (() -> Void)!
|
||||
var dragAndDropTimer: Timer?
|
||||
var indexInRecycledViews: Int!
|
||||
var isShowingWindowControls = false
|
||||
|
||||
var isFirstInRow = false
|
||||
var isLastInRow = false
|
||||
@@ -36,7 +31,6 @@ class ThumbnailView: FlippedView {
|
||||
var numberOfViewsInRow = 0
|
||||
private var lastLabelWidth: CGFloat = -1
|
||||
|
||||
var windowControlIcons: [TrafficLightButton] { [quitIcon, closeIcon, minimizeIcon, maximizeIcon] }
|
||||
var windowIndicatorIcons: [ThumbnailFontIconView] { [hiddenIcon, fullscreenIcon, minimizedIcon, spaceIcon] }
|
||||
|
||||
var receivedMouseDown = false
|
||||
@@ -113,7 +107,6 @@ class ThumbnailView: FlippedView {
|
||||
}
|
||||
|
||||
func mouseMoved() {
|
||||
showOrHideWindowControls(true)
|
||||
updateLabelTooltipIfNeeded()
|
||||
mouseMovedCallback()
|
||||
}
|
||||
@@ -138,34 +131,14 @@ class ThumbnailView: FlippedView {
|
||||
}
|
||||
|
||||
func drawHighlight() {
|
||||
let isFocused = indexInRecycledViews == Windows.selectedWindowIndex
|
||||
let isHovered = indexInRecycledViews == Windows.hoveredWindowIndex
|
||||
setBackground(isFocused: isFocused, isHovered: isHovered)
|
||||
setBorder(isFocused: isFocused, isHovered: isHovered)
|
||||
if Preferences.appearanceStyle == .appIcons {
|
||||
let isFocused = indexInRecycledViews == Windows.selectedWindowIndex
|
||||
let isHovered = indexInRecycledViews == Windows.hoveredWindowIndex
|
||||
label.isHidden = !(isFocused || isHovered)
|
||||
updateAppIconsLabel(isFocused: isFocused, isHovered: isHovered)
|
||||
}
|
||||
}
|
||||
|
||||
func showOrHideWindowControls(_ shouldShowWindowControls: Bool) {
|
||||
guard Preferences.appearanceStyle == .thumbnails else { return }
|
||||
let shouldShow = shouldShowWindowControls && !Preferences.hideColoredCircles && !Appearance.hideThumbnails
|
||||
guard isShowingWindowControls != shouldShow else { return }
|
||||
isShowingWindowControls = shouldShow
|
||||
for icon in windowControlIcons {
|
||||
let shouldHide = !shouldShow
|
||||
|| (icon.type == .quit && !(window_?.application.canBeQuit() ?? true))
|
||||
|| (icon.type == .close && !(window_?.canBeClosed() ?? true))
|
||||
|| ((icon.type == .miniaturize || icon.type == .fullscreen) && !(window_?.canBeMinDeminOrFullscreened() ?? true))
|
||||
|
||||
if icon.isHidden != shouldHide {
|
||||
icon.isHidden = shouldHide
|
||||
icon.needsDisplay = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func updateDockLabelIcon(_ dockLabel: String?) {
|
||||
assignIfDifferent(&dockLabelIcon.isHidden, dockLabel == nil || Preferences.hideAppBadges || Appearance.iconSize == 0)
|
||||
@@ -198,10 +171,6 @@ class ThumbnailView: FlippedView {
|
||||
appIcon.setSubviewAbove(dockLabelIcon)
|
||||
label.fixHeight()
|
||||
vStackView.wantsLayer = true
|
||||
vStackView.layer!.backgroundColor = .clear
|
||||
vStackView.layer!.borderColor = .clear
|
||||
vStackView.layer!.cornerRadius = Appearance.cellCornerRadius
|
||||
vStackView.layer!.borderWidth = CGFloat(1)
|
||||
setSubviews([vStackView])
|
||||
vStackView.setSubviews([hStackView])
|
||||
hStackView.setSubviews([appIcon])
|
||||
@@ -216,10 +185,6 @@ class ThumbnailView: FlippedView {
|
||||
} else if Preferences.appearanceStyle == .thumbnails {
|
||||
vStackView.addSubviews([thumbnail])
|
||||
thumbnail.setSubviewAbove(windowlessAppIndicator)
|
||||
for icon in windowControlIcons {
|
||||
thumbnail.setSubviewAbove(icon)
|
||||
icon.isHidden = true
|
||||
}
|
||||
hStackView.addSubviews([label] + windowIndicatorIcons)
|
||||
} else {
|
||||
hStackView.setSubviewAbove(windowlessAppIndicator)
|
||||
@@ -227,33 +192,6 @@ class ThumbnailView: FlippedView {
|
||||
}
|
||||
}
|
||||
|
||||
private func getBackgroundColor(isFocused: Bool, isHovered: Bool) -> NSColor {
|
||||
if isFocused {
|
||||
return Appearance.highlightFocusedBackgroundColor
|
||||
}
|
||||
if isHovered {
|
||||
return Appearance.highlightHoveredBackgroundColor
|
||||
}
|
||||
return NSColor.clear
|
||||
}
|
||||
|
||||
private func setBackground(isFocused: Bool, isHovered: Bool) {
|
||||
vStackView.layer!.backgroundColor = getBackgroundColor(isFocused: isFocused, isHovered: isHovered).cgColor
|
||||
}
|
||||
|
||||
private func setBorder(isFocused: Bool, isHovered: Bool) {
|
||||
if isFocused {
|
||||
vStackView.layer!.borderColor = Appearance.highlightFocusedBorderColor.cgColor
|
||||
vStackView.layer!.borderWidth = Appearance.highlightBorderWidth
|
||||
} else if isHovered {
|
||||
vStackView.layer!.borderColor = Appearance.highlightHoveredBorderColor.cgColor
|
||||
vStackView.layer!.borderWidth = Appearance.highlightBorderWidth
|
||||
} else {
|
||||
vStackView.layer!.borderColor = NSColor.clear.cgColor
|
||||
vStackView.layer!.borderWidth = 0
|
||||
}
|
||||
}
|
||||
|
||||
private func updateAppIconsLabel(isFocused: Bool, isHovered: Bool) {
|
||||
let focusedView = ThumbnailsView.recycledViews[Windows.selectedWindowIndex]
|
||||
var hoveredView: ThumbnailView? = nil
|
||||
@@ -371,8 +309,6 @@ class ThumbnailView: FlippedView {
|
||||
updateAppIcon(element, title)
|
||||
updateDockLabelIcon(element.dockLabel)
|
||||
setAccessibilityHelp(getAccessibilityHelp(element.application.localizedName, element.dockLabel))
|
||||
windowControlIcons.forEach { $0.window_ = element }
|
||||
showOrHideWindowControls(isShowingWindowControls)
|
||||
mouseUpCallback = { () -> Void in App.app.focusSelectedWindow(element) }
|
||||
mouseMovedCallback = { () -> Void in Windows.updateSelectedAndHoveredWindowIndex(index, true) }
|
||||
}
|
||||
@@ -416,16 +352,6 @@ class ThumbnailView: FlippedView {
|
||||
if Preferences.appearanceStyle == .thumbnails {
|
||||
assignIfDifferent(&thumbnail.frame.origin, NSPoint(x: Appearance.edgeInsetsSize, y: hStackView.frame.maxY + Appearance.intraCellPadding))
|
||||
thumbnail.centerFrameInParent(x: true)
|
||||
var xOffset = CGFloat(3)
|
||||
var yOffset = thumbnail.frame.height - CGFloat(2)
|
||||
for icon in windowControlIcons {
|
||||
assignIfDifferent(&icon.frame.origin, NSPoint(x: xOffset, y: yOffset - TrafficLightButton.size))
|
||||
xOffset += TrafficLightButton.size + TrafficLightButton.spacing
|
||||
if xOffset + TrafficLightButton.size > thumbnail.frame.width {
|
||||
xOffset = 3
|
||||
yOffset -= TrafficLightButton.size + TrafficLightButton.spacing
|
||||
}
|
||||
}
|
||||
}
|
||||
if !windowlessAppIndicator.isHidden {
|
||||
if Preferences.appearanceStyle != .titles {
|
||||
|
||||
@@ -9,6 +9,7 @@ class ThumbnailsView {
|
||||
static var thumbnailsWidth = CGFloat(0.0)
|
||||
static var thumbnailsHeight = CGFloat(0.0)
|
||||
static var layoutCache = LayoutCache()
|
||||
var highlightOverlay = HighlightOverlayView()
|
||||
|
||||
init() {
|
||||
updateBackgroundView()
|
||||
@@ -51,15 +52,22 @@ class ThumbnailsView {
|
||||
for i in 0..<ThumbnailsView.recycledViews.count {
|
||||
ThumbnailsView.recycledViews[i] = ThumbnailView()
|
||||
}
|
||||
highlightOverlay = HighlightOverlayView()
|
||||
Self.updateCachedSizes()
|
||||
}
|
||||
|
||||
static func highlight(_ indexInRecycledViews: Int) {
|
||||
let view = recycledViews[indexInRecycledViews]
|
||||
view.indexInRecycledViews = indexInRecycledViews
|
||||
if view.frame != NSRect.zero {
|
||||
view.drawHighlight()
|
||||
}
|
||||
guard view.frame != .zero else { return }
|
||||
view.drawHighlight()
|
||||
let overlay = App.app.thumbnailsPanel.thumbnailsView.highlightOverlay
|
||||
let focusedView = recycledViews[Windows.selectedWindowIndex]
|
||||
let hoveredView = Windows.hoveredWindowIndex.map { recycledViews[$0] }
|
||||
overlay.updateHighlight(
|
||||
focusedView: focusedView.frame != .zero ? focusedView : nil,
|
||||
hoveredView: hoveredView != focusedView && hoveredView?.frame != .zero ? hoveredView : nil
|
||||
)
|
||||
}
|
||||
|
||||
func nextRow(_ direction: Direction, allowWrap: Bool = true) -> [ThumbnailView]? {
|
||||
@@ -175,6 +183,7 @@ class ThumbnailsView {
|
||||
}
|
||||
}
|
||||
scrollView.documentView!.subviews = newViews
|
||||
scrollView.documentView!.addSubview(highlightOverlay)
|
||||
return (maxX, maxY, labelHeight, rowSignature)
|
||||
}
|
||||
|
||||
@@ -218,6 +227,7 @@ class ThumbnailsView {
|
||||
scrollView.documentView!.subviews.forEach { $0.frame.origin.x -= croppedWidth }
|
||||
}
|
||||
scrollView.documentView!.frame.size = NSSize(width: maxX, height: maxY)
|
||||
highlightOverlay.frame = CGRect(origin: .zero, size: scrollView.documentView!.frame.size)
|
||||
if let existingTrackingArea = scrollView.trackingAreas.first {
|
||||
scrollView.removeTrackingArea(existingTrackingArea)
|
||||
}
|
||||
@@ -249,6 +259,9 @@ class ThumbnailsView {
|
||||
ThumbnailsView.highlight(Windows.selectedWindowIndex)
|
||||
if let hoveredWindowIndex = Windows.hoveredWindowIndex {
|
||||
ThumbnailsView.highlight(hoveredWindowIndex)
|
||||
if highlightOverlay.isShowingWindowControls {
|
||||
highlightOverlay.showWindowControls(for: ThumbnailsView.recycledViews[hoveredWindowIndex])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,8 +329,8 @@ class ScrollView: NSScrollView {
|
||||
if let oldIndex = Windows.hoveredWindowIndex {
|
||||
Windows.hoveredWindowIndex = nil
|
||||
ThumbnailsView.highlight(oldIndex)
|
||||
ThumbnailsView.recycledViews[oldIndex].showOrHideWindowControls(false)
|
||||
}
|
||||
App.app.thumbnailsPanel.thumbnailsView.highlightOverlay.hideWindowControls()
|
||||
}
|
||||
|
||||
override func mouseExited(with event: NSEvent) {
|
||||
@@ -332,10 +345,12 @@ class ScrollView: NSScrollView {
|
||||
let location = documentView.convert(App.app.thumbnailsPanel.mouseLocationOutsideOfEventStream, from: nil)
|
||||
let newTarget = findTarget(location)
|
||||
guard newTarget !== previousTarget else { return }
|
||||
let overlay = App.app.thumbnailsPanel.thumbnailsView.highlightOverlay
|
||||
caTransaction {
|
||||
if let newTarget {
|
||||
previousTarget?.showOrHideWindowControls(false)
|
||||
overlay.hideWindowControls()
|
||||
newTarget.mouseMoved()
|
||||
overlay.showWindowControls(for: newTarget)
|
||||
} else {
|
||||
resetHoveredWindow()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user