Build the Panama Hyprland desktop
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
# Contextual Signal Glass Design
|
||||
|
||||
## Purpose
|
||||
|
||||
Extend the existing focus-session Signal Glass into a quiet, shell-wide status surface. It should acknowledge meaningful desktop transitions without becoming a second notification system or a stream of routine telemetry.
|
||||
|
||||
## Experience
|
||||
|
||||
- Only curated events appear: capture completion, recording transitions, audio-output changes, Bluetooth/KDE Connect connection changes, Night Light changes, focus completion, and privacy-sensitive activity.
|
||||
- Volume adjustments, ordinary clipboard changes, Wi-Fi signal fluctuations, and background health polling do not appear.
|
||||
- Transient events use one compact glass capsule below the clock for roughly three seconds. A newer event replaces an equivalent event, while higher-priority privacy and recording events preempt lower-priority device events.
|
||||
- Events are not retained as history. Actionable events may be clicked; every event may be dismissed.
|
||||
- Focus controls remain the richer, persistent Signal Glass state. A transient event may briefly occupy the surface, after which the focus controls return.
|
||||
- Microphone, camera, screen sharing, and recording show a brief start/stop event. While active, a tiny semantic glyph remains in the right status area. Clicking it opens a compact activity detail card with the responsible activity and a safe stop action when Panama owns that activity.
|
||||
|
||||
## Architecture
|
||||
|
||||
`StatusEvents.qml` is the broker. Producers call `publish(event)`, using stable keys, semantic priority, duration, and an optional action identifier. The broker deduplicates, bounds its queue, expires transient entries, and routes actions without allowing render components to spawn commands.
|
||||
|
||||
`PrivacyState.qml` derives persistent activity from Panama capture state and PipeWire metadata. It publishes transition events through the broker but exposes current booleans independently so the bar never depends on transient UI state.
|
||||
|
||||
`SignalGlass.qml` becomes the only per-screen host. It chooses the current transient event first, then the existing focus-session card. `EventCard.qml` and the extracted `FocusCard.qml` remain presentation-only.
|
||||
|
||||
`ActivityIndicator.qml` renders persistent privacy state beside the existing focus indicator. `ActivityPanel.qml` explains active states and only offers Stop when Panama owns the recording operation.
|
||||
|
||||
## Event Policy
|
||||
|
||||
- `critical`: recording, screen sharing, camera, or microphone transitions; shown immediately.
|
||||
- `important`: screenshots saved, focus completion, and failed user-initiated shell actions.
|
||||
- `ambient`: output-device, Bluetooth, KDE Connect, and Night Light changes.
|
||||
- Equivalent keys replace instead of stacking. The pending queue is capped at four entries and discards the oldest lowest-priority entry first.
|
||||
- Initial service discovery never emits an event. Only transitions after initialization do.
|
||||
- Do Not Disturb suppresses ambient events but not privacy transitions or Panama-owned recording state.
|
||||
|
||||
## Reliability and Performance
|
||||
|
||||
- No visual element animates while idle.
|
||||
- PipeWire privacy discovery is event-triggered where available and falls back to a low-frequency bounded probe; only state transitions repaint UI.
|
||||
- Missing optional commands or malformed service data disable that producer and log one concise warning rather than creating a respawn loop.
|
||||
- A Quickshell reload reconstructs persistent privacy state but does not replay old transient events.
|
||||
|
||||
## Verification
|
||||
|
||||
- Contract tests exercise broker priority, replacement, dismissal, and DND filtering through IPC.
|
||||
- Capture tests prove screenshot and recording transitions emit the intended events.
|
||||
- Activity tests prove persistent glyph state is independent of capsule expiry.
|
||||
- QML lint/runtime logs must contain no new warnings, and visual captures must cover ambient, privacy, recording, focus-restoration, and detail-panel states.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Continuum Scratchpad and Window Actions Design
|
||||
|
||||
## Purpose
|
||||
|
||||
Complete Continuum as a practical GNOME-like window overview: windows can be moved directly between workspaces, closed without first focusing them, and set aside in one global scratchpad shelf.
|
||||
|
||||
## Experience
|
||||
|
||||
- Every window thumbnail is clickable, draggable, and gains a quiet close button on hover or keyboard focus.
|
||||
- Dropping a thumbnail on a workspace card moves it there without leaving the overview.
|
||||
- A global scratchpad shelf sits along the bottom of Continuum. Empty, it is a subtle drop target. Populated, it expands into a horizontal row of live cards.
|
||||
- Dropping a normal window on the shelf sends it to `special:scratch`. Clicking a shelf card restores it to the selected positive workspace, focuses it, and closes Continuum.
|
||||
- `Super+X` continues to toggle the global scratchpad and `Super+Shift+X` continues to send the active window there.
|
||||
- Closing a thumbnail asks Hyprland to close exactly that address and leaves the overview open.
|
||||
- Drag operations have restrained scale/highlight feedback, never continuous decorative animation.
|
||||
|
||||
## Architecture
|
||||
|
||||
`WindowThumbnail.qml` owns pointer drag initiation, hover chrome, and close intent. It emits `activated`, `closeRequested`, and `dragStarted/dragFinished` signals with its toplevel; it does not dispatch compositor commands.
|
||||
|
||||
`WorkspaceCard.qml` becomes a drop destination and forwards window actions to `OverviewBody.qml`. `OverviewBody.qml` is the sole compositor-command boundary for focus, close, workspace moves, and scratchpad moves, keeping address normalization in one place.
|
||||
|
||||
`ScratchpadShelf.qml` renders the special workspace model and provides the global drop target. `ScratchpadCard.qml` reuses the same thumbnail presentation at a compact size.
|
||||
|
||||
The shelf reads the Hyprland workspace whose name is `special:scratch`. Positive workspaces remain the only entries in the filmstrip and search model.
|
||||
|
||||
## Keyboard and Input
|
||||
|
||||
- Left/Right selects workspaces when search is empty.
|
||||
- Enter opens the selected workspace or focused search result.
|
||||
- Delete closes the keyboard-selected window.
|
||||
- Escape closes Continuum.
|
||||
- Pointer dragging never activates a window on release after a successful drag.
|
||||
|
||||
## Failure Handling
|
||||
|
||||
- Missing or stale addresses make the command a no-op and trigger a workspace/toplevel refresh.
|
||||
- If the scratch workspace does not yet exist, the first drop creates it through Hyprland's normal special-workspace move dispatcher.
|
||||
- Closing or moving a window invalidates captures; Continuum refreshes models and recaptures after the compositor reports the change.
|
||||
|
||||
## Verification
|
||||
|
||||
- Static contracts confirm all dispatches are address-scoped and the shelf only targets `special:scratch`.
|
||||
- Live tests create disposable windows, move them across workspaces and into/out of the scratchpad, close only the intended disposable window, and restore the user's prior workspace.
|
||||
- Visual captures cover the empty shelf, populated shelf, workspace drop target, and hover close control.
|
||||
- Existing focus and overview-search tests remain green.
|
||||
@@ -0,0 +1,65 @@
|
||||
# Focus Glass and Continuum Overview Design
|
||||
|
||||
## Outcome
|
||||
|
||||
Panama gains a polished focus-session surface and a GNOME-like workspace overview. The focus surface uses the selected Signal Glass visual language, keeps Command Deck's useful controls, and treats its associated Hyprland workspace as a first-class destination. The overview uses the selected Continuum layout: a workspace filmstrip above a large, spatially familiar active-workspace preview.
|
||||
|
||||
## Focus session behavior
|
||||
|
||||
- A focus session starts with Panama's configurable default duration of 45 minutes and binds to the currently focused positive-numbered Hyprland workspace.
|
||||
- Starting a session enables Do Not Disturb and Caffeine. Panama remembers their prior values and restores them when the session ends.
|
||||
- The session uses a wall-clock deadline rather than decrementing persistent state every second. It therefore survives a Quickshell reload without losing time.
|
||||
- Pause stores the exact remaining duration. Resume creates a new deadline from that stored duration.
|
||||
- The session completes automatically at zero and posts a normal desktop notification through the existing Panama notification server.
|
||||
- End deliberately terminates the session and restores the prior DND and Caffeine values.
|
||||
- Only one focus session exists at a time. Starting again replaces the old session with a fresh session on the current workspace.
|
||||
|
||||
## Signal Glass surface
|
||||
|
||||
- The main capsule is a top-centred blurred glass surface below the bar, carrying Panama's Prism edge, Tokyo Night Moon palette, and event-driven open/close motion.
|
||||
- Its primary row shows the focus icon, workspace label, remaining time, and whether DND and Caffeine are being held.
|
||||
- Clicking the primary row activates the bound workspace and dismisses the capsule without ending the session.
|
||||
- The action row contains Pause or Resume, Workspace, and End.
|
||||
- Workspace opens the Continuum overview with the session's bound workspace selected.
|
||||
- A labelled close button hides the capsule while the session continues.
|
||||
- While a session exists, a compact bar indicator remains visible. Clicking it reopens the capsule, so dismissal never makes the running session undiscoverable.
|
||||
- No focus UI animates while idle. The only periodic update is the once-per-second remaining-time text while a session is running and not paused.
|
||||
|
||||
## Discoverability and controls
|
||||
|
||||
- Quick Settings includes a full-width Focus row. When idle it starts a 45-minute session on the current workspace. When active it shows the remaining time and opens the capsule.
|
||||
- `SUPER+SHIFT+F` performs the same start-or-show action.
|
||||
- A `focus` Quickshell IPC target exposes `start`, `reveal`, `pause`, `workspace`, `overview`, and `end` for launcher integration and diagnostics.
|
||||
|
||||
## Continuum overview
|
||||
|
||||
- The overview keeps the existing full-screen dimmed and blurred layer, Escape behavior, outside-click dismissal, one-shot window captures, and dynamic-workspace support.
|
||||
- A horizontally scrollable workspace filmstrip occupies the top of the surface. It contains every positive-numbered workspace plus the trailing new-workspace affordance.
|
||||
- The focused or requested workspace is rendered as a large preview below the filmstrip. Clicking one of its windows activates that window and closes the overview.
|
||||
- Selecting a workspace in the filmstrip activates it while keeping the overview open, matching GNOME's spatial workflow. Scrolling over the filmstrip moves left or right through workspaces.
|
||||
- Opening from the focus capsule initially selects the session workspace and marks it with a subtle focus-session badge.
|
||||
- A search field filters windows across all positive workspaces by title or application id. Selecting a result activates its workspace and window, then closes the overview.
|
||||
- The overview IPC target can open directly into a search query, enabling deterministic diagnostics and future launcher actions without synthesizing keyboard input.
|
||||
|
||||
## State and boundaries
|
||||
|
||||
- `services/FocusSession.qml` owns session timing, persistence, DND and Caffeine coordination, and workspace activation. Visual modules only call its public functions and render its properties.
|
||||
- `services/ShellState.qml` remains the owner of mutually exclusive overlays and gains only the requested overview workspace id.
|
||||
- `modules/focus/` owns the capsule and bar indicator.
|
||||
- `modules/overview/` owns the Continuum presentation and window search.
|
||||
- Persistent state is stored atomically through Quickshell `FileView` and `JsonAdapter` under `Quickshell.stateDir`; no daemon or new package is required.
|
||||
|
||||
## Failure handling
|
||||
|
||||
- If the persisted workspace no longer exists, direct activation falls back to Hyprland's workspace dispatcher using the stored positive id.
|
||||
- A malformed or absent state file falls back to an inactive session with no user-visible error.
|
||||
- If the shell reloads after the deadline, the session is completed during restoration and its managed DND and Caffeine state is released.
|
||||
- Search and workspace lists tolerate transient null Hyprland objects while IPC state refreshes.
|
||||
|
||||
## Verification
|
||||
|
||||
- Validate the focus state machine with a standalone Quickshell harness using a very short session.
|
||||
- Validate every QML component constructs without warnings against Quickshell 0.3.0.
|
||||
- Exercise start, pause, resume, dismiss, reopen, workspace activation, overview targeting, automatic completion, and manual end through live IPC.
|
||||
- Reload the daily-driver shell and inspect its logs for QML errors.
|
||||
- Capture the capsule, compact indicator, Continuum overview, and search state for visual review.
|
||||
@@ -0,0 +1,75 @@
|
||||
# Panama Settings Design
|
||||
|
||||
## Purpose
|
||||
|
||||
Panama Settings is the native control center for the Panama Hyprland desktop. It gives Gabriel one polished, understandable place to inspect the current desktop and change Panama-owned behavior without editing Lua, QML, JSON, or systemd units by hand.
|
||||
|
||||
The approved visual direction is **Luminous System Settings**: an Apple-like two-pane settings window, rendered with Panama's restrained Prism glass and Tokyo Night Moon palette. It is a real application window, not a transient layer-shell popover.
|
||||
|
||||
## Product boundaries
|
||||
|
||||
Panama Settings owns settings whose source of truth is Panama, Quickshell, or Hyprland. The first release includes:
|
||||
|
||||
- Home summary with the active display, current desktop profile, Night Light, notification/focus state, and startup-service health.
|
||||
- Appearance controls for clock format and bar vitals.
|
||||
- Display policy for game-aware HDR, content-aware VRR, direct scanout, and Night Light.
|
||||
- Desktop controls for dock auto-hide and timing.
|
||||
- A searchable, read-only shortcut reference generated from the established Panama mental model.
|
||||
- Sound entry points that reuse Panama's live PipeWire controls.
|
||||
- Notification, Do Not Disturb, and focus-duration controls.
|
||||
- Startup/service health for Nextcloud, RustDesk, KDE Connect, Hyprpaper, Hypridle, and Vicinae, with safe open/restart actions where appropriate.
|
||||
- An About page with the running Hyprland, Quickshell, and Panama identity.
|
||||
|
||||
Hardware configuration, user accounts, printers, online accounts, and other services owned by Fedora or GNOME remain delegated to GNOME Settings. Panama Settings labels those handoffs and launches the relevant GNOME panel with a one-process `XDG_CURRENT_DESKTOP=GNOME` override. GNOME Settings remains installed and searchable in Vicinae.
|
||||
|
||||
Screen Intelligence remains a separate subsystem with its own capture, recognition, and result lifecycle. Once that subsystem is installed, Settings exposes its real readiness and privacy page rather than duplicating the feature or presenting inactive controls.
|
||||
|
||||
## Interaction model
|
||||
|
||||
`Super+I` opens or raises Panama Settings. The shell also exposes a typed `settings` IPC target with `open`, `toggle`, `close`, and `page(name)` operations. A desktop entry makes Panama Settings searchable in Vicinae alongside GNOME Settings.
|
||||
|
||||
The sidebar is always visible at desktop sizes and contains a search field, category groups, and a quiet system-status footer. Search filters categories and setting labels rather than becoming a command palette.
|
||||
|
||||
The content pane uses a stable header, restrained cards, and rows with labels, concise explanations, and controls aligned to the trailing edge. Changes apply immediately. There is no global Save button.
|
||||
|
||||
## State and architecture
|
||||
|
||||
`config/DesktopPreferences.qml` persists user choices to `Quickshell.stateDir + "/panama-settings.json"` through `FileView` and `JsonAdapter`. Existing consumers continue reading `Settings.qml`; dynamic values in that singleton bind to `DesktopPreferences`, preserving one public configuration surface.
|
||||
|
||||
`services/SystemSettings.qml` is the machine boundary. It reads current monitor and service state, invokes allow-listed Hyprland runtime settings, opens GNOME panels, and reports command failures. UI components never construct arbitrary shell commands.
|
||||
|
||||
The display policy values are persisted and re-applied when the shell starts:
|
||||
|
||||
- Game-aware HDR maps to `render:cm_auto_hdr` with values `0` or `1`.
|
||||
- VRR maps to `misc:vrr` with values `0` or `3`.
|
||||
- Direct scanout maps to `render:direct_scanout` with values `0` or `2`.
|
||||
|
||||
Full-time desktop HDR is informational in this release because it can break screenshots, OBS, Sunshine, and lock-screen capture on the current Hyprland build. It must not be exposed as an unsafe one-click toggle without a tested automatic rollback path.
|
||||
|
||||
`services/ShellState.qml` owns whether the window is open and the requested page. `modules/settings/SettingsWindow.qml` owns the normal application toplevel, which participates in Hyprland's active tiling layout. Presentation components under `modules/settings/` call only public preference or service methods.
|
||||
|
||||
## Visual language
|
||||
|
||||
- Tokyo Night Moon is the only palette.
|
||||
- A faint blue-to-orchid Prism hairline marks the selected category and major surfaces; orchid never appears as a standalone accent.
|
||||
- The window is dense enough to feel professional but leaves generous breathing room around page headers and section groups.
|
||||
- Typography uses Adwaita Sans for interface text and VictorMono Nerd Font only for version strings, dimensions, and key chords.
|
||||
- Motion is event-driven and short. No pulse, shimmer, animated gradient, or idle repaint loop is allowed.
|
||||
- Enabled states use the primary blue, warnings use amber, and destructive/error states use red only when there is an actual problem.
|
||||
|
||||
## Failure handling
|
||||
|
||||
- A malformed or absent preferences file falls back to shipped defaults.
|
||||
- A failed `hyprctl` write restores the previous preference value and surfaces a quiet inline error.
|
||||
- Missing optional applications or services are shown as unavailable, never as a shell error or empty card.
|
||||
- Service refreshes are bounded and user-triggerable; no polling loop runs continuously.
|
||||
- Closing Panama Settings only hides the window. It does not terminate Quickshell or alter another overlay.
|
||||
|
||||
## Verification
|
||||
|
||||
- Exercise preferences through a disposable Quickshell state directory and prove values survive a shell restart.
|
||||
- Verify each display policy emits only its allow-listed numeric `hyprctl keyword` command.
|
||||
- Verify `Super+I`, IPC open/close/page routing, and the searchable desktop entry.
|
||||
- Construct every Settings page without QML warnings.
|
||||
- Exercise live monitor refresh, Night Light, DND, audio controls, service refresh, and GNOME handoffs.
|
||||
- Restart the live shell, inspect logs, and capture Home, Displays, Desktop, and Services pages for visual review.
|
||||
@@ -0,0 +1,70 @@
|
||||
# Screen Intelligence Design
|
||||
|
||||
## Purpose
|
||||
|
||||
Screen Intelligence makes text trapped in pixels feel like normal desktop content. It extends Panama's existing screenshot picker with a local **Read** action for a screen, window, or selection, then presents the result in a focused Prism glass sheet.
|
||||
|
||||
The feature is deliberately local-first. Screen pixels are captured into Panama's cache and processed by Tesseract and ZBar on the workstation. Nothing is uploaded unless the user explicitly chooses Search, Translate, or Open.
|
||||
|
||||
## Interaction model
|
||||
|
||||
- `Super+Shift+S` opens the existing capture picker in Selection + Read mode.
|
||||
- `Print` keeps opening the complete picker, where Screenshot, Record, and Read are peers.
|
||||
- Screen, Window, and Selection continue to use one shared target-selection model.
|
||||
- Committing a Read capture dismisses the picker before taking the final image, then opens a result sheet while recognition runs.
|
||||
- `Escape` dismisses the result and deletes its temporary image.
|
||||
- The result provides selectable text and explicit Copy, Search, and Translate actions.
|
||||
- A detected URL, QR code, or barcode is shown separately. Web URLs can be opened; all detected values can be copied.
|
||||
- A searchable desktop entry opens Read mode without requiring the shortcut.
|
||||
|
||||
## Architecture
|
||||
|
||||
`services/Capture.qml` remains the owner of screen/window/selection geometry and frozen-frame behavior. It gains a third action state, `intelligenceMode`, and delegates committed Read geometry to `services/ScreenIntelligence.qml` only after the capture overlay has unmapped.
|
||||
|
||||
`services/ScreenIntelligence.qml` owns recognition state, process lifecycle, result actions, and cleanup. Its public boundary is:
|
||||
|
||||
- `refresh(): void`
|
||||
- `analyzeRegion(geometry: string, outputName: string): void`
|
||||
- `analyzeFile(path: string): void`
|
||||
- `copyText(): void`
|
||||
- `copyCode(): void`
|
||||
- `search(): void`
|
||||
- `translate(): void`
|
||||
- `openDetected(): void`
|
||||
- `close(): void`
|
||||
|
||||
`scripts/screen-intelligence` is the deterministic machine boundary. `probe` reports engine availability. `analyze-file IMAGE` emits one JSON object containing OCR text, detected code data, and a user-safe error. It never evaluates UI-provided shell text.
|
||||
|
||||
`modules/capture/IntelligenceResult.qml` is a transient overlay, not an application window. It renders a quiet processing state, the selectable result, detected-content card, actions, and actionable failure guidance.
|
||||
|
||||
## Recognition behavior
|
||||
|
||||
- OCR uses the installed English Tesseract language pack.
|
||||
- Tesseract's automatic page-segmentation mode handles both short snippets and larger document regions.
|
||||
- ZBar recognition is additive. A capture can return text, a code, or both.
|
||||
- Empty recognition is not treated as a crash; the sheet explains that no readable text or code was found.
|
||||
- Missing engines produce a precise install command and keep the rest of the shell healthy.
|
||||
- Temporary captures live under `Quickshell.cachePath(...)` and are removed when dismissed or replaced.
|
||||
|
||||
## Visual language
|
||||
|
||||
- The result is a centered Prism glass sheet over a lightly dimmed desktop.
|
||||
- Tokyo Night Moon tokens are the only colors.
|
||||
- Processing uses a static status treatment; there is no spinner, pulse, shimmer, or idle animation.
|
||||
- OCR text is readable interface typography in a selectable editor, not a terminal-like dump.
|
||||
- The primary action is Copy. Network-leaving actions are visually secondary and clearly labelled.
|
||||
|
||||
## Settings and discoverability
|
||||
|
||||
Panama Settings gains a real **Screen Intelligence** page. It shows engine readiness, the `Super+Shift+S` shortcut, the local-processing privacy boundary, and the exact package requirement if recognition is unavailable. The page contains no fake toggles.
|
||||
|
||||
The shortcut reference, Hyprland README, root README, desktop package list, and desktop entry remain in sync.
|
||||
|
||||
## Verification
|
||||
|
||||
- A generated image fixture must be recognized as literal text by the helper.
|
||||
- The live IPC contract must expose readiness, open Read mode, and route the Settings page.
|
||||
- The capture picker must construct with Screenshot, Record, and Read actions without QML warnings.
|
||||
- The result sheet must construct for processing, success, empty, and unavailable states.
|
||||
- Hyprland must register `Super+Shift+S` as Screen Intelligence and pass config verification.
|
||||
- The complete Quickshell contract suite must remain green.
|
||||
Reference in New Issue
Block a user