Skip to content

v0.5.7 — Custom layouts, seam drag, dirty-state save

Choose a tag to compare

@ChiFungHillmanChan ChiFungHillmanChan released this 24 Apr 14:34
· 13 commits to main since this release

Custom layouts, seam drag, and a save button that actually works

Three headline changes in V0.5.7. First, user-authored custom layouts: click a slot to split it, drag seams to adjust, save any tile shape you want as a first-class hotkey-bindable layout. Second, companion resize: when Scene has tiled your windows and you drag one edge, the neighbouring tile now follows in real time. Third, the Save button in Settings → Layouts finally behaves — changes persist through layout switches (they didn't before), and the button darkens after a successful save so you can tell it landed.

What's new

  • Build-your-own layouts. Settings → Layouts has a new "+ Custom" toolbar button (the square-on-square icon). Clicking it gives you a blank canvas — click any slot for a menu (split horizontally / split vertically / delete), drag seams to adjust proportions, collapse a slot to merge it with its sibling. Any tile shape is possible: 3-narrow over 2-wide, asymmetric L+4, 7-slot dashboards, whatever your monitor can hold. Saves into the same layouts.json, binds hotkeys alongside built-in templates, fires like any preset.
  • Companion resize when dragging. Drag the edge of any tile in a twoCol / twoRow / threeCol / threeRow layout and the neighbouring tile now shrinks or grows in sympathy — no more leftover gaps. Middle-slot drags in 3-way splits auto-pick whichever edge you grabbed. Hold Option to bypass and let macOS do its native resize without Scene interfering. Custom-tree layouts don't reflow yet (the reflow math is template-axis-based for now; extending it to arbitrary trees is v0.6 work).
  • Save button actually persists and gives visual feedback. Fixed two compounding bugs in Settings → Layouts: (a) the Save button on existing layouts was a silent no-op — changes appeared to apply because the binding auto-wrote to the store on every slider tick, but an .onChange handler reset proportions back to preset defaults the moment you switched layouts, silently wiping customisations on return. The editor now uses a proper @State draft with explicit commit (matching WorkspaceEditorView's pattern). (b) Save is now wired to a dirty-state flag — darkens immediately after a successful save, only re-enables when you edit further. No more guessing whether the save took.
  • Multi-display coordinate fix. Reworked the AX ↔ NSScreen coordinate conversion at the AXWindow wrapper boundary and the drag-swap observer callback. All drag-swap / seam-resize math now runs in a single NSScreen (bottom-left) space, with AX's top-left origin converted exactly once at the wrapper boundary. On multi-display setups where the secondary display sits below or to the left of the primary, drag-swap and seam-resize now target the correct seam instead of landing windows off-screen.

Why this matters

Scene's built-in 11 templates cover the common cases (halves, thirds, quads, L-shapes, main+side) but they can't express "3 narrow tiles on top, 2 equal tiles on bottom" or "L+4 with a rotated main pane" or any of the dozens of asymmetric shapes you might actually want on a 32-inch ultrawide. V0.5.7 removes that ceiling: the split-tree data model lets you compose any binary-partitioned shape, and the canvas editor makes it click-and-drag easy. Companion resize makes every layout feel less like a one-shot snap and more like a live reflowable grid — once you've tiled, pushing an edge reflows everything around it. And the Save button fix closes a real bug that had been silently eating user customisations on every settings visit.

Under the hood

  • New SceneCore types: LayoutNode (indirect enum — leaf, hSplit, vSplit), LayoutReflow (pure seam math), SeamResizeController (AX event handler mirroring DragSwapController's injection pattern), DisplayCoordinates (AX ↔ NSScreen conversion helpers).
  • CustomLayout extension: optional customTree: LayoutNode? field with backward-compatible Codable (legacy layouts.json without the field decodes cleanly; template-only layouts still encode without emitting a customTree key).
  • New SceneApp view: CustomLayoutCanvasEditor — recursive SwiftUI renderer with draggable seams and Menu-driven leaf actions. Built as a sibling to the existing LayoutEditorView; LayoutDraftEditor branches on customTree presence.
  • AXMoveObserverGroup now subscribes to both kAXMovedNotification and kAXResizedNotification and delivers NS-flipped frames to handlers.
  • Tests 177 → 244: added coverage for LayoutReflow, SeamResizeController, LayoutNode (including a verbatim check of the canonical 5-slot example from the design spec), CustomLayout legacy-JSON decode, and DisplayCoordinates round-trip.
  • Hardened runtime, Developer ID signed, Apple notarized + stapled. Universal binary (arm64 + x86_64), minos 14.0.

Install

Homebrew (recommended):

brew upgrade --cask scene                         # existing users — installs V0.5.7 via V0.5.6's in-app installer path if you're on 0.5.6+, otherwise replaces the bundle
brew install --cask chifunghillmanchan/tap/scene  # new users

DMG: download Scene-0.5.7.dmg below, double-click, drag into Applications. Universal — works on Apple Silicon and Intel.

Upgrade notes

  • From V0.5.6+: the in-app update installer handles everything. Click "Update available" in the menu → "Install and Restart" → Scene downloads, verifies the signature, replaces itself, relaunches. Accessibility grant survives automatically.
  • Existing layouts are preserved. The new customTree field is optional and additive — your V0.5.6 layouts.json decodes unchanged on first launch of V0.5.7, and template-only layouts never emit the new key so downgrading is also safe.
  • Custom layouts can't be reflowed by seam-drag yet. The companion-resize feature covers twoCol / twoRow / threeCol / threeRow only for this release. If you drag the edge of a window inside a custom-tree layout, the neighbour doesn't follow. Tracked for a future release.
  • Multi-display fix: if you had windows landing off-screen during drag-swap on a secondary display below / left of your primary, V0.5.7 fixes that. Nothing to do on your end — fire your layout once and everything snaps to the correct targets.