Zonogy

Zonogy Launcher

This specification describes the Launcher feature for Zonogy - a window switcher and application launcher that integrates with Zonogy’s zone-based window management.

Overview

The Launcher provides a quick way to switch between windows or launch applications, with the launched/selected window being placed into the targeted zone. The Launcher appears as a floating overlay over the currently targeted zone.

Activation

The Launcher opens via:

Dismissal

The launcher dismisses when user:

Further, we don’t want to steal focus from the user’s intended key/active window (recall Launcher is floating frontmost and grabs keyboard input). So the launcher automatically dismisses when:

Positioning

The launcher window should appear:

  1. Centered on the currently targeted zone - The launcher is positioned at the center of the currently targeted zone’s frame. If the zone is too small, the launcher window should extend beyond the zone. The launcher is not user-moveable; it re-centers when the targeted zone changes or the targeted zone’s frame changes (e.g., zone add/remove/resize).
  2. If the targeted zone is the floating zone (which has no visible placeholder), center on the screen containing the floating zone

User Interface

Visual Design

The launcher window should be a floating panel that stays above all other windows. It should have an elegant, professional appearance matching macOS design language:

Layout

  1. Search field at the top - focused immediately when launcher opens
  2. Results list below showing filtered items
  3. Each item row displays:
    • Icon (application icon, window glyph, or file icon)
    • Display name
    • Running indicator (small dot) for running applications
    • Window-in-zone indicator (small window glyph after the name) for running applications whose preferred window is currently placed in a tiling or floating zone. The preferred window is the one that selecting the app would activate (see Window Placement → “If selecting a running app with 1+ managed windows”).
    • Window count (small number next to the expandable indicator) for running applications with one or more managed windows
    • Expandable indicator (“>”) for running applications

Empty State

When no items match the search query, display a friendly empty state message rather than a blank list.

Item Types and Sources

Applications

All applications known to the OS are included, except those listed in ignoredBundleIdentifiers (see main spec’s Configuration section):

Windows

When a running application is selected, the user can drill down to that application’s window list (even when Zonogy currently tracks zero managed windows):

Window Ordering:

Windows not placed in any zone are shown first, then windows in zones. The rationale is that zoned windows are already visible and tiled, so users are more likely to want to select a window that is not currently in a zone.

Within each group, windows are ordered by recency (most recently active first). Zonogy tracks when each managed window becomes active. Windows without recency data fall back to Zonogy ID order (discovery order), which typically places the main window first.

Files and Directories

Users can extend the searchable list via configuration:

Search and Filtering

Fuzzy Matching

Search uses subsequence matching: characters typed must appear in the item name in order, but not necessarily consecutively. Example: “ff” matches “Firefox”. Matching is case-insensitive.

Ranking

For non-empty queries, items are sorted by:

  1. Per-query count (descending): How many times this item was selected for this exact query in the last 5 selections. If count ≥ 3 (majority), the item is guaranteed to rank first regardless of other factors.
  2. Combined score (descending): Weighted blend of match quality (70%) and recency (30%):
    • Match quality (0.0–1.0): Scored based on how well the query matches the item name or alias:
      • Exact alias match: Query exactly matches an item’s configured alias (case-insensitive) → 1.0
      • Word boundary bonus: Matches at start of string or after whitespace score highest
      • Delimiter bonus: Matches after -, _, ., / score well
      • CamelCase bonus: Matches at uppercase letters following lowercase
      • Consecutive bonus: Consecutive matched characters score higher than scattered matches
      • Gap penalty: Gaps between matched characters reduce score
    • Recency score (0.0–1.0): 1 / (1 + 0.03 × rank) where rank is position in Zonogy’s app recency list. Apps never used are treated as rank 50.
    • Formula: 0.7 × matchQuality + 0.3 × recencyScore
  3. Alphabetical: case-insensitive name (tiebreaker).

When query is empty, ranking uses recency then alphabetical.

History Persistence

Persisted to ~/Library/Application Support/Zonogy/launcher-history.json:

Keyboard Navigation

Option Mode

While the Launcher is open in app-list mode and Option is held, each application row replaces its [window count] > chevron with a non-interactive “+” badge. Releasing Option restores the chevron. Selecting an application row (Enter or click) while Option is held opens a new window of that app in the targeted zone instead of performing the default action (for running apps Zonogy activates the app and simulates a Cmd-N keystroke; for non-running apps Zonogy launches the app). Option mode only affects application rows; file and folder rows are unchanged. No effect in the window list mode.

Mouse Interaction

Shortcut Forwarding

Certain keyboard shortcuts are forwarded to the menu bar owner app (the frontmost non-Zonogy application) so users can issue common commands while the Launcher is visible: Cmd-N (new window), Cmd-Shift-N (new private window), Cmd-O (open), and Cmd-Q (quit).

Window List Mode

When drilling into an application’s windows:

  1. The list is replaced with that application’s managed windows (which may be empty)
  2. Search field is cleared
  3. If at least one window exists, the first actual window is selected (not the app header); otherwise the app header (Menu Bar entry) is selected
  4. Same fuzzy matching applies to window titles; when searching, windows are ranked by match quality with recency order as the tie-breaker

App Header Entry:

After Selection

After selecting any item via Enter:

Integration with Zonogy Window Management

Window Placement

When the user selects a window or launches an application:

  1. If selecting an existing window:
    • If minimized: resize/position to the eventual placement frame before unminimizing for smooth animation (see “Accessibility API Workarounds” in SPECIFICATION.md). Then place using standard Zonogy placement rules.
    • If not minimized: move the window using standard Zonogy placement rules (if not already there)
    • Uses the targeted zone for placement
  2. If selecting a running app with 1+ managed windows:
    • Selects the preferred window and treats as window selection (zone placement as above)
    • Main window apps (hasMainWindow: true in config): selects window with lowest CGWindowID
    • Other apps (default): selects the same window as drilling down and opening the first window row (not-in-zone first, then recency)
    • Pre-configured main window apps: Mail, Notes, Messages, Calendar, Reminders, Music, Photos
  3. If launching a new application:
    • The new window will be placed into the targeted zone via normal Zonogy window capture
  4. If activating an app header (not a specific window):
    • Use app.activate(options: [.activateIgnoringOtherApps]) without changing window placement

Note: When Launcher moves a window out of its source zone, that zone becoming empty does not trigger the normal “target the emptied zone” or auto-show behaviors—the user’s intended target is preserved.

Configuration

Settings Integration

Launcher settings should integrate with Zonogy’s existing configuration system:

Configuration Files

Custom items config schema:

{
  "items": [
    {
      "path": "/path/to/file/or/directory",
      "alias": "optional alias text"
    },
    {
      "bundleIdentifier": "com.example.app",
      "alias": "optional alias for existing app"
    }
  ]
}

Implementation Notes

Accessibility API Workarounds

Window Configuration

The launcher window should be configured as:

Performance