Skip to content
16 changes: 12 additions & 4 deletions Rectangle.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@
9824704F22B189250037B409 /* BestEffortWindowMover.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9824704A22B189250037B409 /* BestEffortWindowMover.swift */; };
9824705122B28D7A0037B409 /* LeftRightHalfCalculation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9824705022B28D7A0037B409 /* LeftRightHalfCalculation.swift */; };
983BBD6F253B609D000D223E /* FootprintWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 983BBD6E253B609D000D223E /* FootprintWindow.swift */; };
F1AC0DE000000000000000A2 /* StackBadgeGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1AC0DE000000000000000A1 /* StackBadgeGeometry.swift */; };
F1AC0DE000000000000000A4 /* StackBadgeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1AC0DE000000000000000A3 /* StackBadgeManager.swift */; };
F1AC0DE000000000000000A8 /* StackBadgeListPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1AC0DE000000000000000A9 /* StackBadgeListPanel.swift */; };
F1AC0DE000000000000000AA /* StackBadgeRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1AC0DE000000000000000AB /* StackBadgeRowView.swift */; };
983DD04028A844BE00BF1EEE /* SnapAreaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 983DD03F28A844BE00BF1EEE /* SnapAreaViewController.swift */; };
983DD04428B0639E00BF1EEE /* SnapAreaModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 983DD04328B0639E00BF1EEE /* SnapAreaModel.swift */; };
984EDB0F29A42ED200D119D2 /* LaunchOnLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 984EDB0E29A42ED200D119D2 /* LaunchOnLogin.swift */; };
Expand Down Expand Up @@ -191,8 +195,6 @@
D8644560FF112B0748CE1975 /* UpperMiddleLeftSixteenthCalculation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E2DBE0733F31BC159BC99C /* UpperMiddleLeftSixteenthCalculation.swift */; };
DCD3CF2993E9AFAF30820117 /* MiddleCenterRightTwelfthCalculation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCF2AC59501448BD3BAA16EC /* MiddleCenterRightTwelfthCalculation.swift */; };
E791B00A88D90C24A4C3D2D1 /* UpperMiddleCenterLeftSixteenthCalculation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B8CA6901E6FE134E930135B /* UpperMiddleCenterLeftSixteenthCalculation.swift */; };
F1AC0DE000000000000000A2 /* StackBadgeGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1AC0DE000000000000000A1 /* StackBadgeGeometry.swift */; };
F1AC0DE000000000000000A4 /* StackBadgeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1AC0DE000000000000000A3 /* StackBadgeManager.swift */; };
F1AC0DE000000000000000C2 /* OverlapOffsetGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1AC0DE000000000000000C1 /* OverlapOffsetGeometry.swift */; };
F4EED30B47FB6C55EA937254 /* TopRightTwelfthCalculation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E8357E928530D10A806F3CD /* TopRightTwelfthCalculation.swift */; };
F51A7467767F8EAF97321A00 /* TopRightSixteenthCalculation.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD222258713B13274FB651B0 /* TopRightSixteenthCalculation.swift */; };
Expand Down Expand Up @@ -321,6 +323,10 @@
9824704A22B189250037B409 /* BestEffortWindowMover.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BestEffortWindowMover.swift; sourceTree = "<group>"; };
9824705022B28D7A0037B409 /* LeftRightHalfCalculation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightHalfCalculation.swift; sourceTree = "<group>"; };
983BBD6E253B609D000D223E /* FootprintWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FootprintWindow.swift; sourceTree = "<group>"; };
F1AC0DE000000000000000A1 /* StackBadgeGeometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackBadgeGeometry.swift; sourceTree = "<group>"; };
F1AC0DE000000000000000A3 /* StackBadgeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackBadgeManager.swift; sourceTree = "<group>"; };
F1AC0DE000000000000000A9 /* StackBadgeListPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackBadgeListPanel.swift; sourceTree = "<group>"; };
F1AC0DE000000000000000AB /* StackBadgeRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackBadgeRowView.swift; sourceTree = "<group>"; };
983DD03F28A844BE00BF1EEE /* SnapAreaViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapAreaViewController.swift; sourceTree = "<group>"; };
983DD04328B0639E00BF1EEE /* SnapAreaModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapAreaModel.swift; sourceTree = "<group>"; };
984EDB0E29A42ED200D119D2 /* LaunchOnLogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchOnLogin.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -417,8 +423,6 @@
D7D038C68560DC11F14496F6 /* BottomRightTwelfthCalculation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomRightTwelfthCalculation.swift; sourceTree = "<group>"; };
D9FDCA1333C1BF6930A8D7F3 /* TopLeftTwelfthCalculation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopLeftTwelfthCalculation.swift; sourceTree = "<group>"; };
EEABF10E66D648DDB37DABBA /* MiddleLeftTwelfthCalculation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiddleLeftTwelfthCalculation.swift; sourceTree = "<group>"; };
F1AC0DE000000000000000A1 /* StackBadgeGeometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackBadgeGeometry.swift; sourceTree = "<group>"; };
F1AC0DE000000000000000A3 /* StackBadgeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackBadgeManager.swift; sourceTree = "<group>"; };
F1AC0DE000000000000000C1 /* OverlapOffsetGeometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlapOffsetGeometry.swift; sourceTree = "<group>"; };
F3592F8E85CE82B8FA662A31 /* TwelfthsRepeated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwelfthsRepeated.swift; sourceTree = "<group>"; };
FA34D0FE2F7E896E00EEBEF1 /* SpecificDisplayCalculation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpecificDisplayCalculation.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -802,6 +806,8 @@
children = (
F1AC0DE000000000000000A1 /* StackBadgeGeometry.swift */,
F1AC0DE000000000000000A3 /* StackBadgeManager.swift */,
F1AC0DE000000000000000A9 /* StackBadgeListPanel.swift */,
F1AC0DE000000000000000AB /* StackBadgeRowView.swift */,
);
path = StackBadge;
sourceTree = "<group>";
Expand Down Expand Up @@ -1104,6 +1110,8 @@
F1AC0DE000000000000000C2 /* OverlapOffsetGeometry.swift in Sources */,
F1AC0DE000000000000000A2 /* StackBadgeGeometry.swift in Sources */,
F1AC0DE000000000000000A4 /* StackBadgeManager.swift in Sources */,
F1AC0DE000000000000000A8 /* StackBadgeListPanel.swift in Sources */,
F1AC0DE000000000000000AA /* StackBadgeRowView.swift in Sources */,
988D067F22EB4EDE004EABD7 /* MoveLeftRightCalculation.swift in Sources */,
AA3A9E8B29230A82004EB8E5 /* CFExtension.swift in Sources */,
98C6DEF023CE191700CC0C1E /* GapCalculation.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion Rectangle/AccessibilityElement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ class AccessibilityElement {
return getElementValue(.window)
}

private var isMainWindow: Bool? {
var isMainWindow: Bool? {
get {
windowElement?.wrappedElement.getValue(.main) as? Bool
}
Expand Down
4 changes: 2 additions & 2 deletions Rectangle/PrefsWindow/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extension Defaults {
shortcuts[action.name] = Shortcut(masShortcut: masShortcut)
}
}
for defaultsKey in TodoManager.defaultsKeys {
for defaultsKey in TodoManager.defaultsKeys + StackBadgeManager.defaultsKeys {
guard
let shortcutDict = UserDefaults.standard.dictionary(forKey: defaultsKey),
let dictTransformer = ValueTransformer(forName: NSValueTransformerName(rawValue: MASDictionaryTransformerName)),
Expand Down Expand Up @@ -79,7 +79,7 @@ extension Defaults {
UserDefaults.standard.removeObject(forKey: action.name)
}
}
for defaultsKey in TodoManager.defaultsKeys {
for defaultsKey in TodoManager.defaultsKeys + StackBadgeManager.defaultsKeys {
if let importedShortcut = config.shortcuts[defaultsKey], importedShortcut.keyCode >= 0 {
let shortcut = importedShortcut.toMASSHortcut()
let dictValue = dictTransformer.reverseTransformedValue(shortcut)
Expand Down
38 changes: 36 additions & 2 deletions Rectangle/PrefsWindow/SettingsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class SettingsViewController: NSViewController {
private var cycleSizeCheckboxes = [NSButton]()
private var cornerCycleExpansionAxisButtons = [NSButton]()
private var cooperativeCornerResizeCheckbox: NSButton?
private var stackBadgeCheckbox: NSButton?
private var combinedDisplayModeCheckbox: NSButton?
private var greenButtonOverrideCheckbox: NSButton?
private var autoMaximizeCheckbox: NSButton?
Expand Down Expand Up @@ -910,11 +911,30 @@ class SettingsViewController: NSViewController {
overlapOffsetCheckbox.translatesAutoresizingMaskIntoConstraints = false
overlapOffsetCheckbox.alignment = .left

let stackBadgeCheckbox = NSButton(checkboxWithTitle: NSLocalizedString("Show stacked window badge on hover", tableName: "Main", value: "", comment: ""), target: self, action: #selector(toggleStackBadge(_:)))
let stackBadgeCheckbox = NSButton(checkboxWithTitle: NSLocalizedString("Show stacked window list on hover", tableName: "Main", value: "", comment: ""), target: self, action: #selector(toggleStackBadge(_:)))
self.stackBadgeCheckbox = stackBadgeCheckbox
stackBadgeCheckbox.state = Defaults.stackBadge.userEnabled ? .on : .off
stackBadgeCheckbox.translatesAutoresizingMaskIntoConstraints = false
stackBadgeCheckbox.alignment = .left

let stackBadgeToggleLabel = NSTextField(labelWithString: NSLocalizedString("Toggle stacked window list", tableName: "Main", value: "", comment: ""))
stackBadgeToggleLabel.alignment = .right
stackBadgeToggleLabel.translatesAutoresizingMaskIntoConstraints = false
// The label yields rather than pushing the recorder out of the
// column it shares with the rows above.
stackBadgeToggleLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
let stackBadgeToggleShortcutView = MASShortcutView(frame: NSRect(x: 0, y: 0, width: 160, height: 19))
stackBadgeToggleShortcutView.setAssociatedUserDefaultsKey(StackBadgeManager.toggleDefaultsKey, withTransformerName: MASDictionaryTransformerName)
stackBadgeToggleShortcutView.translatesAutoresizingMaskIntoConstraints = false
stackBadgeToggleShortcutView.shortcutValidator = AppShortcutValidator(defaultsKey: StackBadgeManager.toggleDefaultsKey)
shortcutRecordingObserver.observe([stackBadgeToggleShortcutView])
let stackBadgeToggleRow = NSStackView()
stackBadgeToggleRow.orientation = .horizontal
stackBadgeToggleRow.alignment = .centerY
stackBadgeToggleRow.spacing = 18
stackBadgeToggleRow.addArrangedSubview(stackBadgeToggleLabel)
stackBadgeToggleRow.addArrangedSubview(stackBadgeToggleShortcutView)

mainStackView.addArrangedSubview(gridHeaderLabel)
mainStackView.setCustomSpacing(4, after: gridHeaderLabel)
mainStackView.addArrangedSubview(cyclingHintLabel)
Expand All @@ -933,7 +953,9 @@ class SettingsViewController: NSViewController {
mainStackView.addArrangedSubview(showAdditionalSizesCheckbox)
mainStackView.addArrangedSubview(overlapOffsetCheckbox)
mainStackView.addArrangedSubview(stackBadgeCheckbox)
mainStackView.setCustomSpacing(8, after: stackBadgeCheckbox)
mainStackView.setCustomSpacing(6, after: stackBadgeCheckbox)
mainStackView.addArrangedSubview(stackBadgeToggleRow)
mainStackView.setCustomSpacing(8, after: stackBadgeToggleRow)


mainStackView.addArrangedSubview(splitRatioHeaderLabel)
Expand Down Expand Up @@ -963,6 +985,8 @@ class SettingsViewController: NSViewController {
ninthsCyclingLabel.widthAnchor.constraint(equalTo: twelfthsCyclingLabel.widthAnchor),
twelfthsCyclingLabel.widthAnchor.constraint(equalTo: sixteenthsCyclingLabel.widthAnchor),
sixteenthsCyclingLabel.widthAnchor.constraint(equalTo: hSplitLabel.widthAnchor),
stackBadgeToggleShortcutView.leadingAnchor.constraint(equalTo: sixteenthsCyclingShortcutView.leadingAnchor),
stackBadgeToggleShortcutView.widthAnchor.constraint(equalToConstant: 160),
hSplitLabel.widthAnchor.constraint(equalTo: vSplitLabel.widthAnchor),
largerWidthLabelStack.widthAnchor.constraint(equalTo: smallerWidthLabelStack.widthAnchor),
largerWidthShortcutView.widthAnchor.constraint(equalToConstant: 160),
Expand Down Expand Up @@ -994,6 +1018,8 @@ class SettingsViewController: NSViewController {
showAdditionalSizesCheckbox.leadingAnchor.constraint(equalTo: largerWidthShortcutView.leadingAnchor),
overlapOffsetCheckbox.leadingAnchor.constraint(equalTo: largerWidthShortcutView.leadingAnchor),
stackBadgeCheckbox.leadingAnchor.constraint(equalTo: largerWidthShortcutView.leadingAnchor),
stackBadgeToggleRow.leadingAnchor.constraint(equalTo: largerWidthShortcutView.leadingAnchor),
stackBadgeToggleShortcutView.widthAnchor.constraint(equalToConstant: 160),
smallerWidthShortcutView.leadingAnchor.constraint(equalTo: largerWidthShortcutView.leadingAnchor),
topVerticalThirdShortcutView.leadingAnchor.constraint(equalTo: largerWidthShortcutView.leadingAnchor),
middleVerticalThirdShortcutView.leadingAnchor.constraint(equalTo: largerWidthShortcutView.leadingAnchor),
Expand Down Expand Up @@ -1036,6 +1062,10 @@ class SettingsViewController: NSViewController {

override func awakeFromNib() {
initializeToggles()
NotificationCenter.default.addObserver(self,
selector: #selector(stackBadgeChanged),
name: .stackBadgeChanged,
object: nil)

checkForUpdatesAutomaticallyCheckbox.bind(.value, to: AppDelegate.instance.updaterController.updater, withKeyPath: "automaticallyChecksForUpdates", options: nil)

Expand Down Expand Up @@ -1428,6 +1458,10 @@ class SettingsViewController: NSViewController {
cooperativeCornerResizeCheckbox?.state = Defaults.cooperativeCornerResize.enabled ? .on : .off
}

@objc private func stackBadgeChanged() {
stackBadgeCheckbox?.state = Defaults.stackBadge.userEnabled ? .on : .off
}

}

extension SettingsViewController {
Expand Down
2 changes: 2 additions & 0 deletions Rectangle/ShortcutManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class ShortcutManager {
},
todoSessionStateChanged: @escaping (Bool) -> Void = { isActive in
TodoManager.setShortcutBindingsSessionActive(isActive)
StackBadgeManager.setShortcutBindingsSessionActive(isActive)
}
) {
self.windowManager = windowManager
Expand Down Expand Up @@ -298,6 +299,7 @@ class ShortcutManager {
}

TodoManager.setShortcutBindingsSuspended(isRecording)
StackBadgeManager.setShortcutBindingsSuspended(isRecording)
}

private func isRepeatAction(parameters: ExecutionParameters, windowElement: AccessibilityElement, windowId: CGWindowID) -> Bool {
Expand Down
Loading
Loading