Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion Sources/OmniWM/Core/Config/MonitorGapSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,22 @@ struct MonitorGapSettings: MonitorSettingsType {
var monitorName: String
var monitorDisplayId: CGDirectDisplayID?

var innerGap: Double?
var outerGapLeft: Double?
var outerGapRight: Double?
var outerGapTop: Double?
var outerGapBottom: Double?

var hasOverrides: Bool {
innerGap != nil || outerGapLeft != nil || outerGapRight != nil ||
outerGapTop != nil || outerGapBottom != nil
}

init(
id: UUID = UUID(),
monitorName: String,
monitorDisplayId: CGDirectDisplayID? = nil,
innerGap: Double? = nil,
outerGapLeft: Double? = nil,
outerGapRight: Double? = nil,
outerGapTop: Double? = nil,
Expand All @@ -26,6 +33,7 @@ struct MonitorGapSettings: MonitorSettingsType {
self.id = id
self.monitorName = monitorName
self.monitorDisplayId = monitorDisplayId
self.innerGap = innerGap
self.outerGapLeft = outerGapLeft
self.outerGapRight = outerGapRight
self.outerGapTop = outerGapTop
Expand All @@ -34,14 +42,15 @@ struct MonitorGapSettings: MonitorSettingsType {

private enum CodingKeys: String, CodingKey {
case id, monitorName, monitorDisplayId
case outerGapLeft, outerGapRight, outerGapTop, outerGapBottom
case innerGap, outerGapLeft, outerGapRight, outerGapTop, outerGapBottom
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
monitorName = try container.decode(String.self, forKey: .monitorName)
monitorDisplayId = try container.decodeIfPresent(CGDirectDisplayID.self, forKey: .monitorDisplayId)
innerGap = try container.decodeIfPresent(Double.self, forKey: .innerGap)
outerGapLeft = try container.decodeIfPresent(Double.self, forKey: .outerGapLeft)
outerGapRight = try container.decodeIfPresent(Double.self, forKey: .outerGapRight)
outerGapTop = try container.decodeIfPresent(Double.self, forKey: .outerGapTop)
Expand All @@ -53,6 +62,7 @@ struct MonitorGapSettings: MonitorSettingsType {
try container.encode(id, forKey: .id)
try container.encode(monitorName, forKey: .monitorName)
try container.encodeIfPresent(monitorDisplayId, forKey: .monitorDisplayId)
try container.encodeIfPresent(innerGap, forKey: .innerGap)
try container.encodeIfPresent(outerGapLeft, forKey: .outerGapLeft)
try container.encodeIfPresent(outerGapRight, forKey: .outerGapRight)
try container.encodeIfPresent(outerGapTop, forKey: .outerGapTop)
Expand All @@ -61,6 +71,7 @@ struct MonitorGapSettings: MonitorSettingsType {
}

struct ResolvedGapSettings: Equatable {
let innerGap: CGFloat
let outerGapLeft: CGFloat
let outerGapRight: CGFloat
let outerGapTop: CGFloat
Expand Down
10 changes: 10 additions & 0 deletions Sources/OmniWM/Core/Config/MonitorSettingsType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,14 @@ enum MonitorSettingsStore {
static func remove<T: MonitorSettingsType>(for monitorName: String, from settings: inout [T]) {
settings.removeAll { $0.monitorName == monitorName }
}

static func remove<T: MonitorSettingsType>(matching item: T, from settings: inout [T]) {
settings.removeAll { existing in
if let displayId = item.monitorDisplayId {
return existing.monitorDisplayId == displayId ||
(existing.monitorDisplayId == nil && existing.monitorName == item.monitorName)
}
return existing.monitorDisplayId == nil && existing.monitorName == item.monitorName
}
}
}
30 changes: 24 additions & 6 deletions Sources/OmniWM/Core/Config/SettingsStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ final class SettingsStore {
monitors: monitors
)
monitorGapSettings = SettingsStore.reboundMonitorSettings(
export.monitorGapSettings,
export.monitorGapSettings.filter(\.hasOverrides),
monitors: monitors
)

Expand Down Expand Up @@ -1218,22 +1218,31 @@ final class SettingsStore {
}

func resolvedDwindleSettings(for monitor: Monitor) -> ResolvedDwindleSettings {
resolvedDwindleSettings(override: dwindleSettings(for: monitor))
resolvedDwindleSettings(
override: dwindleSettings(for: monitor),
sharedInnerGap: resolvedGapSettings(for: monitor).innerGap
)
}

func resolvedDwindleSettings(for monitorName: String) -> ResolvedDwindleSettings {
resolvedDwindleSettings(override: dwindleSettings(for: monitorName))
resolvedDwindleSettings(
override: dwindleSettings(for: monitorName),
sharedInnerGap: resolvedInnerGap(gapSettings(for: monitorName)?.innerGap)
)
}

private func resolvedDwindleSettings(override: MonitorDwindleSettings?) -> ResolvedDwindleSettings {
private func resolvedDwindleSettings(
override: MonitorDwindleSettings?,
sharedInnerGap: CGFloat
) -> ResolvedDwindleSettings {
let useGlobalGaps = override?.useGlobalGaps ?? dwindleUseGlobalGaps
return ResolvedDwindleSettings(
smartSplit: override?.smartSplit ?? dwindleSmartSplit,
defaultSplitRatio: CGFloat(override?.defaultSplitRatio ?? dwindleDefaultSplitRatio),
splitWidthMultiplier: CGFloat(override?.splitWidthMultiplier ?? dwindleSplitWidthMultiplier),
singleWindowFit: override?.singleWindowFit ?? dwindleSingleWindowFit,
useGlobalGaps: useGlobalGaps,
innerGap: useGlobalGaps ? CGFloat(gapSize) : CGFloat(override?.innerGap ?? gapSize)
innerGap: useGlobalGaps ? sharedInnerGap : CGFloat(override?.innerGap ?? gapSize)
)
}

Expand All @@ -1246,7 +1255,11 @@ final class SettingsStore {
}

func updateGapSettings(_ settings: MonitorGapSettings) {
MonitorSettingsStore.update(settings, in: &monitorGapSettings)
if settings.hasOverrides {
MonitorSettingsStore.update(settings, in: &monitorGapSettings)
} else {
MonitorSettingsStore.remove(matching: settings, from: &monitorGapSettings)
}
}

func removeGapSettings(for monitor: Monitor) {
Expand All @@ -1260,13 +1273,18 @@ final class SettingsStore {
func resolvedGapSettings(for monitor: Monitor) -> ResolvedGapSettings {
let override = gapSettings(for: monitor)
return ResolvedGapSettings(
innerGap: resolvedInnerGap(override?.innerGap),
outerGapLeft: CGFloat(override?.outerGapLeft ?? outerGapLeft),
outerGapRight: CGFloat(override?.outerGapRight ?? outerGapRight),
outerGapTop: CGFloat(override?.outerGapTop ?? outerGapTop),
outerGapBottom: CGFloat(override?.outerGapBottom ?? outerGapBottom)
)
}

private func resolvedInnerGap(_ override: Double?) -> CGFloat {
CGFloat(min(64, max(0, override ?? gapSize)))
}

nonisolated static let defaultColumnWidthPresets: [Double] = BuiltInSettingsDefaults.niriColumnWidthPresets

static func validatedPresets(_ presets: [Double]) -> [Double] {
Expand Down
4 changes: 2 additions & 2 deletions Sources/OmniWM/Core/Controller/CommandHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ final class CommandHandler {
var state = controller.workspaceManager.niriViewportState(for: workspaceId)
let motion = controller.motionPolicy.snapshot()
let workingFrame = controller.insetWorkingFrame(for: monitor)
let gaps = CGFloat(controller.workspaceManager.gaps)
let gaps = controller.innerGap(for: monitor)

let previousWindow = controller.workspaceManager.withEngineMutationScope { () -> NiriWindow? in
if let currentId = state.selectedNodeId {
Expand Down Expand Up @@ -543,7 +543,7 @@ final class CommandHandler {
return
}

let gap = CGFloat(controller.workspaceManager.gaps)
let gap = controller.innerGap(for: monitor)
let workingFrame = controller.insetWorkingFrame(for: monitor)
let motion = controller.motionPolicy.snapshot()
guard let newNode = controller.workspaceManager.withEngineMutationScope(label: "focus_navigation", {
Expand Down
4 changes: 3 additions & 1 deletion Sources/OmniWM/Core/Controller/DwindleLayoutHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1017,9 +1017,11 @@ import QuartzCore
) {
guard let controller,
let engine = controller.dwindleEngine,
let wsId = controller.activeWorkspace()?.id
let wsId = controller.activeWorkspace()?.id,
let monitor = controller.workspaceManager.monitor(for: wsId)
else { return }
controller.workspaceManager.withEngineMutationScope {
applyResolvedSettings(controller.settings.resolvedDwindleSettings(for: monitor), to: engine)
perform(engine, wsId)
}
}
Expand Down
16 changes: 8 additions & 8 deletions Sources/OmniWM/Core/Controller/MouseEventHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ final class MouseEventHandler {
return
}
let workingFrame = controller.insetWorkingFrame(for: monitor)
let gaps = CGFloat(controller.workspaceManager.gaps)
let gaps = controller.innerGap(for: monitor)
controller.workspaceManager.withNiriViewportState(for: workspaceId) { viewportState in
engine.interactiveResizeEnd(
motion: controller.motionPolicy.snapshot(),
Expand Down Expand Up @@ -765,7 +765,7 @@ final class MouseEventHandler {
let monitor = controller.workspaceManager.monitor(for: wsId)
{
let workingFrame = controller.insetWorkingFrame(for: monitor)
let gaps = CGFloat(controller.workspaceManager.gaps)
let gaps = controller.innerGap(for: monitor)

let isInsertMode = modifiers.contains(.maskShift)
var moveStarted = false
Expand Down Expand Up @@ -942,7 +942,7 @@ final class MouseEventHandler {
targetWindowId: nodeId,
position: insertPosition,
in: wsId,
gaps: CGFloat(controller.workspaceManager.gaps)
gaps: controller.innerGap(for: wsId)
) {
state.dragGhostController?.showSwapTarget(frame: dropFrame)
}
Expand Down Expand Up @@ -980,8 +980,8 @@ final class MouseEventHandler {
}

let gaps = LayoutGaps(
horizontal: CGFloat(controller.workspaceManager.gaps),
vertical: CGFloat(controller.workspaceManager.gaps),
horizontal: controller.innerGap(for: monitor),
vertical: controller.innerGap(for: monitor),
outer: controller.workspaceManager.outerGaps
)
let insetFrame = controller.insetWorkingFrame(for: monitor)
Expand Down Expand Up @@ -1014,7 +1014,7 @@ final class MouseEventHandler {
let wsId = move.workspaceId
if let monitor = controller.workspaceManager.monitor(for: wsId) {
let workingFrame = controller.insetWorkingFrame(for: monitor)
let gaps = CGFloat(controller.workspaceManager.gaps)
let gaps = controller.innerGap(for: monitor)
let movedToken = move.windowHandle.id
var didEnd = false
controller.workspaceManager.withNiriViewportState(for: wsId) { vstate in
Expand Down Expand Up @@ -1613,7 +1613,7 @@ final class MouseEventHandler {
) {
guard let controller else { return }
let insetFrame = controller.insetWorkingFrame(for: monitor)
let gap = CGFloat(controller.workspaceManager.gaps)
let gap = controller.innerGap(for: monitor)
let step = ticks > 0 ? 1 : -1
let motion = controller.motionPolicy.snapshot()

Expand Down Expand Up @@ -1682,7 +1682,7 @@ final class MouseEventHandler {

let insetFrame = controller.insetWorkingFrame(for: monitor)
let columns = engine.columns(in: wsId)
let gap = CGFloat(controller.workspaceManager.gaps)
let gap = controller.innerGap(for: monitor)
let scale = NSScreen.screens.first(where: { $0.displayId == monitor.displayId })?
.backingScaleFactor ?? 2.0

Expand Down
18 changes: 9 additions & 9 deletions Sources/OmniWM/Core/Controller/NiriLayoutHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ enum StructuralMutationOutcome: Equatable {
hasCompletedInitialRefresh: controller.layoutRefreshController.layoutState.hasCompletedInitialRefresh,
useScrollAnimationPath: useScrollAnimationPath,
removalSeed: removalSeed,
gap: CGFloat(controller.workspaceManager.gaps),
gap: controller.innerGap(for: monitor),
outerGaps: controller.workspaceManager.outerGaps,
displayRefreshRate: controller.layoutRefreshController.layoutState
.refreshRateByDisplay[monitor.displayId] ?? 60.0,
Expand Down Expand Up @@ -1310,7 +1310,7 @@ enum StructuralMutationOutcome: Equatable {
var state = controller.workspaceManager.niriViewportState(for: workspaceId)
controller.workspaceManager.withEngineMutationScope {
if let monitor = controller.workspaceManager.monitor(for: workspaceId) {
let gap = CGFloat(controller.workspaceManager.gaps)
let gap = controller.innerGap(for: monitor)
engine.ensureSelectionVisible(
node: target,
in: workspaceId,
Expand Down Expand Up @@ -1391,7 +1391,7 @@ enum StructuralMutationOutcome: Equatable {
}

guard let monitor = controller.workspaceManager.monitor(for: wsId) else { return false }
let gap = CGFloat(controller.workspaceManager.gaps)
let gap = controller.innerGap(for: monitor)
let workingFrame = controller.insetWorkingFrame(for: monitor)

let newNode = controller.workspaceManager.withEngineMutationScope { () -> NiriNode? in
Expand Down Expand Up @@ -1794,7 +1794,7 @@ enum StructuralMutationOutcome: Equatable {
}

if options.ensureVisible, let monitor = controller.workspaceManager.monitor(for: workspaceId) {
let gap = CGFloat(controller.workspaceManager.gaps)
let gap = controller.innerGap(for: monitor)
let workingFrame = controller.insetWorkingFrame(for: monitor)
engine.ensureSelectionVisible(
node: node,
Expand Down Expand Up @@ -1860,7 +1860,7 @@ enum StructuralMutationOutcome: Equatable {
return
}

let gap = CGFloat(controller.workspaceManager.gaps)
let gap = controller.innerGap(for: monitor)
let workingFrame = controller.insetWorkingFrame(for: monitor)
let orientation = engine.monitor(for: monitor.id)?.orientation
?? controller.settings.effectiveOrientation(for: monitor)
Expand Down Expand Up @@ -1948,7 +1948,7 @@ enum StructuralMutationOutcome: Equatable {

let workspaceId = entry.workspaceId
let workingFrame = controller.insetWorkingFrame(for: monitor)
let gaps = CGFloat(controller.workspaceManager.gaps)
let gaps = controller.innerGap(for: monitor)
let context = NiriOperationContext(
controller: controller,
engine: engine,
Expand Down Expand Up @@ -2113,7 +2113,7 @@ enum StructuralMutationOutcome: Equatable {
guard let controller, let engine = controller.niriEngine else { return }
guard let monitor = controller.workspaceManager.monitor(for: workspaceId) else { return }
let workingFrame = controller.insetWorkingFrame(for: monitor)
let gaps = CGFloat(controller.workspaceManager.gaps)
let gaps = controller.innerGap(for: monitor)
var targetState = controller.workspaceManager.niriViewportState(for: workspaceId)

var consumed = false
Expand Down Expand Up @@ -2419,7 +2419,7 @@ enum StructuralMutationOutcome: Equatable {
guard let monitor = controller.workspaceManager.monitor(for: wsId) else { return }
let motion = controller.motionPolicy.snapshot()
let workingFrame = controller.insetWorkingFrame(for: monitor)
let gaps = CGFloat(controller.workspaceManager.gaps)
let gaps = controller.innerGap(for: monitor)
controller.workspaceManager.withNiriViewportState(for: wsId) { state in
perform(engine, wsId, motion, &state, monitor, workingFrame, gaps)
}
Expand All @@ -2442,7 +2442,7 @@ enum StructuralMutationOutcome: Equatable {
guard let monitor = controller.workspaceManager.monitor(for: workspaceId) else { return }
let motion = controller.motionPolicy.snapshot()
let workingFrame = controller.insetWorkingFrame(for: monitor)
let gaps = CGFloat(controller.workspaceManager.gaps)
let gaps = controller.innerGap(for: monitor)
controller.workspaceManager.withNiriViewportState(for: workspaceId) { state in
perform(engine, workspaceId, motion, &state, monitor, workingFrame, gaps)
}
Expand Down
Loading