fix an issue with horizontal window margins not respected

This commit is contained in:
2026-07-12 15:23:22 +02:00
parent 6de06ac8e1
commit 19a8f09e5a
5 changed files with 112 additions and 52 deletions
+51 -12
View File
@@ -488,40 +488,43 @@ private struct DimensionWrapper: Decodable {
@Test func anchorPlacesAtTopEdge() {
let screen = CGRect(x: 0, y: 0, width: 1000, height: 800)
let size = CGSize(width: 1000, height: 30)
let origin = PHThemeWindowAnchor.top.origin(in: screen, size: size, margin: .init())
let origin = PHThemeWindowAnchor.top.origin(in: screen, size: size)
#expect(origin == CGPoint(x: 0, y: 770))
}
@Test func anchorRespectsTopMargin() {
let screen = CGRect(x: 0, y: 0, width: 1000, height: 800)
let size = CGSize(width: 1000, height: 30)
let origin = PHThemeWindowAnchor.top.origin(in: screen, size: size, margin: .init(top: 10))
let rect = PHThemeWindowMargin(top: 10).inset(of: screen)
let origin = PHThemeWindowAnchor.top.origin(in: rect, size: size)
#expect(origin == CGPoint(x: 0, y: 760))
}
@Test func anchorPlacesBottomLeadingCorner() {
let screen = CGRect(x: 0, y: 0, width: 1000, height: 800)
let size = CGSize(width: 200, height: 40)
let origin = PHThemeWindowAnchor.bottomLeading.origin(
in: screen, size: size, margin: .init(bottom: 8, leading: 12)
)
let rect = PHThemeWindowMargin(bottom: 8, leading: 12).inset(of: screen)
let origin = PHThemeWindowAnchor.bottomLeading.origin(in: rect, size: size)
#expect(origin == CGPoint(x: 12, y: 8))
}
@Test func anchorTrailingCentersVertically() {
let screen = CGRect(x: 0, y: 0, width: 1000, height: 800)
let size = CGSize(width: 200, height: 40)
let origin = PHThemeWindowAnchor.trailing.origin(
in: screen, size: size, margin: .init(trailing: 20)
)
let rect = PHThemeWindowMargin(trailing: 20).inset(of: screen)
let origin = PHThemeWindowAnchor.trailing.origin(in: rect, size: size)
#expect(origin == CGPoint(x: 780, y: 380))
}
@Test func anchorCentersOnBothAxesIgnoringMargin() {
@Test func anchorCentersWithinContentRect() {
let screen = CGRect(x: 0, y: 0, width: 1000, height: 800)
let size = CGSize(width: 200, height: 40)
let origin = PHThemeWindowAnchor.center.origin(in: screen, size: size, margin: .init(top: 999))
#expect(origin == CGPoint(x: 400, y: 380))
// `.center` centers within the inset rect: a top margin lifts the center,
// it doesn't ignore the margin.
let rect = PHThemeWindowMargin(top: 100).inset(of: screen)
let origin = PHThemeWindowAnchor.center.origin(in: rect, size: size)
// rect: y [0, 700], midY = 350 350 20 = 330
#expect(origin == CGPoint(x: 400, y: 330))
}
// MARK: - Monitor window/blocks resolver
@@ -625,7 +628,15 @@ private func makeBlocksConfigDir() throws -> URL {
@MainActor
@Test func computeFrameDefaultsToFullScreenTopBar() throws {
let screen = try #require(NSScreen.main)
let theme = try PHTheme.load("voltage")
// A window that omits geometry exercises computeFrame's defaults:
// width 100%, top anchor, no margin a full-screen top bar. Built locally
// (rather than loading the bundled theme) so the test tracks the engine's
// defaults, not the theme file's editorial margins.
let theme = PHTheme(
windows: [PHThemeWindow(name: "default")],
texts: nil,
styles: nil
)
let config = PHConfig(window: "default", blocks: nil, env: nil, monitors: nil)
let blocks = try PHBlock.load(from: "[[block]]\ncommand = \"echo x\"")
let controller = BarController(config: config, screen: screen, theme: theme, blocks: blocks, debug: false)
@@ -655,6 +666,34 @@ private func makeBlocksConfigDir() throws -> URL {
#expect(frame.height == 30)
}
@MainActor
@Test func computeFrameInsetsFullWidthBarByMargins() throws {
// Regression: `width = "100%"` previously ignored leading/trailing margins
// and spanned edge to edge. Margins now inset the content rectangle, so the
// bar spans only between them.
let screen = try #require(NSScreen.main)
let sf = screen.frame
let theme = PHTheme(
windows: [PHThemeWindow(
name: "inset",
width: .percentage(1.0),
anchor: .top,
margin: PHThemeWindowMargin(leading: 20, trailing: 20)
)],
texts: nil,
styles: nil
)
let config = PHConfig(window: "inset", blocks: nil, env: nil, monitors: nil)
let blocks = try PHBlock.load(from: "[[block]]\ncommand = \"echo x\"")
let controller = BarController(config: config, screen: screen, theme: theme, blocks: blocks, debug: false)
let frame = BarWindow.computeFrame(from: controller)
#expect(frame.width == sf.width - 40)
#expect(frame.minX == sf.minX + 20)
#expect(frame.maxX == sf.maxX - 20)
}
// MARK: - PHPaths (config directory cascade)
@Test func pathsCandidatesIncludeAbsoluteXdgFirst() {