Grid Screen lets you assign desktop windows to zones — predefined screen splits like two columns, three columns, or a main area with a sidebar. Instead of manually dragging and resizing every window, you drag window cards onto a visual canvas and click Arrange. Assignments are submitted to the X11 adapter; actual window movement is currently unverified because of the documented X11 protocol limitation.
Built for general desktop users who want a tidy workspace without learning tiling window managers or memorizing keyboard shortcuts.
- 5 built-in presets — Two Columns, Three Columns, Focus + Stack, Main + Sidebar, 3 Wide Center
- Drag-and-drop canvas — assign windows to zones visually before applying
- Customizable layouts — create and persist two- or three-zone layouts
- X11 arrangement path — select the available X11 root screen and submit assigned windows; actual movement is currently unverified
- Zero network — no telemetry, no analytics, no cloud. Everything stays on your machine
- Lightweight — idle CPU <1%, written in Rust
The repository is configured to build .AppImage and .deb bundles for pushed version tags. Check GitHub Releases for published artifacts; this repository checkout does not establish that one is available.
- Linux with an X11 session (Xorg).
- A window manager with EWMH support (GNOME, KDE Plasma, Xfce — most modern WMs work).
Wayland users: the current Wayland adapter is read-only. It can enumerate some top-level windows but cannot arrange them.
- Open Grid Screen. The Arrange tab shows your running windows on the left.
- Choose a screen and layout from the toolbar.
- Drag window cards from the catalog into the zones on the canvas.
- Click Arrange N windows. All assigned windows are submitted for placement.
- Go to the Layouts tab.
- Click New Layout.
- Give it a name, choose two or three zones, and save.
- Switch to Arrange and select your layout.
- Snap modifier & behavior — stored, but not connected to native snapping
- Start at Login — stored, but does not create an autostart entry
- Minimize to Tray — can hide the window on close; tray lifecycle is not implemented
- System Status — view adapter-reported session and EWMH data
- Rust 1.96+
- Node.js 20+
- Linux system dependencies for Tauri:
sudo apt install libwebkit2gtk-4.1-dev libappindicator3-dev \ librsvg2-dev patchelf libx11-dev libxrandr-dev
git clone https://github.com/enolalabs/grid-screen.git
cd grid-screen
npm installnpm run tauri devnpm run tauri buildProduces .deb and .AppImage in src-tauri/target/release/bundle/.
grid-screen/
├── src/ # Svelte UI
│ ├── components/ # 25 UI components
│ ├── lib/
│ │ ├── stores/ # 8 Svelte stores
│ │ ├── commands.ts # Tauri IPC wrapper
│ │ └── events.ts # Rust → Svelte event listeners
│ └── App.svelte # Root component with tab routing
├── src-tauri/ # Rust application core
│ └── src/
│ ├── main.rs # Tauri entry point & lifecycle
│ ├── app_shell.rs # Tauri commands (bootstrap, arrange, save)
│ ├── layout_engine.rs # Zone rectangle computation
│ ├── arrange_orchestrator.rs # Validate-then-move pipeline
│ ├── platform_adapter.rs # OS abstraction trait
│ ├── x11_adapter.rs # X11/EWMH adapter architecture; XRandR/multi-monitor discovery is not implemented
│ ├── config_store.rs # Atomic JSON persistence
│ ├── window_catalog.rs # Window eligibility filtering
│ └── diagnostics.rs # File-based logging
├── shared-types/ # Rust ↔ TypeScript type definitions
├── mockups/ # UI design mockups (dark, light, pro)
└── docs/ # Design specs & implementation plans
Svelte UI (webview)
↕ Tauri IPC (typed commands + events)
Rust application core
↕ PlatformAdapter trait
X11 adapter (EWMH; XRandR detection is deferred)
The Rust core handles platform communications, layout computation, and config persistence. The Svelte webview handles drag-and-drop state, canvas rendering, and user input. X11 is the only intended movement path, but its actual move/resize behavior is unverified; the Wayland adapter is read-only.
| Layer | Technology |
|---|---|
| Desktop shell | Tauri 2 |
| Application core | Rust |
| UI framework | Svelte 5 + TypeScript |
| X11 integration | x11rb with EWMH window metadata |
| Config persistence | JSON in ~/.config/grid-screen/ |
| Logging | tracing |
| Drag-and-drop | Pointer-event-based (custom implementation) |
Contributions are welcome! Here's how to get started:
- Check the issues — look for
good-first-issueorhelp-wantedlabels - Read the docs — design specs and implementation plans are in
docs/ - Pick a task — comment on the issue to claim it
- Follow the code style — Rust:
cargo fmt+cargo clippy; Svelte:npm run lint - Write tests — Rust:
cargo test; UI: verify component renders correctly - Open a PR — keep it focused, reference the issue, include screenshots for UI changes
- X11 adapter hardening — real window enumeration, EWMH move/resize, edge cases
- Wayland support — implement
PlatformAdapterfor Wayland compositors - Modifier-assisted snap — drag real system windows into zones with a modifier key
- Accessibility — keyboard navigation, screen reader support, ARIA
- Testing — integration tests, X11 test suite, property-based geometry tests