Skip to content
Merged
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
40 changes: 40 additions & 0 deletions CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,40 @@ duration_ms = 35
| `enabled` | `true` | boolean | Enables visual scrolling and managed resize animation. |
| `duration_ms` | `35` | integer from `0` to `2000` | Animation duration in milliseconds. `0` disables animation even when `enabled = true`. |

## `[overview]`

Controls the Overview scale and optional pixels inside window cards.

```toml
[overview]
zoom = 0.5
window_previews = false
```

| Setting | Default | Values/type | Description |
| --- | --- | --- | --- |
| `zoom` | `0.5` | number from `0` to `0.75` | Scales workspaces and windows. Lower values show more of the neighboring workspaces. |
| `window_previews` | `false` | boolean | Captures a card-sized still image when a window first becomes visible in the current Overview session. |

With the default `false`, Defi performs no Screen Recording permission check,
request, or ScreenCaptureKit content query. With `true`, the next Overview
opening reuses a valid in-memory preview when available, then captures a fresh
image. Denial, revocation, protected content, and capture errors leave the
icon-and-title cards fully usable and do not trigger repeated prompts in the
same daemon session.

Previews are memory-only, contain no audio or cursor, and use at most 16 MiB
between Overview sessions. Defi validates the window and process identity before
reuse, requests a fresh image immediately, and removes the remembered image if
that capture fails. A full-display screen share can include the Overview and the
content shown in its cards; sharing one selected application or window does not
normally include Defi's overlay.

When dragging a tiled card, the outer quarter on either side of a column creates
a neighboring column. Its central half inserts the card into the stack according
to pointer height. The Overview animates the projected ribbons immediately;
native windows receive only the final layout while the overlay is visible.

## `[decorations.borders]`

Controls borders around visible tiled windows.
Expand Down Expand Up @@ -311,6 +345,7 @@ an entry from `[workspaces].names`.
| `join-window left` | Join focused window into stack on left. | `<mod>-semicolon` |
| `join-window right` | Join focused window into stack on right. | `<mod>-quote` |
| `unjoin-windows` | Split focused window from stack into new column. | `<mod>-r` |
| `toggle-overview` | Open or close the interactive workspace Overview. | `<mod>-o` |
| `diagnostic-mark` | Record current status and recent trace without changing managed windows. | unset |

`previous` may be written as `prev`. `focus-column` also accepts
Expand Down Expand Up @@ -436,6 +471,10 @@ enabled = true
enabled = true
duration_ms = 35

[overview]
zoom = 0.5
window_previews = false

[decorations.borders]
enabled = true
width = 4
Expand All @@ -456,6 +495,7 @@ default = "1"
"alt-right" = "focus-column right"
"alt-up" = "focus-window up"
"alt-down" = "focus-window down"
"alt-o" = "toggle-overview"
"alt-leftbracket" = "focus-column first"
"alt-rightbracket" = "focus-column last"

Expand Down
15 changes: 15 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@ The offscreen placement of windows from inactive workspaces without hiding or
minimizing them.
_Avoid_: Hiding, minimizing

**Overview**:
An interactive stack of full-width workspace ribbons. Each ribbon shows a
uniformly scaled view of its scrolling strip and exposes normal navigation and
window movement.

**Overview viewport**:
The temporary two-axis view into an Overview. Moving it does not change native
window frames or a workspace's scrolling offset.
_Avoid_: Workspace scroll offset

**Window preview**:
A non-authoritative captured image of a managed window shown in the Overview.
Its absence or staleness never changes Overview behavior.
_Avoid_: Live window, window mirror, screenshot

## Focus and responsiveness

**Human focus intent**:
Expand Down
10 changes: 10 additions & 0 deletions Sources/DefiConfig/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public struct Config: Equatable, Sendable {
public var input: InputConfig
public var layout: LayoutConfig
public var animation: AnimationConfig
public var overview: OverviewConfig
public var decorations: DecorationsConfig
public var menuBar: MenuBarConfig
public var workspaces: WorkspacesConfig
Expand All @@ -18,6 +19,7 @@ public struct Config: Equatable, Sendable {
input: InputConfig = InputConfig(),
layout: LayoutConfig = LayoutConfig(),
animation: AnimationConfig = AnimationConfig(),
overview: OverviewConfig = OverviewConfig(),
decorations: DecorationsConfig = DecorationsConfig(),
menuBar: MenuBarConfig = MenuBarConfig(),
workspaces: WorkspacesConfig = WorkspacesConfig(),
Expand All @@ -29,6 +31,7 @@ public struct Config: Equatable, Sendable {
self.input = input
self.layout = layout
self.animation = animation
self.overview = overview
self.decorations = decorations
self.menuBar = menuBar
self.workspaces = workspaces
Expand All @@ -49,6 +52,7 @@ public struct Config: Equatable, Sendable {
input: raw.input ?? InputConfig(),
layout: raw.layout ?? LayoutConfig(),
animation: raw.animation ?? AnimationConfig(),
overview: raw.overview ?? OverviewConfig(),
decorations: raw.decorations ?? DecorationsConfig(),
menuBar: raw.menuBar ?? MenuBarConfig(),
workspaces: workspaces,
Expand Down Expand Up @@ -114,6 +118,9 @@ public struct Config: Equatable, Sendable {
guard (0...2_000).contains(animation.durationMS) else {
throw ConfigError.invalidValue("animation.duration_ms")
}
guard overview.zoom.isFinite, (0...0.75).contains(overview.zoom) else {
throw ConfigError.invalidValue("overview.zoom")
}
guard (0...64).contains(decorations.borders.width) else {
throw ConfigError.invalidValue("decorations.borders.width")
}
Expand Down Expand Up @@ -220,6 +227,7 @@ public struct Config: Equatable, Sendable {
"\(modifier)-semicolon": "join-window left",
"\(modifier)-quote": "join-window right",
"\(modifier)-r": "unjoin-windows",
"\(modifier)-o": "toggle-overview",
]
for (index, workspace) in workspaceNames.prefix(9).enumerated() {
let number = index + 1
Expand Down Expand Up @@ -250,6 +258,7 @@ private struct RawConfig: Decodable {
var input: InputConfig?
var layout: LayoutConfig?
var animation: AnimationConfig?
var overview: OverviewConfig?
var decorations: DecorationsConfig?
var menuBar: MenuBarConfig?
var workspaces: WorkspacesConfig?
Expand All @@ -262,6 +271,7 @@ private struct RawConfig: Decodable {
case input
case layout
case animation
case overview
case decorations
case menuBar = "menu_bar"
case workspaces
Expand Down
22 changes: 22 additions & 0 deletions Sources/DefiConfig/ConfigModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,28 @@ public struct AnimationConfig: Codable, Equatable, Sendable {
}
}

public struct OverviewConfig: Codable, Equatable, Sendable {
public var zoom: Double
public var windowPreviews: Bool

public init(zoom: Double = 0.5, windowPreviews: Bool = false) {
self.zoom = zoom
self.windowPreviews = windowPreviews
}

enum CodingKeys: String, CodingKey {
case zoom
case windowPreviews = "window_previews"
}

public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
zoom = try values.decodeIfPresent(Double.self, forKey: .zoom) ?? 0.5
windowPreviews =
try values.decodeIfPresent(Bool.self, forKey: .windowPreviews) ?? false
}
}

public struct LayoutConfig: Codable, Equatable, Sendable {
public var defaultColumnWidth: Double
public var presetColumnWidths: [Double]
Expand Down
Loading