Skip to content

Commit cf66bfe

Browse files
tieubaolaveezhuynguyenhrm335
committed
fix: display hot-plug length re-apply, constraint and observer leaks
Absorbs the still-relevant pieces of three community PRs that overlapped this branch, with authorship credit: - collapse length re-applies to the live separator when displays change, and isCollapsed compares > btnHiddenLength so the state survives the recompute; collapse sizing uses frame.width x2 capped at the documented 10,000pt NSStatusItem maximum (from #354) - NSLayoutConstraint.deactivate before removeFromSuperview in removeAllSubViews, plugging the tutorial-view rebuild leak (from #335) - PreferencesViewController balances its prefsChanged observer in deinit (from #335/#346) Co-authored-by: Laveez <niko.muukkonen1@gmail.com> Co-authored-by: huynguyenh <hoanghuy2908@gmail.com> Co-authored-by: Rob Mulder <hallo@robmulder.com>
1 parent ea6fcd6 commit cf66bfe

3 files changed

Lines changed: 27 additions & 8 deletions

File tree

hidden/Extensions/StackView+Extension.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import Cocoa
1111
extension NSStackView {
1212
func removeAllSubViews() {
1313
for view in self.views {
14+
// Deactivate constraints before removal or they leak on every
15+
// tutorial-view rebuild (PR #335).
16+
NSLayoutConstraint.deactivate(view.constraints)
1417
view.removeFromSuperview()
1518
}
1619
}

hidden/Features/Preferences/PreferencesViewController.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,12 @@ class PreferencesViewController: NSViewController {
5555
createTutorialView()
5656
NotificationCenter.default.addObserver(self, selector: #selector(updateData), name: .prefsChanged, object: nil)
5757
}
58-
58+
59+
deinit {
60+
// Balance the viewDidLoad observer (PRs #335/#346).
61+
NotificationCenter.default.removeObserver(self, name: .prefsChanged, object: nil)
62+
}
63+
5964
static func initWithStoryboard() -> PreferencesViewController {
6065
let vc = NSStoryboard(name:"Main", bundle: nil).instantiateController(withIdentifier: "prefVC") as! PreferencesViewController
6166
return vc

hidden/Features/StatusBar/StatusBarController.swift

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ class StatusBarController {
2828
private let imgIconLine = NSImage(named:NSImage.Name("ic_line"))
2929

3030
private var isCollapsed: Bool {
31-
return self.btnSeparate.length == self.btnHiddenCollapseLength
31+
// Compare with > rather than == so the state survives updateCollapsedLengths
32+
// changing btnHiddenCollapseLength while the bar is collapsed (PR #354).
33+
return self.btnSeparate.length > self.btnHiddenLength
3234
}
3335

3436
private var isBtnSeparateValidPosition: Bool {
@@ -125,18 +127,27 @@ class StatusBarController {
125127
}
126128

127129
@objc private func handleScreenParametersChanged() {
130+
// Re-apply the recomputed length to the LIVE item when collapsed, or a
131+
// display hot-plug leaves the separator at a stale length (PR #354).
132+
let wasCollapsed = isCollapsed
128133
updateCollapsedLengths()
134+
if wasCollapsed {
135+
btnSeparate.length = btnHiddenCollapseLength
136+
if Preferences.areSeparatorsHidden {
137+
btnAlwaysHidden?.length = btnAlwaysHiddenEnableExpandCollapseLength
138+
}
139+
}
129140
}
130-
141+
131142
private func updateCollapsedLengths() {
132143
// The menubar replicates across every attached display, so the collapse
133144
// length must cover the WIDEST screen, not NSScreen.main (the focused one);
134145
// sizing from a narrower screen leaks hidden icons on wider displays.
135-
let screenWidth = NSScreen.screens.map { $0.visibleFrame.width }.max() ?? 1728
136-
// Keep collapse length bounded to avoid pathological layout/memory behavior
137-
// on newer macOS versions while still fully hiding the trailing section.
138-
// 6000 covers 5K2K ultrawides (5120pt); was 4000.
139-
let boundedCollapseLength = max(500, min(screenWidth + 200, 6000))
146+
// frame.width, not visibleFrame: the menubar spans the full frame width.
147+
let screenWidth = NSScreen.screens.map { $0.frame.width }.max() ?? 1728
148+
// Keep collapse length bounded to avoid pathological layout/memory behavior;
149+
// macOS enforces a hard 10,000pt maximum on NSStatusItem.length (PR #354).
150+
let boundedCollapseLength = max(500, min(screenWidth * 2, 10_000))
140151
btnHiddenCollapseLength = boundedCollapseLength
141152
btnAlwaysHiddenEnableExpandCollapseLength = Preferences.alwaysHiddenSectionEnabled ? boundedCollapseLength : 0
142153
}

0 commit comments

Comments
 (0)