v0.5.7 — Custom layouts, seam drag, dirty-state save
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/threeRowlayout 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
.onChangehandler reset proportions back to preset defaults the moment you switched layouts, silently wiping customisations on return. The editor now uses a proper@State draftwith explicit commit (matchingWorkspaceEditorView'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
AXWindowwrapper 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 mirroringDragSwapController's injection pattern),DisplayCoordinates(AX ↔ NSScreen conversion helpers). - CustomLayout extension: optional
customTree: LayoutNode?field with backward-compatible Codable (legacylayouts.jsonwithout the field decodes cleanly; template-only layouts still encode without emitting acustomTreekey). - New SceneApp view:
CustomLayoutCanvasEditor— recursive SwiftUI renderer with draggable seams and Menu-driven leaf actions. Built as a sibling to the existingLayoutEditorView;LayoutDraftEditorbranches oncustomTreepresence. - AXMoveObserverGroup now subscribes to both
kAXMovedNotificationandkAXResizedNotificationand 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),CustomLayoutlegacy-JSON decode, andDisplayCoordinatesround-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
customTreefield is optional and additive — your V0.5.6layouts.jsondecodes 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/threeRowonly 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.