From 3bf3aa1989403fdd6c1c7106c98b3af5fce0d078 Mon Sep 17 00:00:00 2001 From: hzhang Date: Fri, 22 May 2026 23:00:02 +0100 Subject: [PATCH] chore: P0 skeleton Bootstrap the Dashward repo per arch/UBUNTU-DASHBOARD-SPACE.md: - pnpm-workspaces monorepo (sdk, extension, container, widgets-builtin/*) - GNOME extension stub (metadata.json, src/*.ts placeholders for warden, guard, supervisor, entry UX, DBus service) - WebKit container stub (GJS main + page-side runtime + dashboard.html) - TypeScript widget SDK (defineWidget + types) - Builtin clock widget as the first SDK consumer example - DBus interface XML (proto/shell.iface.xml) and shared types - esbuild configs for extension and container; tsc for SDK - Design doc copied in at repo root for discoverability No functional logic yet -- all components are placeholders that compose in extension.ts so the build chain can be exercised. P1 (workspace warden) starts next. Co-Authored-By: Claude Opus 4.7 (1M context) --- .editorconfig | 15 + .gitignore | 29 + README.md | 60 ++ UBUNTU-DASHBOARD-SPACE.md | 683 +++++++++++++++++++ container/esbuild.config.js | 34 + container/package.json | 16 + container/runtime/dashboard.html | 12 + container/runtime/runtime.ts | 15 + container/runtime/styles.css | 22 + container/src/bridge.ts | 4 + container/src/dbus-client.ts | 3 + container/src/main.ts | 10 + container/src/window.ts | 4 + container/tsconfig.json | 10 + extension/esbuild.config.js | 28 + extension/metadata.json | 9 + extension/package.json | 16 + extension/src/container-supervisor.ts | 9 + extension/src/dbus-service.ts | 8 + extension/src/entry-ux.ts | 9 + extension/src/extension.ts | 40 ++ extension/src/window-guard.ts | 9 + extension/src/workspace-warden.ts | 9 + extension/tsconfig.json | 10 + extension/widgets-builtin/clock/package.json | 13 + extension/widgets-builtin/clock/src/index.ts | 41 ++ extension/widgets-builtin/clock/widget.json | 10 + package.json | 20 + pnpm-workspace.yaml | 6 + proto/shell.iface.xml | 38 ++ proto/types.ts | 42 ++ scripts/dev-vm.sh | 10 + scripts/lint.sh | 4 + scripts/package.sh | 9 + sdk/package.json | 22 + sdk/src/define-widget.ts | 5 + sdk/src/index.ts | 11 + sdk/src/types.ts | 41 ++ sdk/tsconfig.json | 8 + tsconfig.base.json | 17 + widgets/.gitkeep | 0 41 files changed, 1361 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 README.md create mode 100644 UBUNTU-DASHBOARD-SPACE.md create mode 100644 container/esbuild.config.js create mode 100644 container/package.json create mode 100644 container/runtime/dashboard.html create mode 100644 container/runtime/runtime.ts create mode 100644 container/runtime/styles.css create mode 100644 container/src/bridge.ts create mode 100644 container/src/dbus-client.ts create mode 100644 container/src/main.ts create mode 100644 container/src/window.ts create mode 100644 container/tsconfig.json create mode 100644 extension/esbuild.config.js create mode 100644 extension/metadata.json create mode 100644 extension/package.json create mode 100644 extension/src/container-supervisor.ts create mode 100644 extension/src/dbus-service.ts create mode 100644 extension/src/entry-ux.ts create mode 100644 extension/src/extension.ts create mode 100644 extension/src/window-guard.ts create mode 100644 extension/src/workspace-warden.ts create mode 100644 extension/tsconfig.json create mode 100644 extension/widgets-builtin/clock/package.json create mode 100644 extension/widgets-builtin/clock/src/index.ts create mode 100644 extension/widgets-builtin/clock/widget.json create mode 100644 package.json create mode 100644 pnpm-workspace.yaml create mode 100644 proto/shell.iface.xml create mode 100644 proto/types.ts create mode 100755 scripts/dev-vm.sh create mode 100755 scripts/lint.sh create mode 100755 scripts/package.sh create mode 100644 sdk/package.json create mode 100644 sdk/src/define-widget.ts create mode 100644 sdk/src/index.ts create mode 100644 sdk/src/types.ts create mode 100644 sdk/tsconfig.json create mode 100644 tsconfig.base.json create mode 100644 widgets/.gitkeep diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4250a32 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c39223 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# Build outputs +**/dist/ +**/build/ +*.tsbuildinfo + +# Node +node_modules/ +.pnpm-store/ +npm-debug.log* +pnpm-debug.log* + +# Editor +.idea/ +.vscode/ +*.swp + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log + +# Packaged extension +*.shell-extension.zip + +# Local env / state +.env +.env.local diff --git a/README.md b/README.md new file mode 100644 index 0000000..8006028 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# Dashward + +A dedicated rightmost workspace for custom widgets on Ubuntu/GNOME, in the +spirit of macOS Dashboard. + +- **GNOME Shell extension** (GJS) creates the dashboard workspace, defends + it from regular window incursions, and supervises the container. +- **WebKitGTK container** (separate process) renders an HTML page on that + workspace. +- **Widget SDK** (TypeScript) lets you write widgets as web components. + +Status: P0 skeleton. Design lives in +[`UBUNTU-DASHBOARD-SPACE.md`](https://git.hangman-lab.top/hzhang/Dashward/src/branch/main/UBUNTU-DASHBOARD-SPACE.md) +(see also `~/arch/UBUNTU-DASHBOARD-SPACE.md` locally). + +## Target + +- Ubuntu 25.04 / GNOME Shell 48 / Wayland. +- Other distros & versions: post-v1. + +## Repo layout + +``` +sdk/ TS widget SDK, published as @dashward/widget-sdk +extension/ GNOME Shell extension (GJS, TS-authored) + src/ Extension source + widgets-builtin/ Builtin widgets shipped with the extension +container/ WebKit kiosk process + src/ GJS bootstrap + runtime/ Page-side runtime (host grid, edit mode, widget loader) +widgets/ Example / 3rd-party widget dev tree +proto/ Shared DBus XML + TS types +scripts/ Build & dev helpers +``` + +## Dev setup + +Requires Node ≥ 20 and pnpm ≥ 9. To install pnpm: + +```bash +npm install -g pnpm +``` + +Then: + +```bash +pnpm install +pnpm build +``` + +## Testing discipline + +All Shell-side iteration happens inside the +`ubuntu2504-test` libvirt VM, **never on the host GNOME session** — a +buggy extension can lock you out of the Wayland session. See the design +doc §17 for the dev loop. + +## License + +TBD. diff --git a/UBUNTU-DASHBOARD-SPACE.md b/UBUNTU-DASHBOARD-SPACE.md new file mode 100644 index 0000000..ec7130d --- /dev/null +++ b/UBUNTU-DASHBOARD-SPACE.md @@ -0,0 +1,683 @@ +# Ubuntu Dashboard Space — Design + +Status: design. Goal: a macOS-Dashboard-style **dedicated rightmost workspace** +on GNOME/Ubuntu that hosts user-defined widgets. Widgets are written against +a TypeScript SDK and rendered as web components inside an embedded WebKit +view; the GNOME Shell extension is the workspace warden and the IPC bridge, +nothing heavier. + +Codename: **Dashward** (decided 2026-05-22; see §19). + +--- + +## 1. Goals & non-goals + +### Goals + +- A workspace that is **created by the extension** at enable time, lives at + the rightmost position, and is **destroyed** at disable time. It is not + one of the user's existing workspaces, even temporarily. +- **Regular windows cannot enter it** — neither by overview drag, by + `super+shift+arrow`, by `wmctrl`/`xdotool`, nor by being newly mapped + there. Attempts get bounced to the prior workspace immediately. +- Widgets are **web components in TS**. A buggy widget cannot take down + GNOME Shell. +- Hot-reload during widget development. +- Light/dark theme follows the system. +- Zero hand-edits to user dotfiles outside `~/.local/share/dashward/` and + the extension install dir. + +### Non-goals (v1) + +- Cross-distro support beyond Ubuntu 25.04 / GNOME 48. KDE, XFCE, Cinnamon + are out of scope until v1 lands and stabilizes. +- A widget marketplace, signing, or sandboxing beyond what WebKit's process + model already provides. Widgets are trusted code at v1. +- macOS-style "ripple in" widget add animation. Edit mode is utilitarian. +- Multi-monitor span: dashboard appears on the **primary** monitor only; + other monitors get the regular last-workspace view. +- Replacing the regular workspace switcher UX. The dashboard is reached by a + dedicated gesture/shortcut, not by being workspace N+1 in the existing + switcher. + +--- + +## 2. Hard constraints (carried from chat) + +| C# | Constraint | Resolution | +|---|---|---| +| C1 | Dashboard does **not** reuse any existing workspace | §5: append a new workspace at enable, mark it, remove at disable | +| C2 | Dashboard is **always rightmost** | §5: position invariant maintained on every workspace mutation | +| C3 | Regular windows cannot be **dragged into** dashboard | §6: layered defense on `window-added`, overview drop target, gesture handlers | +| C4 | Widgets in **TypeScript** | §9: SDK is a TS package; widgets are TS modules bundled to ESM | +| C5 | Avoid the GridSpaces lockout failure mode | §17: VM-only iteration loop; extension never touches `gnome-extensions enable` on host until VM-green | + +--- + +## 3. Reality check (probed 2026-05-22 on ubuntu2504-test) + +| Component | Version | Note | +|---|---|---| +| Ubuntu | 25.04 (Plucky) | | +| GNOME Shell | 48.0-1ubuntu1 | ESM extension format | +| Mutter | 48.1 (`libmutter-16-0`) | API gen 16, `Meta.WorkspaceManager` stable | +| gjs | 1.82.1 | SpiderMonkey 128 era — ESM, top-level await OK | +| WebKit2GTK 4.1 (GTK3) | 2.50.4 + `gir1.2-webkit2-4.1` pre-installed | **Chosen** for the container — zero new GIR deps | +| WebKitGTK 6.0 (GTK4) | 2.50.4 lib present, GIR not installed | Migration target post-v1 | +| Session | Wayland (gdm `Ubuntu on Wayland` default) | | +| Pre-existing ext | `ding`, `tiling-assistant`, `ubuntu-appindicators`, `ubuntu-dock` | tiling-assistant is the relevant precedent for window manipulation | + +Implication: we can build v1 with only what's already on disk — no new apt +packages required. (Build chain is in dev only; not shipped onto the VM at +runtime.) + +--- + +## 4. Architecture + +Three processes, two IPC channels: + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ gnome-shell (GJS, in-process) │ +│ ┌──────────────────────────────────────────────────────────────────┐ │ +│ │ Dashward extension │ │ +│ │ • WorkspaceWarden (create/destroy + position invariant) │ │ +│ │ • WindowGuard (block window-added on dashboard ws) │ │ +│ │ • EntryUX (gesture, shortcut, panel indicator) │ │ +│ │ • ContainerSupervisor (spawn/respawn web container, pin window) │ │ +│ │ • DBusService "top.hangmanlab.Dashward.Shell" │ │ +│ └─────────┬────────────────────────────────────────────────────────┘ │ +└────────────┼────────────────────────────────────────────────────────────┘ + │ DBus session bus + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ dashward-container (GJS + WebKit2 4.1, separate process) │ +│ • One GtkWindow, fullscreen, undecorated, app_id = container │ +│ • WebKitWebView loads file://…/dashboard.html │ +│ • DBus client: pushes shell events into the page via │ +│ UserContentManager.evaluate_javascript() │ +│ • UserContentManager script-message handlers receive page→shell calls │ +└─────────────────────────────────────────────────────────────────────────┘ + │ WebKit user-content-manager bridge + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ dashboard.html (WebKit content process, sandboxed by WebKit) │ +│ • Runtime: dashboard-runtime.js (host shell, layout grid, edit mode) │ +│ • SDK: @dashward/widget-sdk (TS, bundled in) │ +│ • Widgets: each loaded into its own